Ajax-ajax实例3-动态树形列表

项目结构:

项目演示:

技术要点:

1.3.2 技术要点
在基本原理的介绍中,了解到通过在父节点内动态创建子节点,并利用样式表缩进完成树形列表
的基本框架。除了这一点外,还有下面一些问题需要考虑。
1 .将父节点所有的子节点放入一个容器中
基本原理页面中仅包含了创建子节点的功能,不可以将创建好的节点再进行关闭操作。实际应用
中菜单总是包含打开和关闭两种操作。为了方便进行关闭操作,将子节点放入一个容器中,在关闭时
只需要设置容器的显示属性即可。
2 .节点开关的具体实现
每个父节点的所有子节点放入容器中后,在单击父节点时判断子节点容器的显示状态。如果当前
为打开状态,则将其关闭,反之则将其打开。具体使用的方法是调用节点的 style.display 属性进行判断,
关闭时的状态为 none,非 none 时表示打开。为了清晰地表示父节点的打开或关闭状态,使用“+”和
“-”字符进行标识。
3 .节点分为目录节点和非目录节点
目录节点下可包含子节点,非目录节点也可称为叶子节点,即该节点不包含子节点。在本例中对
这两种节点进行区别对待。单击目录节点将对其子节点进行展开或关闭操作。单击非目录节点将链接
到新的页面(目前暂时将新页面地址弹出,在实际应用中可进行修改)。

数据库:

CREATE TABLE `tree` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT ‘主键‘,
  `text` varchar(255) NOT NULL COMMENT ‘显示文本‘,
  `isfolder` varchar(5) NOT NULL DEFAULT ‘false‘ COMMENT ‘是否含有下级目录‘,
  `link` varchar(255) NOT NULL COMMENT ‘连接‘,
  `pid` int(11) NOT NULL DEFAULT ‘0‘ COMMENT ‘父id‘,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8

GetTreeByParentId.java:获取节点信息servlet:

package com.gordon.servlet;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.gordon.util.DBUtils;

/**
 * Servlet implementation class GetTreeByParentId
 */
@WebServlet("/GetTreeByParentId")
public class GetTreeByParentId extends HttpServlet {
	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public GetTreeByParentId() {
		super();
		// TODO Auto-generated constructor stub
	}

	/**
	 * @see Servlet#init(ServletConfig)
	 */
	public void init(ServletConfig config) throws ServletException {
		// TODO Auto-generated method stub
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		request.setCharacterEncoding("utf-8");
		response.setContentType("text/xml;charset=utf-8");

		String parentId = request.getParameter("parentId"); // 获取要加载的节点编号
		// 创建用于保存 xmlTree 信息的 StringBuffer 对象
		StringBuffer xmlTree = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
		xmlTree.append("<tree>"); // xmlTree 根节点为<tree>
		/*
		 * 根据请求的目标节点返回不同的结果 isFolder 属性标识当前节点是否为目录,true 表示目录,false 表示普通节点 link
		 * 属性用于设置普通节点的目标链接地址
		 */
		String sql = "select * from tree where pid = ?"; // 定义查询数据库的 SQL 语句
		Connection conn = null; // 声明 Connection 对象
		PreparedStatement pstmt = null; // 声明 PreparedStatement 对象
		ResultSet rs = null; // 声明 ResultSet 对象
		try {
			conn = DBUtils.getConnection(); // 获取数据库连接
			pstmt = conn.prepareStatement(sql); // 创建 PreparedStatement
			pstmt.setString(1, parentId); // 设置参数
			rs = pstmt.executeQuery(); // 执行查询,返回结果集
			while (rs.next()) { // 遍历结果集创建 item 节点
				xmlTree.append("<item id=\"");
				xmlTree.append(rs.getString("id"));
				xmlTree.append("\" isFolder=\"");
				xmlTree.append(rs.getString("isfolder"));
				String link = rs.getString("link");
				// 当 link 字段数据存在时才加入 link 属性信息
				if (link != null && !"".equals(link)) {
					xmlTree.append("\" link=\"");
					xmlTree.append(link);
				}
				xmlTree.append("\">");
				xmlTree.append(rs.getString("text"));
				xmlTree.append("</item>");
			}
		} catch (ClassNotFoundException cnfe) {
			System.out.println(cnfe.toString());
		} catch (SQLException e) {
			System.out.println(e.toString());
		}

		try {
			rs.close(); // 关闭结果集
			pstmt.close(); // 关闭 PreparedStatement
			conn.close(); // 关闭连接
		} catch (Exception e) {
			System.out.println(e.toString());
		}

		xmlTree.append("</tree>"); // xmlTree 根节点的结束标签

		System.out.println(xmlTree.toString());

		response.getWriter().print(xmlTree.toString());
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

DBUtil.java:数据库连接:

package com.gordon.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DBUtils {
	private static final String URL = "jdbc:mysql://localhost:3306/ajaxexample_3";
	private static final String DRIVER = "com.mysql.jdbc.Driver";
	private static final String USERNAME = "root";
	private static final String PASSWORD = "root";

	public static Connection getConnection() throws ClassNotFoundException, SQLException {
		Class.forName(DRIVER);
		return DriverManager.getConnection(URL, USERNAME, PASSWORD);
	}
}

tree.css:

/* 子节点容器 box 需要缩进 */
div.box {
	margin-left: 20px;
}
/* 目录节点标识样式 */
span.folderMark {
	font-family: "宋体";
	color: #F00;
	cursor: hand;
	margin-right: 5px;
}
/* 目录节点样式 */
span.folder {
	cursor: hand;
}
/* 非目录节点标识样式 */
span.itemMark {
	font-family: "宋体";
	color: #F00;
	margin-right: 5px;
}
/* 非目录节点样式 */
span.item {
	cursor: hand;
}

tree.js:

// 创建Tree对象
var Tree = new function() {
	this._url = "GetTreeByParentId"; // 用于请求数据的服务器页面地址

	this._openMark = "-"; // 目录节点处于展开状态时的标识
	this._closeMark = "+"; // 目录节点处于关闭状态时的标识
	this._itemMark = "·"; // 非目录节点标识

	this._initId = "treeInit"; // 树形目录初始 div 标识
	this._rootData = "根目录"; // 根节点文字信息

	this._boxSuffix = "_childrenBox"; // 子节点容器后缀

	this._folderType = "folder"; // 目录节点类型变量
	this._itemType = "item"; // 非目录节点类型变量

	// 初始化根节点
	this.init = function() {
		var initNode = document.getElementById(this._initId); // 获取初始 div
		var _node = document.createElement("div"); // 创建新 div 作为根节点

		_node.id = "0"; // 根节点 id 为 0
		_node.innerHTML = this.createItemHTML(_node.id, this._folderType,
				this._rootData);
		initNode.appendChild(_node); // 将根节点加入初始 div
	}

	// 获取给定节点的子节点
	this.getChildren = function(_parentId) {
		// 获取页面子节点容器 box
		var childBox = document.getElementById(_parentId + this._boxSuffix);
		// 如果子节点容器已存在,则直接设置显示状态,否则从服务器获取子节点信息
		if (childBox) {
			var isHidden = (childBox.style.display == "none"); // 判断当前状态是否隐藏
			// 隐藏则显示,如果显示则变为隐藏
			childBox.style.display = isHidden ? "" : "none";
			// 根据子节点的显示状态修改父节点标识
			var _parentNode = document.getElementById(_parentId);
			_parentNode.firstChild.innerHTML = isHidden ? this._openMark
					: this._closeMark;
		} else {
			var xmlHttp = this.createXmlHttp(); // 创建 XmlHttpRequest 对象
			xmlHttp.onreadystatechange = function() {
				if (xmlHttp.readyState == 4) {
					// 调用 addChildren 函数生成子节点
					Tree.addChildren(_parentId, xmlHttp.responseXML);
				}
			}
			xmlHttp.open("GET", this._url + "?parentId=" + _parentId, true);
			xmlHttp.send(null);
		}
	}

	// 根据获取的 xmlTree 信息,设置指定节点的子节点
	this.addChildren = function(_parentId, _data) {
		var _parentNode = document.getElementById(_parentId); // 获取父节点
		_parentNode.firstChild.innerHTML = this._openMark;// 设置节点前标记为目录展开形式
		// 创建一个容器,称为 box,用于存放所有子节点
		var _nodeBox = document.createElement("div");
		// 容器的 id 规则为:在父节点 id 后加固定后缀
		_nodeBox.id = _parentId + this._boxSuffix;
		_nodeBox.className = "box"; // 样式名称为 box,div.box 样式会对此节点生效
		_parentNode.appendChild(_nodeBox); // 将子节点 box 放入父节点中
		// 获取所有 item 节点
		var _children = _data.getElementsByTagName("tree")[0].childNodes;

		var _child = null; // 声明_child 变量用于保存每个子节点
		var _childType = null; // 声明_childType 变量用于保存每个子节点类型
		for (var i = 0; i < _children.length; i++) { // 循环创建每个子节点
			_child = _children[i];
			_node = document.createElement("div"); // 每个节点对应一个新 div
			_node.id = _child.getAttribute("id"); // 节点的 id 值就是获取数据中的 id 属性值
			// 设置子节点类型
			_childType = _child.getAttribute("isFolder") == "true" ? this._folderType
					: this._itemType;
			// 根据节点类型不同,调用 createItemHTML 创建节点内容
			if (_childType == this._itemType) {
				// 非目录节点在最后多传一个 link 数据,用于单击后链接到新页面
				_node.innerHTML = this.createItemHTML(_node.id, _childType,
						_child.firstChild.data, _child.getAttribute("link"));
			} else {
				// 目录节点只需传递 id,节点类型,节点数据
				_node.innerHTML = this.createItemHTML(_node.id, _childType,
						_child.firstChild.data);
			}
			_nodeBox.appendChild(_node); // 将创建好的节点加入子节点 box 中
		}
	}

	// 创建节点的页面片断
	this.createItemHTML = function(itemId, itemType, itemData, itemLink) {
		// 根据节点类型不同,返回不同的 HTML 片断
		if (itemType == this._itemType) {
			// 非目录节点的 class 属性以 item 开头,并且 onclick 事件调用 Tree.clickItem 函数
			return ‘<span class="itemMark">‘ + this._itemMark + ‘</span>‘
					+ ‘<span class="item" onclick="Tree.clickItem(\‘‘
					+ itemLink + ‘\‘);">‘ + itemData + ‘</span>‘;
		} else if (itemType == this._folderType) {
			// 目录节点的 class 属性以 folder 开头,并且 onclick 事件调用 Tree.getChildren 函数
			return ‘<span class="folderMark" onclick="Tree.getChildren(\‘‘
					+ itemId + ‘\‘)">‘ + this._closeMark + ‘</span>‘
					+ ‘<span class="folder" onclick="Tree.getChildren(\‘‘
					+ itemId + ‘\‘)">‘ + itemData + ‘</span>‘
		}
	}

	// 单击叶子节点后的动作,目前只是弹出对话框,可修改为链接到具体的页面
	this.clickItem = function(_link) {
		alert("当前节点可以链接到页面 " + _link + " 。");
	}

	// 用于创建 XMLHttpRequest 对象
	this.createXmlHttp = function() {
		var xmlHttp = null;
		// 根据 window.XMLHttpRequest 对象是否存在使用不同的创建方式
		if (window.XMLHttpRequest) {
			xmlHttp = new XMLHttpRequest(); // FireFox、Opera 等浏览器支持的创建方式
		} else {
			xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); // IE 浏览器支持的创建方式
		}
		return xmlHttp;
	}
}

index.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>动态树形列表</title>
<script type="text/javascript" src="js/tree.js"></script>
<link href="css/tree.css" type="text/css" rel="stylesheet">
</head>
<body >
	<h1>动态树形列表</h1>
	<div id="treeInit"></div>
</body>
</html>
时间: 2024-11-18 17:36:28

Ajax-ajax实例3-动态树形列表的相关文章

Winform开发主界面菜单的动态树形列表展示

我在之前很多文章里面,介绍过Winform主界面的开发,基本上都是标准的界面,在顶部放置工具栏,中间区域则放置多文档的内容,但是在顶部菜单比较多的时候,就需要把菜单分为几级处理,如可以在顶部菜单放置一二级菜单,这种方式在一般功能点不算太多的情况下,呈现的界面效果较为直观.也较为美观.不过随着一些系统功能的增多,这种方式可能就会显得工具栏比较拥挤,那么我们是否可以在左侧放置一个树形列表,这样通过树形列表的收缩折叠,就可以放置非常多的菜单功能了. 1.菜单的树形列表展示 一般情况下,树形列表的显示可

Ajax 使用实例

在介绍实例之前,先就AJAX的几种便捷形式作出说明. Ajax传输Data时有四种常用的数据类型,分别是html文档.Json数据.js文件和Xml文档,四种数据类型对应着如下方法: 数据形式 方法 适用情况 HTML 形式 $().load(a,b)   适用于对数据没什么操作的情况,如简单的文本拼接等 Json 形式 $.getJSON(a,b) 特点是格式清晰,数据较少,但对结构要求很精确,人工编写时要特别注意.适用于数据需要重用的情况,能在性能上得到显著提高. JS 形式 $.getSc

Ajax基础实例(二)

用了很久的Asp.Net Ajax,也看了段时间的jquery中ajax的应用,但到头来,居然想不起xmlHttpRequest的该如何使用了. 以前记的也不怎么清楚,这次就重新完整的学习一遍吧,也为了自己以后能找个完整的地方来复习. 什么是Ajax Ajax的全称是Asynchronous Javascript And XML.AJax由HTML,Javascript,DHTML和DOM组成. HTML用于建立Web表单 Javascript代码用于运行Ajax应用程序的核心代码,用于和服务器

简单的Ajax应用实例

从网页前端输入提示范围内的字符,然后显示从后台返回的结果 <html> <head> <meta http-equiv="content-type" content="text/html;charset=utf-8"> <script type="text/javascript"> function showHint(str) { var xmlhttp; if (str.length==0) {

ajax 基础实例

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 优点:使用ajax读取数据文件,不需要刷新页面就能取出文件数据<br><br><br><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transition

AJAX 数据库实例

AJAX 用于创建动态性更强的应用程序. AJAX ASP 实例 下面的例子将演示当用户在输入框中键入字符时,网页如何与服务器进行通信: 实例 请在下面的输入框中键入字母(A - Z): 姓名: 建议: 亲自试一下源代码 实例解释 - HTML 页面 当用户在上面的输入框中键入字符时,会执行 "showHint()" 函数.该函数由 "onkeyup" 事件触发: <!DOCTYPE html> <html> <head> <

ajax常用实例代码总结参考

http的交互方法有四种:get.post.put(增加数据).delete(删除数据) put和delete实现用的是get和post get方式 页面不能被修改,只是获取查询信息.但是提交的数据会通过链接暴露在外,使用get请求会被人拿到登陆的用户名和密码,url长度有限制 post方式 页面可以修改,比如回帖.评论.但是提交的数据不会暴露在外,url长度无限制,但是提交大小会有限制 默认不被缓存,不在同一个请求域下远程请求,post都会被转为get 推荐两篇不错的jquery教程:<jQu

AJAX XML 实例

AJAX XML 实例 下面的例子将演示网页如何使用 AJAX 来读取来自 XML 文件的信息 <!DOCTYPE html> <html> <head> <script> function loadXMLDoc(url) { var xmlhttp; var txt,x,xx,i; if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari xmlhttp=new

AJAX 请求实例

AJAX ASP/PHP 实例 下面的例子将为您演示当用户在输入框中键入字符时,网页如何与 web 服务器进行通信: 请在下面的输入框中键入字母(A - Z): 姓氏: 实例解释 - showHint() 函数 当用户在上面的输入框中键入字符时,会执行函数 "showHint()" .该函数由 "onkeyup" 事件触发: function showHint(str) { var xmlhttp; if (str.length==0) { document.get