- 浏览: 760771 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
Ripin_Yan:
写的挺透彻
session与cookie的区别? -
1045565111:
谢谢,运行起来了,非常不错~~~
EXTJS动态树的实现 -
hlxhf5000:
找了半天,机会都没有全套的下载
ExtJs视频教程集锦 -
slysuccess:
讲解的非常好!以前还不是太明白,现在终于明白了!谢谢博主
ExtJs中关于grid和store的应用分析(二) -
yixiandave:
怎么看都蛋疼啊。。
js继承的实现
EXTJS动态树的实现举例
一、描述:通过dwr实现JS与后台的交互,从而实现动态树中叶子节点和目录节点的增加和编辑、以及节点的拖曳,节点的增删和拖曳都会改变自身以及它所在的目录节点下的相关节点的序号,能使得后台与前台同步。这个序号借助了tree中node的index。
1、相关基础:
servlet、mysql、dwr、json
2、涉及的ExtJs中部分知识点:
menu、tree、window以及事件机制
3、实现的效果图:
a)ExtJs动态树-右键叶子节点菜单
b)ExtJs动态树-选择右键叶子节点菜单的“编辑”选项
c)ExtJs动态树-右键目录节点菜单
d)ExtJs动态树-选择右键目录节点菜单的“编辑”选项
e)ExtJs动态树-拖曳节点
4、导航数据表结构:
5、源码结构图:
6、页面结构图:
二、实现流程
JAVA源码部分:
1、数据库连接
2、dao层:
3、Service层
4、Servlet层
a)edit
b)save
c)json
页面:
1、edit
2、success
3、json
4、in.jsp
js核心:
console-index.js
dwr配置:
dwr.xml
servlet配置:
web.xml
提示XDB,我试了也出现这样的情况。但是这是因为Oracle也占用了8080端口,这个提示是Oracle 中自带的Apache提示的。所以,要么改Oracle中的端口,要么把运行本工程的Tomcat服务器商品改了。
为什么我在界面上的操作没有存入数据库呢?我已经修改了DAO文件
请在跟踪下后台进行断点调试
个人愚见:
extjs有了设计很完善的ajax交互类,为了提高效率extjs貌似只会创建一个全局的ajax请求交互对象,所以在这里,我认为没有必要去使用dwr的ajax功能,dwr能做的,Ext.ajax基本都能实现。这样貌似更加完美。
谢谢yourgame,包括这个树节点的修改和添加界面同样我也没有采用panel的方式来做,否则效果也更好。我要突出“树”,而不是要突出panel和Ext的ajax。因为ajax需要另外的文章来进行描述,这样对初学者来说才可以看懂。
一、描述:通过dwr实现JS与后台的交互,从而实现动态树中叶子节点和目录节点的增加和编辑、以及节点的拖曳,节点的增删和拖曳都会改变自身以及它所在的目录节点下的相关节点的序号,能使得后台与前台同步。这个序号借助了tree中node的index。
1、相关基础:
servlet、mysql、dwr、json
2、涉及的ExtJs中部分知识点:
menu、tree、window以及事件机制
3、实现的效果图:
a)ExtJs动态树-右键叶子节点菜单
b)ExtJs动态树-选择右键叶子节点菜单的“编辑”选项
c)ExtJs动态树-右键目录节点菜单
d)ExtJs动态树-选择右键目录节点菜单的“编辑”选项
e)ExtJs动态树-拖曳节点
4、导航数据表结构:
5、源码结构图:
6、页面结构图:
二、实现流程
JAVA源码部分:
1、数据库连接
package com.demo.core.dao; import java.sql.Connection; import java.sql.DriverManager; public class DBConn { private static String url = "jdbc:mysql://localhost:3306/langsin"; private static String username = "root"; private static String password = ""; private static String driver = "com.mysql.jdbc.Driver"; public static Connection getConnection(){ Connection conn = null; try{ Class.forName(driver); conn = DriverManager.getConnection(url,username,password); }catch(Exception e){ e.printStackTrace(); } return conn; } }
2、dao层:
package com.demo.navigate.dao; import java.io.Serializable; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.List; import com.demo.core.dao.DBConn; import com.demo.navigate.model.Navigate; public class NavigateDao { private static NavigateDao dao; private NavigateDao(){ } public static NavigateDao getInstanece(){ if(null == dao){ dao = new NavigateDao(); } return dao; } /** * 获得指定ID的数据 * @param id * @return */ public Navigate get(Serializable id){ Connection conection = null; Statement stmt = null; ResultSet rs = null; Navigate obj = null; try{ conection = DBConn.getConnection(); stmt = conection.createStatement(); StringBuffer sql = new StringBuffer("select * from navigate where id = "); sql.append(id); rs = stmt.executeQuery(sql.toString()); if(rs.next()) { obj = new Navigate(); obj.setId(rs.getInt("id")); obj.setLeaf(rs.getInt("leaf")); obj.setNumber(rs.getInt("number")); obj.setParentId(rs.getInt("parentId")); obj.setTitle(rs.getString("title")); obj.setUrl(rs.getString("url")); } }catch(Exception e){ e.printStackTrace(); }finally{ try{ if(rs != null) { try { rs.close(); } catch (SQLException e) { } rs = null; } if (stmt != null) { try { stmt.close(); } catch (SQLException sqlex) { } stmt = null; } if (conection != null) { try { conection.close(); } catch (SQLException sqlex) { } conection = null; } }catch(Exception e){ e.printStackTrace(); } } return obj; } /** * 获得指定节点的所有儿子节点 * @param id */ @SuppressWarnings("unchecked") public List<Navigate> getChildrenById(Integer id){ List<Navigate> list = new ArrayList<Navigate>(); Connection conection = null; Statement stmt = null; ResultSet rs = null; try{ conection = DBConn.getConnection(); stmt = conection.createStatement(); StringBuffer sql = new StringBuffer("select * from navigate where parentId = "); sql.append(id); sql.append(" order by number,id"); rs = stmt.executeQuery(sql.toString()); while(rs.next()) { Navigate obj = new Navigate(); obj.setId(rs.getInt("id")); obj.setLeaf(rs.getInt("leaf")); obj.setNumber(rs.getInt("number")); obj.setParentId(rs.getInt("parentId")); obj.setTitle(rs.getString("title")); obj.setUrl(rs.getString("url")); list.add(obj); } }catch(Exception e){ e.printStackTrace(); }finally{ try{ if(rs != null) { try { rs.close(); } catch (SQLException e) { } rs = null; } if (stmt != null) { try { stmt.close(); } catch (SQLException sqlex) { } stmt = null; } if (conection != null) { try { conection.close(); } catch (SQLException sqlex) { } conection = null; } }catch(Exception e){ e.printStackTrace(); } } return list; } /** * 保存数据 * @param obj */ public void save(Navigate obj){ StringBuffer sql = new StringBuffer("insert into navigate(parentId,title,leaf,number,url) values("); sql.append(obj.getParentId()); sql.append(",'"); sql.append(obj.getTitle()); sql.append("',"); sql.append(obj.getLeaf()); sql.append(","); sql.append(obj.getNumber()); sql.append(",'"); sql.append(obj.getUrl()); sql.append("')"); this.bulkUpdate(sql.toString()); } /** * 更新数据 * @param obj */ public void update(Navigate obj){ StringBuffer sql = new StringBuffer("update navigate set"); sql.append(" parentId = "); sql.append(obj.getParentId()); sql.append(","); sql.append(" title = '"); sql.append(obj.getTitle()); sql.append("',"); sql.append(" leaf = "); sql.append(obj.getLeaf()); sql.append(","); sql.append(" number = "); sql.append(obj.getNumber()); sql.append(", url = '"); sql.append(obj.getUrl()); sql.append("' where id = "); sql.append(obj.getId()); this.bulkUpdate(sql.toString()); } /** * 异步更新标题 * @param id * @param title * @return true-修改成功 false-修改失败 */ public Boolean ajaxUpdateTitle(Integer id,String title){ Boolean flag = false; Navigate obj = this.get(id); if(null != obj){ StringBuffer sql = new StringBuffer("update navigate set"); sql.append(" title = '"); sql.append(title); sql.append("'"); sql.append(" where id = "); sql.append(id); this.bulkUpdate(sql.toString()); flag = true; } return flag; } /** * 删除指定的一条数据 * @param id */ public void removeById(Integer id){ StringBuffer sql = new StringBuffer("delete from navigate where id = "); sql.append(id); this.bulkUpdate(sql.toString()); } /** * 异步删除数据,包括其子孙节点 * @param id * @param title */ @SuppressWarnings("unchecked") public void ajaxRemoveNode(Integer id){ List list = this.getChildrenById(id); for (Object object : list) { Navigate obj = (Navigate)object; ajaxRemoveNode(obj.getId()); } this.removeById(id); } /** * 移动指定节点 * @param id 指定的节点的id * @param oldParentId 节点移动前所在的父节点 * @param newParentId 节点移动后的目标父节点 * @param nodeIndex 节点移动后的目标位置 */ public void ajaxMoveNode(int id, int oldParentId, int newParentId, int nodeIndex){ Navigate obj = this.get(id); int minIndex = obj.getNumber().intValue(); int maxIndex = nodeIndex; if(oldParentId == newParentId && minIndex != maxIndex){ // 在同一个父节点下发生移动 if(minIndex < maxIndex){ // 当要移动的节点的序号小于要移动到的目标序号,则下移 this.downNode(oldParentId, minIndex, maxIndex); }else if(minIndex > maxIndex){ // 当要移动的节点的序号大于要移动到的目标序号,则上移 maxIndex = minIndex; minIndex = nodeIndex; this.upNode(oldParentId, minIndex, maxIndex); } // 节点本身的序号设置成要移动到的目标序号 obj.setNumber(nodeIndex); this.update(obj); } if(oldParentId != newParentId){ // 在不同父节点下发生移动 //1、相当于要移动的节点在原父节点下下移到最后再删除掉,因此要指定移动发生时节点所在的位置 this.downNode(oldParentId, minIndex, -1); //2、相当于要移动的节点在新父节点下上移到指定的位置,因此需要指定要移动到的位置 this.upNode(newParentId, maxIndex, -1); // 节点本身的序号设置成要移动到的目标序号 obj.setNumber(nodeIndex); obj.setParentId(newParentId); this.update(obj); } } /** * 指定的节点下移 * @param parentId 指定范围内要移动的节点的父节点 * @param minIndex 指定节点移动发生时所在的位置 * @param maxIndex 指定节点要移动到的目标位置 */ @SuppressWarnings("unchecked") public void downNode(int parentId, int minIndex, int maxIndex){ // 指定的节点下移,意味着其范围内的节点各自减1 StringBuffer sql = new StringBuffer("update navigate set number=number-1 where parentId = "); sql.append(parentId); if(maxIndex != -1){ sql.append(" and number <= "); sql.append(maxIndex); } if(minIndex != -1){ sql.append(" and number > "); sql.append(minIndex); } this.bulkUpdate(sql.toString()); } /** * 指定的节点上移 * @param parentId 指定范围内要移动的节点的父节点 * @param minIndex 指定节点要移动到的目标位置 * @param maxIndex 指定节点移动发生时所在的位置 */ @SuppressWarnings("unchecked") public void upNode(int parentId, int minIndex, int maxIndex){ // 指定的节点上移,意味着其范围内的节点各自加1 StringBuffer sql = new StringBuffer("update navigate set number=number+1 where parentId = "); sql.append(parentId); if(maxIndex != -1){ sql.append(" and number < "); sql.append(maxIndex); } if(minIndex != -1){ sql.append(" and number >= "); sql.append(minIndex); } this.bulkUpdate(sql.toString()); } /** * 批量更新或删除操作 * @param sql */ public void bulkUpdate(String sql){ Connection conection = null; Statement stmt = null; try{ conection = DBConn.getConnection(); stmt = conection.createStatement(); stmt.executeUpdate(sql); }catch(Exception e){ e.printStackTrace(); }finally{ try{ if (stmt != null) { try { stmt.close(); } catch (SQLException sqlex) { } stmt = null; } if (conection != null) { try { conection.close(); } catch (SQLException sqlex) { } conection = null; } }catch(Exception e){ e.printStackTrace(); } } } }
3、Service层
package com.demo.navigate.service; import java.io.Serializable; import java.util.List; import com.demo.navigate.dao.NavigateDao; import com.demo.navigate.model.Navigate; public class NavigateManager { private NavigateDao dao = NavigateDao.getInstanece(); public Navigate get(Serializable id){ return dao.get(id); } /** * 获得指定节点的所有儿子节点 * @param id */ @SuppressWarnings("unchecked") public List<Navigate> getChildrenById(Integer id){ return dao.getChildrenById(id); } /** * 保存数据 * @param obj */ public void save(Navigate obj){ dao.save(obj); } /** * 更新数据 * @param obj */ public void update(Navigate obj){ dao.update(obj); } /** * 删除指定的一条数据 * @param id */ public void removeById(Integer id){ dao.removeById(id); } /** * 异步更新标题 * @param id * @param title * @return true-修改成功 false-修改失败 */ public Boolean ajaxUpdateTitle(Integer id,String title){ return dao.ajaxUpdateTitle(id, title); } /** * 异步删除数据,包括其子孙节点 * @param id * @param title */ public void ajaxRemoveNode(Integer id){ Navigate obj = dao.get(id); dao.downNode(obj.getParentId(), obj.getNumber(), -1); dao.ajaxRemoveNode(id); } /** * 异步移动指定节点 * @param id 指定的节点的id * @param oldParentId 节点移动前所在的父节点 * @param newParentId 节点移动后的目标父节点 * @param nodeIndex 节点移动后的目标位置 */ public void ajaxMoveNode(int id, int oldParentId, int newParentId, int nodeIndex){ dao.ajaxMoveNode(id, oldParentId, newParentId, nodeIndex); } }
4、Servlet层
a)edit
package com.demo.navigate.web; import java.io.IOException; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.demo.navigate.model.Navigate; import com.demo.navigate.service.NavigateManager; @SuppressWarnings("serial") public class NavigateEditServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String idstr = request.getParameter("id"); String parentId = request.getParameter("parentId"); String leaf = request.getParameter("leaf"); String number = request.getParameter("number"); Navigate obj = null; if(null != idstr){ NavigateManager navigateManager = new NavigateManager(); obj = navigateManager.get(idstr); }else{ obj = new Navigate(); obj.setParentId(new Integer(parentId)); obj.setLeaf(new Integer(leaf)); obj.setNumber(new Integer(number)); } request.setAttribute("obj", obj); RequestDispatcher dispatcher = request.getRequestDispatcher("/navigate/console-edit.jsp"); dispatcher.forward(request, response); } }
b)save
package com.demo.navigate.web; import java.io.IOException; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.demo.navigate.model.Navigate; import com.demo.navigate.service.NavigateManager; @SuppressWarnings("serial") public class NavigateSaveServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { NavigateManager navigateManager = new NavigateManager(); Navigate obj = null; request.setCharacterEncoding("UTF-8"); String id = request.getParameter("id"); String number = request.getParameter("number"); String parentId = request.getParameter("parentId"); String leaf = request.getParameter("leaf"); String title = request.getParameter("title"); String url = request.getParameter("url"); if(null != id && !"".equals(id)){ obj = navigateManager.get(id); if(obj == null){ RequestDispatcher dispatcher = request.getRequestDispatcher("/navigate/error.jsp"); dispatcher.forward(request, response); return; } }else{ obj = new Navigate(); obj.setLeaf(new Integer(leaf)); obj.setParentId(new Integer(parentId)); } obj.setNumber(new Integer(number)); obj.setTitle(title); obj.setUrl(url); if(null != id && !"".equals(id)){ navigateManager.update(obj); }else{ navigateManager.save(obj); } RequestDispatcher dispatcher = request.getRequestDispatcher("/navigate/success.jsp"); dispatcher.forward(request, response); } }
c)json
package com.demo.navigate.web; import java.io.IOException; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.demo.navigate.service.NavigateManager; @SuppressWarnings("serial") public class NavigateJsonServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { NavigateManager navigateManager = new NavigateManager(); request.setAttribute("list", navigateManager.getChildrenById(new Integer(request.getParameter("id")))); RequestDispatcher dispatcher = request.getRequestDispatcher("/navigate/console-json.jsp"); dispatcher.forward(request, response); } }
页面:
1、edit
<%@ page contentType="text/html;charset=UTF-8" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ include file="/common/in.jsp"%> <html> <head> <base href="<%=basePath%>"> <title>菜单编辑</title> <link rel="stylesheet" type="text/css" href="scripts/ext/resources/css/ext-all.css"> <script type="text/javascript" src="scripts/ext/adapter/ext/ext-base.js"></script> <script type="text/javascript" src="scripts/ext/ext-all.js"></script> <script type="text/javascript"> function checkForm(form){ if(form.parentId.value == "" || form.leaf.value == ""){ Ext.Msg.alert("错误提示","表单信息不健全!"); return false; } if(form.title.value == ""){ Ext.Msg.alert("错误提示","标题不能为空!"); return false; } } </script> </head> <body style="background-color: white"> <br/><br/> <form action="navigatesave" method="post" onsubmit="return checkForm(this)"> <input type="hidden" name="id" value="${obj.id}"/> <input type="hidden" name="parentId" value="${obj.parentId}"/> <input type="hidden" name="leaf" value="${obj.leaf}"/> <input type="hidden" name="number" value="${obj.number}"/> <table align="center"> <tr><td width="60">标题:</td> <td><input type="text" name="title" value="${obj.title}"/></td></tr> <c:if test="${obj.leaf==1}"> <tr><td>URL:</td> <td><input type="text" name="url" value="${obj.url}"/></td></tr> </c:if> <tr><td colspan="2" align="center"> <br/> <input type="submit" name="submit" value="保存"/> <input type="reset" name="reset" value="重置"/> <input type="button" name="button" value="取消" onclick="window.parent.FormEditWin.close();"> </td></tr> </table> </form> </body> </html>
2、success
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>信息更新成功</title> <script type="text/javascript"> // 信息保存成功后,刷新父节点 this.parent.FormEditWin.reloadNavNode(); </script> </head> <body> <center> 恭喜,信息更新成功! </center> </body> </html>
3、json
<%@ page contentType="text/html;charset=UTF-8" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> <c:set var="len" value="${fn:length(list)-1}" ></c:set> [ <c:forEach items="${list}" var="obj" varStatus="i"> { id:'${obj.id}', text:'${obj.title}', <c:if test="${obj.leaf == 1}"> leaf:true, </c:if> singleClickExpand:true } <c:if test="${i.index<len}">,</c:if> </c:forEach> ]
4、in.jsp
<%@ page language="java" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %>
js核心:
console-index.js
// 全局路径 var basePath = "http://localhost:8080/langsinext"; if(typeof(glbRootPath) != "undefined"){ basePath = glbRootPath; } // 扩展窗体 FormEditWin = function(){ var curFormWin; return { width : 600, height : 400, showAddDirWin : function(parentNode) { // 显示添加子目录窗口 var number = parentNode.indexOf(parentNode.lastChild) + 1; var editpage = basePath + "/navigateedit?parentId=" + parentNode.id + "&leaf=0&number=" + number; var window = this.createWin("windirnew", "新建目录节点", editpage, function() { parentNode.reload(); }); window.show(); }, showAddLeafWin : function(parentNode) { // 显示添加子叶子节点窗口 var number = parentNode.indexOf(parentNode.lastChild) + 1; var editpage = basePath + "/navigateedit?parentId=" + parentNode.id + "&leaf=1&number=" + number; var window = this.createWin("winleafnew", "新建叶子节点", editpage, function() { parentNode.reload(); }); window.show(); }, showEditDirWin : function(node) { // 显示目录编辑窗口 var editpage = basePath + "/navigateedit?id=" + node.id; var window = this.createWin("win" + node.id, node.text, editpage, function() { var nodeparent = node.parentNode; var tree = node.getOwnerTree(); nodeparent.on("expand", function(pnode) { tree.getNodeById(node.id).select(); }, this, { single : true }); node.parentNode.reload(); }); window.show(); }, showEditLeafWin : function(node) { // 显示叶子节点编辑窗口 var editpage = basePath + "/navigateedit?id=" + node.id; var window = this.createWin("win" + node.id, node.text, editpage, function() { var nodeparent = node.parentNode; var tree = node.getOwnerTree(); nodeparent.on("expand", function(pnode) { tree.getNodeById(node.id).select(); }, this, { single : true }); node.parentNode.reload(); }); window.show(); }, createWin : function(winId, winTitle, iframePage, closeFun) { // 供各类型窗口创建时调用 var win = Ext.getCmp(winId); if (!win) { win = new Ext.Window({ id : winId, title : "菜单编辑窗口-" + winTitle, width : this.width, height : this.height, maximizable : true, modal : true, html : "<iframe width='100%' height='100%' frameborder='0' src='" + iframePage + "'></iframe>" }); this.reloadNavNode = closeFun; } curFormWin = win; return win; }, reloadNavNode : function() { }, close : function() { if(curFormWin){ curFormWin.close(); } } } }(); // 导航树 NavTree = function(){ var nav; var navEditor; var leafMenu; var dirMenu; var loader; var root; var removeFlag = false; var titleChangeFlag = false; var nodeSelected; var mgr; return { init : function(){ if(!mgr){ Ext.Msg.alert("警告提示","请先通过NavTree.setMgr()设置mgr"); return; } if(!loader){ loader = new Ext.tree.TreeLoader({ url : basePath + '/navigatejson' }); loader.on('beforeload', function(treeloader, node) { treeloader.baseParams = { id : node.id, method : 'tree' }; }, this); } if(!root){ root = new Ext.tree.AsyncTreeNode({ id : '0', text : "系统菜单" }); } if(!nav){ nav = new Ext.tree.TreePanel({ title : "左部导航", width : 232, autoScroll : true, animate : true, loader : loader, root : root, enableDD : true, listeners : { 'click' : function(node, event) { if (node.isLeaf()) { // 为叶子节点时,点击不进入链接 event.stopEvent(); } } } }); // 添加右键菜单 nav.on("contextmenu", this.showTreeMenu); // 当节点文本改变时触发事件 nav.on("textchange", function(node, newText, oldText) { if (!titleChangeFlag && newText != oldText) { mgr.ajaxUpdateTitle(node.id, newText, function(success) { if (!success) { Ext.Msg.show({ title : "操作失败!", msg : "菜单修改失败!", buttons : Ext.Msg.OK, icon : Ext.MessageBox.ERROR }); titleChangeFlag = true; node.setText(oldText); titleChangeFlag = false; } }); } }); // 当节点移动时触发事件 nav.on("movenode", function(tree, node, oldParent, newParent, index) { mgr.ajaxMoveNode(node.id, oldParent.id, newParent.id, index); }); // 当节点删除时触发事件 nav.on("remove", function(tree, parentNode, node) { if (removeFlag) { mgr.ajaxRemoveNode(node.id); } }); } if(!navEditor){ navEditor = new Ext.tree.TreeEditor(nav, { allowBlank : false, ignoreNoChange : true, blankText : '标题不能为空', selectOnFocus : true }); } this.setLeafMenu(); this.setDirMenu(); }, setMgr : function(manager){ mgr = manager; }, getMgr : function(){ return mgr; }, setLeafMenu: function(){ // 设置叶子菜单 if(!leafMenu){ leafMenu = new Ext.menu.Menu({ items : [{ text : "修改标题", handler : function() { navEditor.triggerEdit(nodeSelected); } }, "-", { text : "编辑", handler : function() { FormEditWin.showEditLeafWin(nodeSelected); } }, "-", { text : "删除", handler : this.delTreeItemComfirm }] }); } }, setDirMenu: function(){ // 设置目录菜单 if(!dirMenu){ dirMenu = new Ext.menu.Menu({ items : [{ text : "修改标题", handler : function() { navEditor.triggerEdit(nodeSelected); } }, "-", { text : "编辑", handler : function() { FormEditWin.showEditDirWin(nodeSelected); } }, "-", { text : "添加叶子节点", handler : function() { FormEditWin.showAddLeafWin(nodeSelected); } }, "-", { text : "添加目录节点", handler : function() { FormEditWin.showAddDirWin(nodeSelected); } }, "-", { text : "删除", handler : this.delTreeItemComfirm }] }); } }, showTreeMenu : function(node, e){ nodeSelected = node; nodeSelected.select(); if (node.isLeaf()) { // 显示叶子节点菜单 leafMenu.showAt(e.getPoint()); } else { // 显示目录节点菜单 dirMenu.showAt(e.getPoint()); } }, delTreeItemComfirm : function(){ Ext.Msg.confirm("确认删除", "确定要删除所选节点吗?", function(btn) { if (btn == "yes") { NavTree.delTreeItem(); } }); }, delTreeItem : function(){ if (nodeSelected != nav.getRootNode()) { removeFlag = true; nodeSelected.remove(); removeFlag = false; } else { Ext.Msg.alert("警告", "不能删除树的根节点!"); } }, show : function(){ nav.render(Ext.getBody()); nav.getRootNode().toggle(); } } }(); // 文档加载完毕执行 Ext.onReady(function(){ Ext.BLANK_IMAGE_URL = "../scripts/ext/resources/images/default/s.gif"; if(typeof(NavigateManager)=="undefined"){ Ext.Msg.alert("警告提示","请先设置DWR,并实例化NavigateManager"); }else{ NavTree.setMgr(NavigateManager); NavTree.init(); NavTree.show(); } });
dwr配置:
dwr.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" "http://www.getahead.ltd.uk/dwr//dwr20.dtd"> <dwr> <allow> <create javascript="NavigateManager" creator="new"> <param name="class" value="com.demo.navigate.service.NavigateManager"> </param> <include method="ajaxUpdateTitle" /> <include method="ajaxRemoveNode" /> <include method="ajaxMoveNode" /> </create> </allow> </dwr>
servlet配置:
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <servlet> <servlet-name>navigatejson</servlet-name> <servlet-class> com.demo.navigate.web.NavigateJsonServlet </servlet-class> </servlet> <servlet> <servlet-name>navigateedit</servlet-name> <servlet-class> com.demo.navigate.web.NavigateEditServlet </servlet-class> </servlet> <servlet> <servlet-name>navigatesave</servlet-name> <servlet-class> com.demo.navigate.web.NavigateSaveServlet </servlet-class> </servlet> <servlet-mapping> <servlet-name>navigatejson</servlet-name> <url-pattern>/navigatejson</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>navigateedit</servlet-name> <url-pattern>/navigateedit</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>navigatesave</servlet-name> <url-pattern>/navigatesave</url-pattern> </servlet-mapping> <servlet> <servlet-name>dwr-invoker</servlet-name> <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name> allowGetForSafariButMakeForgeryEasier </param-name> <param-value>true</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dwr-invoker</servlet-name> <url-pattern>/dwr/*</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
- 示例代码.rar (1.7 MB)
- 下载次数: 3720
评论
41 楼
1045565111
2014-05-05
谢谢,运行起来了,非常不错~~~
40 楼
Mr.xiaopang
2013-10-29
请问下,把你这课树放在viewport的左边——west,该怎么弄啊?自己试着弄的不成功,可能是对楼主的代码理解的不透彻,QQ:993353141,希望能够指点一二,我也是才接触extjs。多谢!!!
39 楼
w493778311
2013-09-17
缺少好多JS文件
38 楼
春夏虫
2012-08-28
好强大的树
37 楼
lijin2031427
2012-06-01
请问那个 URL 填完后,点击为什么没有响应,能帮忙说下是什么原因吗?
36 楼
lys221221
2011-09-22
老师 我看了你的视频有些问题想问你 能加我qq吗 497234690
35 楼
lys221221
2011-09-22
你好 老师 我把你的源码下载下来啦 部署上怎么 就光显示 一小部分啊 我不知道什么原因 光显示系统菜单 子菜单都不显示 能给解释下吗 我qq是497234690
34 楼
36032075
2011-07-25
请先设置DWR,并实例化NavigateManager 啥意思啊?
33 楼
winnerliub
2011-05-22
最近看了这个例子,很好。能否给个插入数据(insert into)的实例,谢谢!
32 楼
cl1154781231
2011-02-23
非常好 可以用!
31 楼
fx23794087
2010-02-11
如何把他放到指定的table中啊?
30 楼
zengqun89
2010-01-08
丫姐姐,您的项目我下载了,用的很好,
太有才了,呵呵
只是页面中有乱码,在添加后,
这是什么原图呢
太有才了,呵呵
只是页面中有乱码,在添加后,
这是什么原图呢
29 楼
longxiaoyan
2009-12-24
jj,你的项目里面id不好使啊。每次新加一个叶子或者树枝节点,id都
这样的话id就为0了,然后你:
这样的话根本就保存不了。
String id = request.getParameter("id");
这样的话id就为0了,然后你:
obj = navigateManager.get(id);
这样的话根本就保存不了。
28 楼
wintys
2009-12-16
davy138 写道
你好! 请问添加节点时, 提示需要验证:
http://localhost:8080 请求用户名和密码。信息为: “XDB”
用户名:
密码:
请问用什么用户和密码呢?
http://localhost:8080 请求用户名和密码。信息为: “XDB”
用户名:
密码:
请问用什么用户和密码呢?
提示XDB,我试了也出现这样的情况。但是这是因为Oracle也占用了8080端口,这个提示是Oracle 中自带的Apache提示的。所以,要么改Oracle中的端口,要么把运行本工程的Tomcat服务器商品改了。
27 楼
javaAlpha
2009-11-11
运行没问题
26 楼
javaAlpha
2009-11-11
最近也在做ext项目,遇到类似问题。过来看看
25 楼
zjzh123456
2008-12-04
如何设置tree的显示位子。我设置了用于显示树的层,但是在运行时无法显示完整。能指出如何在指定的层中显示树么?
24 楼
yahaitt
2008-11-28
zjzh123456 写道
为什么我在界面上的操作没有存入数据库呢?我已经修改了DAO文件
请在跟踪下后台进行断点调试
23 楼
zjzh123456
2008-11-27
为什么我在界面上的操作没有存入数据库呢?
我已经修改了DAO文件
我已经修改了DAO文件
22 楼
yahaitt
2008-11-04
yourgame 写道
个人愚见:
extjs有了设计很完善的ajax交互类,为了提高效率extjs貌似只会创建一个全局的ajax请求交互对象,所以在这里,我认为没有必要去使用dwr的ajax功能,dwr能做的,Ext.ajax基本都能实现。这样貌似更加完美。
谢谢yourgame,包括这个树节点的修改和添加界面同样我也没有采用panel的方式来做,否则效果也更好。我要突出“树”,而不是要突出panel和Ext的ajax。因为ajax需要另外的文章来进行描述,这样对初学者来说才可以看懂。
发表评论
-
关于Ext2.2中调用iframe,无法打开 Internet 站点
2009-02-26 13:40 2977在 EXT2.0运行正常的程序,调换 EXT2.2 的脚本之 ... -
对applyTo和renderTo的理解和思考
2008-10-06 15:54 18035extjs中经常会用到renderTo ... -
ExtJs视频教程集锦
2008-09-03 12:55 25895《ExtJs视频教程》全套已全面出炉,欢迎大家关注!目录如下: ... -
ExtJs中关于grid和store的应用分析(三)
2008-08-29 16:01 5601第三部分:解析器与数 ... -
ExtJs中关于grid和store的应用分析(二)
2008-08-29 13:45 9643第二部分:Store的核心阐释 Store即数据存储器,主 ... -
ExtJs中关于grid和store的应用分析(一)
2008-08-29 12:35 11086第一部分:阐述grid与st ... -
应用ExtJs时解决乱码的方法
2008-08-22 17:54 10015一般情况下,项目采用了UTF-8的字符集格式,那么所有的js文 ... -
序号结合分页功能的实现
2008-08-15 11:18 3781序号结合分页显示:一 ... -
ExtJs想入门的请进-解读API
2008-07-22 10:49 9189如果你对EXT有兴趣但不知道如何下手,如果你有了API但不知道 ... -
关于动态树的完整示例代码下载
2008-07-14 15:57 7625应网友反馈,现提供动态树的完整示例代码工程,以方便大家学习和交 ... -
ExtJs中关于mask()的应用说明
2008-06-30 10:25 12305Ext.Msg.alert( String title, St ... -
透析Extjs源码之结合API写事件响应函数
2008-05-16 14:34 3946我在一个论坛看到EXT传递参数的问题,觉得很多学EXT的人都 ... -
透析Extjs源码之layout(二)FormPanel与FormLayout的关系
2008-05-16 10:38 6197理解了layout之后,再看看FormPanel源码,发现它指 ... -
透析Extjs源码之layout(一)layout的实现
2008-05-16 09:48 59471、配置选项layout什么时候可用? 只有Ext.Conta ... -
透析Extjs的Ext.js源码(五)分析继承的实现
2008-05-15 14:33 10151ext中有关继承的实现的关键代码如下:(Ext.js中) e ... -
透析Extjs的Ext.js源码(四)去理解Ext.js
2008-05-14 18:00 2582//先定义匿名方法,第一个括号对里的,必须要有这个括号对, ... -
透析Extjs的Ext.js源码(三)扩展
2008-05-14 18:00 2440if(!Person.extend){//若extend属 ... -
透析Extjs的Ext.js源码(二)能在定义时就能执行的方法的写法 function(){...}
2008-05-14 17:59 4036/** * 第二部分:能在 ... -
透析Extjs的Ext.js源码(一)对象属性的添加和设置
2008-05-14 17:57 5768/** * 分析Ext.js */ /** ... -
extjs视频教程系列之-第一讲:ExtJS介绍及应用举例
2008-05-06 15:13 8191地址: http://bbs.langsin.com/view ...
相关推荐
extjs、struts2、mysql做的一个动态树,仅是一个动态树的小demo,不涉及角色、权限,并且数据是手动加入到数据库中的;资源中包涵数据库sql,只需创建一个名称为tree的数据库,执行sql就可以了,另外修改一下练级...
以下是一个简单的EXTJS动态树实现的步骤: 1. **定义数据模型(Model)**:首先,我们需要定义一个数据模型来描述树节点的结构。例如: ```javascript Ext.define('NodeModel', { extend: 'Ext.data.Model', ...
它具有丰富的配置项和事件,支持数据源绑定,能轻松实现动态加载。 2. 数据源:动态树的数据通常来自服务器,通过Ajax请求获取JSON格式的节点数据。这些数据包括节点ID、文本、子节点等信息。 3. 节点模型:每个树...
在 ExtJS 中实现动态树加载,我们需要遵循以下步骤: 1. **配置树节点**:首先,我们需要为树节点定义模型(Ext.data.TreeModel),并在模型中设置`leaf`属性为`false`来表示这是一个可扩展的节点,而非叶子节点。...
同时,ExtJS中的menu、tree、window等组件以及事件机制也是实现动态树的关键。 在实际项目中,动态树的实现可能还需要考虑到数据的存储结构,如导航数据表,以及页面的布局和源码组织。为了创建一个完整的动态树...
你可以通过Ajax请求获取服务器上的数据,并将其加载到Store中,从而实现动态加载节点。这不仅提高了页面的加载速度,还使得用户可以查看大量的层次结构数据而无需一次性加载所有内容。 首先,创建一个树形控件...
在EXTJS中,实现动态树通常需要以下步骤: 1. **配置树面板**:首先创建一个EXTJS的TreePanel,设置其配置项,如`rootVisible`(是否显示根节点)、`displayField`(显示字段)等。为了实现动态加载,需要设置`...
在EXTJS中实现动态树,主要是通过EXTJS的TreePanel组件来完成,下面将详细介绍EXTJS动态树的实现过程及其相关知识点。 1. TreePanel组件: TreePanel是EXTJS中用来展示树形结构数据的组件。它包含节点(Node)、根...
通过分析和学习这个文件,可以更深入地理解ExtJS和Struts如何协作实现动态树功能。 总结以上,ExtJS动态树与Struts的结合使用,需要熟练掌握ExtJS TreePanel的配置,JSON数据的构造和解析,以及Struts2的Action和...
总结来说,这个例子展示了如何使用ExtJS4和Java实现一个动态树结构。前端通过TreeStore从后端动态获取数据,当用户点击树节点时,会触发新的数据请求。后端根据请求参数返回JSON数据,更新树结构。这种动态加载的...
在描述中提到的博客链接可能提供了一个实现动态加载树的实例或教程,虽然具体内容未给出,但我们可以推测讨论的内容可能包括以下几个方面: 1. **Extjs TreePanel**: TreePanel是Extjs中用于展示树形数据的组件,它...
在ExtJS中,我们可以利用TreeStore和AjaxProxy来实现动态加载。TreeStore用于存储树节点的数据,而AjaxProxy则负责向服务器发送请求并处理响应。 接下来,我们探讨**JDBC访问SQL Server数据库**。Java Database ...
在本文中,我们将深入探讨如何使用ExtJS框架来实现自定义树结构以及动态表头的功能。ExtJS是一款强大的JavaScript库,常用于构建富客户端应用程序,它提供了丰富的UI组件和强大的数据绑定机制。VS2015是Visual ...
在ExtJS中,动态树通常通过TreePanel来实现。TreePanel是一个可配置的组件,可以设置各种属性,如节点的样式、展开/折叠行为、拖放功能等。它使用TreeStore来存储和管理数据,而TreeStore可以通过Ajax proxy与服务器...
ExtJS 是一个强大的JavaScript框架,...通过分析和学习这段代码,你可以更好地理解和应用ExtJS动态树的实现方式。记住,实际项目中可能还需要结合服务器端的接口设计和数据格式,确保数据能正确地加载到树形结构中。
总的来说,EXTJS的树形搜索功能是通过结合TreePanel、TreeStore和过滤机制实现的,它提供了灵活的搜索选项,能够满足不同场景下的数据查找需求。通过深入理解和运用这些知识点,我们可以构建出功能强大、用户体验...
下面我们将详细探讨这三个技术在实现动态树实例中的应用。 首先,JSP(JavaServer Pages)是Java的一种动态网页技术,它允许开发者在HTML代码中嵌入Java代码,以实现动态网页的生成。在本实例中,JSP将作为服务器端...
目录树编辑功能是指EXTJS中允许用户对树形结构进行动态操作,包括添加、删除、修改和查询节点。这个功能在许多业务场景中非常实用,例如文件管理系统、权限管理界面等。EXTJS提供了一套完整的API和事件机制,使得...
2. **EXTJS树菜单**: EXTJS中的树菜单(TreeMenu)是TreePanel的一个变体,通常用作下拉菜单。它结合了树的层次结构和菜单的功能,用户可以通过选择不同的菜单节点来执行相应的操作。这种设计使得复杂的操作结构变...