Extjs动态树的实现以及节点拖拽
更新时间:2024-07-04 09:41:01 阅读量: 综合文库 文档下载
- excel表格推荐度:
- 相关推荐
ExtJS TreeGrid
Home ? 02.技术 ? ExtJS TreeGrid叶子节点拖拽问题和选择框使用方法
ExtJS TreeGrid叶子节点拖拽问题和选择框使用方法
Posted by Little Horse - 2011 年 11 月 09 日 - Posted in: 02.技术 - Permalink
最近一直参与开发一个实验室项目,接触到了ExtJs。下面是工程中几个小问题的总结。
1.TreeGrid的叶子节点拖拽问题
我使用的是ExtJs3.1版本。ExtJs中默认在树(Ext.tree.TreePanel)的拖动中,一个节点是不能拖动到一个叶子节点中的。这样的设计有些武断,因为根据应用环境叶子节点是有可能变为父节点的。事件机制给这个问题带来了解决方案,许多地方都提到了在监听TreePanel的\事件时特殊处理使得叶子节点可以被drop。代码为:
1 2 3 4 5 6 7
tree.on(\ var n = e.target; if (n.leaf) { n.leaf = false; }
return true; });
最后的返回值设为true使得目标叶子节点接受拖动的节点。
在使用TreeGrid(Ext.ux.tree.TreeGrid)时,同样面临上面的问题。采取同样的处理方式,尽管TreeGrid是继承自TreePanel,却仍不能使叶子节点被drop:
在上面的事件处理函数中加打印语句,发现在TreeGrid有叶子节点被drop时,nodedragover事件根本就没有被触发。
试着调试一下,把页面引入的ext-all.js换成ext-all-debug.js,从触发nodedragover的地方入手逐渐分析,最终发现当TreePanel的拖拽配置为dropConfig:
{appendOnly:true}时,nodedragover是不会触发的。这里TreePanel和TreeGrid的区别是,TreePanel如果不设置dropConfig属性,默认appendOnly是false;而TreeGrid如果不设置dropConfig属性,默认appendOnly是true。所以同样的处理到了TreeGrid这里就无效了。
明白了原因,只需要在TreeGrid的配置项里增加:dropConfig: {appendOnly:false}和上面的nodedragover事件处理函数就能实现TreeGrid的叶子节点drop问题,效果如下:
2.TreeGrid中增加选择框(checkBox)效果
TreePanel没有直接提供checkBox的配置项,官方例子中的处理完全可以用在TreeGrid上,见/examples/tree/check-tree.html,主要是在数据中增加\false\字段,然后用treeGrid.getChecked()方法获得当前选中的所有节点。效果如下:
小结:初步尝试了前端开发动作,感觉设计某项功能具体的实现方式、界面的样式特别是交互方式,是很有乐趣的工作。
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、数据库连接 Java代码
1. package com.demo.core.dao; 2.
3. import java.sql.Connection; 4. import java.sql.DriverManager; 5.
6. public class DBConn { 7.
8. private static String url = \angsin\
9. private static String username = \10. private static String password = \
11. private static String driver = \12.
13. public static Connection getConnection(){ 14. Connection conn = null; 15. try{
16. Class.forName(driver);
17. conn = DriverManager.getConnection(url,username,password);
18. }catch(Exception e){ 19. e.printStackTrace(); 20. }
21. return conn; 22. } 23.}
2、dao层: Java代码
1. package com.demo.navigate.dao; 2.
3. import java.io.Serializable; 4. import java.sql.Connection; 5. import java.sql.ResultSet; 6. import java.sql.SQLException; 7. import java.sql.Statement; 8. import java.util.ArrayList; 9. import java.util.List; 10.
11.import com.demo.core.dao.DBConn;
12.import com.demo.navigate.model.Navigate; 13.
14.public class NavigateDao {
15. private static NavigateDao dao; 16. private NavigateDao(){ 17. }
18. public static NavigateDao getInstanece(){ 19. if(null == dao){
20. dao = new NavigateDao(); 21. }
22. return dao; 23. } 24. /**
25. * 获得指定ID的数据
26. * @param id 27. * @return 28. */
29. public Navigate get(Serializable id){ 30. Connection conection = null; 31. Statement stmt = null; 32. ResultSet rs = null; 33. Navigate obj = null; 34. try{
35. conection = DBConn.getConnection(); 36. stmt = conection.createStatement();
37. StringBuffer sql = new StringBuffer(\navigate where id = \38. sql.append(id);
39. rs = stmt.executeQuery(sql.toString()); 40. if(rs.next()) 41. {
42. obj = new Navigate();
43. obj.setId(rs.getInt(\44. obj.setLeaf(rs.getInt(\45. obj.setNumber(rs.getInt(\46. obj.setParentId(rs.getInt(\47. obj.setTitle(rs.getString(\48. obj.setUrl(rs.getString(\49. }
50. }catch(Exception e){
51. e.printStackTrace(); 52. }finally{ 53. try{
54. if(rs != null) { 55. try {
56. rs.close();
57. } catch (SQLException e) { 58. }
59. rs = null; 60. } 61. if (stmt != null) { 62. try {
63. stmt.close();
64. } catch (SQLException sqlex) { 65. }
66. stmt = null; 67. }
68. if (conection != null) {
69. try {
70. conection.close();
71. } catch (SQLException sqlex) { 72. }
73. conection = null; 74. }
75. }catch(Exception e){ 76. e.printStackTrace(); 77. } 78. }
79. return obj; 80. } 81. 82. /**
83. * 获得指定节点的所有儿子节点 84. * @param id 85. */
86. @SuppressWarnings(\
87. public List
93. conection = DBConn.getConnection(); 94. stmt = conection.createStatement();
95. StringBuffer sql = new StringBuffer(\navigate where parentId = \96. sql.append(id);
97. sql.append(\
98. rs = stmt.executeQuery(sql.toString()); 99. while(rs.next()) 100. {
101. Navigate obj = new Navigate(); 102. obj.setId(rs.getInt(\103. obj.setLeaf(rs.getInt(\104. obj.setNumber(rs.getInt(\
105. obj.setParentId(rs.getInt(\106. obj.setTitle(rs.getString(\107. obj.setUrl(rs.getString(\108. list.add(obj); 109. }
110. }catch(Exception e){
111. e.printStackTrace();
112. }finally{ 113. try{
114. if(rs != null) { 115. try {
116. rs.close();
117. } catch (SQLException e) { 118. }
119. rs = null; 120. } 121. if (stmt != null) { 122. try {
123. stmt.close();
124. } catch (SQLException sqlex) { 125. }
126. stmt = null; 127. }
128. if (conection != null) { 129. try {
130. conection.close();
131. } catch (SQLException sqlex) { 132. }
133. conection = null; 134. }
135. }catch(Exception e){
136. e.printStackTrace(); 137. } 138. }
139. return list; 140. } 141. 142. /**
143. * 保存数据 144. * @param obj 145. */
146. public void save(Navigate obj){
147. StringBuffer sql = new StringBuffer(\avigate(parentId,title,leaf,number,url) values(\148. sql.append(obj.getParentId()); 149. sql.append(\
150. sql.append(obj.getTitle()); 151. sql.append(\
152. sql.append(obj.getLeaf()); 153. sql.append(\
154. sql.append(obj.getNumber());
155. sql.append(\
156. sql.append(obj.getUrl()); 157. sql.append(\
158. this.bulkUpdate(sql.toString()); 159. } 160. 161. /**
162. * 更新数据 163. * @param obj 164. */
165. public void update(Navigate obj){
166. StringBuffer sql = new StringBuffer(\te set\
167. sql.append(\168. sql.append(obj.getParentId()); 169. sql.append(\
170. sql.append(\171. sql.append(obj.getTitle()); 172. sql.append(\
173. sql.append(\174. sql.append(obj.getLeaf()); 175. sql.append(\
176. sql.append(\177. sql.append(obj.getNumber()); 178. sql.append(\179. sql.append(obj.getUrl()); 180. sql.append(\181. sql.append(obj.getId());
182. this.bulkUpdate(sql.toString()); 183. } 184. 185. /**
186. * 异步更新标题 187. * @param id 188. * @param title
189. * @return true-修改成功 false-修改失败 190. */
191. public Boolean ajaxUpdateTitle(Integer id,String title){
192. Boolean flag = false;
193. Navigate obj = this.get(id); 194. if(null != obj){
195. StringBuffer sql = new StringBuffer(\vigate set\
196. sql.append(\197. sql.append(title); 198. sql.append(\
199. sql.append(\200. sql.append(id);
201. this.bulkUpdate(sql.toString()); 202. flag = true; 203. }
204. return flag; 205. } 206. 207. /**
208. * 删除指定的一条数据 209. * @param id 210. */
211. public void removeById(Integer id){
212. StringBuffer sql = new StringBuffer(\avigate where id = \
213. sql.append(id);
214. this.bulkUpdate(sql.toString()); 215. } 216. 217. /**
218. * 异步删除数据,包括其子孙节点 219. * @param id 220. * @param title 221. */
222. @SuppressWarnings(\
223. public void ajaxRemoveNode(Integer id){ 224. List list = this.getChildrenById(id); 225. for (Object object : list) {
226. Navigate obj = (Navigate)object; 227. ajaxRemoveNode(obj.getId()); 228. }
229. this.removeById(id); 230. } 231. 232. /**
233. * 移动指定节点
234. * @param id 指定的节点的id
235. * @param oldParentId 节点移动前所在的父节点 236. * @param newParentId 节点移动后的目标父节点 237. * @param nodeIndex 节点移动后的目标位置 238. */
239. public void ajaxMoveNode(int id, int oldParentId, int newParentId, int nodeIndex){
240. Navigate obj = this.get(id);
241. int minIndex = obj.getNumber().intValue(); 242. int maxIndex = nodeIndex;
243. if(oldParentId == newParentId && minIndex != maxIndex){
244. // 在同一个父节点下发生移动 245. if(minIndex < maxIndex){
246. // 当要移动的节点的序号小于要移动到的目标序号,则下移
247. this.downNode(oldParentId, minIndex, maxIndex);
248. }else if(minIndex > maxIndex){
249. // 当要移动的节点的序号大于要移动到的目标序号,则上移
250. maxIndex = minIndex; 251. minIndex = nodeIndex;
252. this.upNode(oldParentId, minIndex, maxIndex);
253. }
254. // 节点本身的序号设置成要移动到的目标序号 255. obj.setNumber(nodeIndex); 256. this.update(obj); 257. }
258. if(oldParentId != newParentId){ 259. // 在不同父节点下发生移动
260. //1、相当于要移动的节点在原父节点下下移到最后再删除掉,因此要指定移动发生时节点所在的位置
261. this.downNode(oldParentId, minIndex, -1); 262. //2、相当于要移动的节点在新父节点下上移到指定的位置,因此需要指定要移动到的位置
263. this.upNode(newParentId, maxIndex, -1); 264. // 节点本身的序号设置成要移动到的目标序号 265. obj.setNumber(nodeIndex); 266. obj.setParentId(newParentId); 267. this.update(obj); 268. } 269. } 270. /**
271. * 指定的节点下移
272. * @param parentId 指定范围内要移动的节点的父节点 273. * @param minIndex 指定节点移动发生时所在的位置 274. * @param maxIndex 指定节点要移动到的目标位置
9. import javax.servlet.http.HttpServletResponse; 10.
11.import com.demo.navigate.model.Navigate;
12.import com.demo.navigate.service.NavigateManager; 13.
14.@SuppressWarnings(\
15.public class NavigateSaveServlet extends HttpServlet { 16.
17. public void doGet(HttpServletRequest request, HttpServletResponse response)
18. throws ServletException, IOException { 19. this.doPost(request, response); 20. }
21. public void doPost(HttpServletRequest request, HttpServletResponse response)
22. throws ServletException, IOException {
23. NavigateManager navigateManager = new NavigateManager();
24. Navigate obj = null;
25. request.setCharacterEncoding(\26. String id = request.getParameter(\
27. String number = request.getParameter(\
28. String parentId = request.getParameter(\29. String leaf = request.getParameter(\30. String title = request.getParameter(\31. String url = request.getParameter(\32.
33. if(null != id && !\34. obj = navigateManager.get(id); 35. if(obj == null){
36. RequestDispatcher dispatcher = request.getRequestDispatcher(\
37. dispatcher.forward(request, response); 38. return; 39. } 40. }else{
41. obj = new Navigate();
42. obj.setLeaf(new Integer(leaf));
43. obj.setParentId(new Integer(parentId)); 44. }
45. obj.setNumber(new Integer(number)); 46. obj.setTitle(title); 47. obj.setUrl(url);
48. if(null != id && !\
49. navigateManager.update(obj); 50. }else{
51. navigateManager.save(obj); 52. }
53. RequestDispatcher dispatcher = request.getRequestDispatcher(\
54. dispatcher.forward(request, response); 55. } 56. 57.}
c)json Java代码
1. package com.demo.navigate.web; 2.
3. import java.io.IOException; 4.
5. import javax.servlet.RequestDispatcher; 6. import javax.servlet.ServletException; 7. import javax.servlet.http.HttpServlet;
8. import javax.servlet.http.HttpServletRequest; 9. import javax.servlet.http.HttpServletResponse; 10.
11.import com.demo.navigate.service.NavigateManager; 12.
13.@SuppressWarnings(\
14.public class NavigateJsonServlet extends HttpServlet {
15. public void doGet(HttpServletRequest request, HttpServletResponse response)
16. throws ServletException, IOException { 17. this.doPost(request, response); 18. }
19. public void doPost(HttpServletRequest request, HttpServletResponse response)
20. throws ServletException, IOException { 21.
22. NavigateManager navigateManager = new NavigateManager();
23. request.setAttribute(\nById(new Integer(request.getParameter(\
24. RequestDispatcher dispatcher = request.getRequestDispatcher(\
25. dispatcher.forward(request, response); 26. } 27. 28.}
页面: 1、edit Html代码
1. <%@ page contentType=\ %>
2. <%@ taglib uri=\ prefix=\ %>
3. <%@ include file=\%> 4. 5.
6.
8.
9. 10. 11. 12.
13.
14. 26.
27.
28.29. 51. 52.
2、success Html代码
1. <%@ page language=\ contentType=\
2. pageEncoding=\%>
3.
4. 5.
6.
7.
14.
15. 恭喜,信息更新成功! 16.
3、json Html代码
1. <%@ page contentType=\ %>
2. <%@ taglib uri=\ prefix=\ %>
3. <%@ taglib uri=\ prefix=\ %> 4.
5.
7.
9. id:'${obj.id}',
10. text:'${obj.title}',
11.
14. singleClickExpand:true 15.}
16.
178. }
179. if(!navEditor){
180. navEditor = new Ext.tree.TreeEditor(nav, {
181. allowBlank : false, 182. ignoreNoChange : true,
183. blankText : '标题不能为空', 184. selectOnFocus : true 185. }); 186. }
187. this.setLeafMenu(); 188. this.setDirMenu(); 189. },
190. setMgr : function(manager){ 191. mgr = manager; 192. },
193. getMgr : function(){ 194. return mgr; 195. },
196. setLeafMenu: function(){ 197. // 设置叶子菜单 198. if(!leafMenu){
199. leafMenu = new Ext.menu.Menu({ 200. items : [{
201. text : \修改标题\202. handler : function() {
203. navEditor.triggerEdit(nodeSelected);
204. } 205. }, \
206. text : \编辑\
207. handler : function() {
208. FormEditWin.showEditLeafWin(nodeSelected);
209. } 210. }, \
211. text : \删除\
212. handler : this.delTreeItemComfirm
213. }] 214. }); 215. } 216. },
217. setDirMenu: function(){
218. // 设置目录菜单 219. if(!dirMenu){
220. dirMenu = new Ext.menu.Menu({ 221. items : [{
222. text : \修改标题\223. handler : function() {
224. navEditor.triggerEdit(nodeSelected);
225. } 226. }, \
227. text : \228. handler : function() {
229. FormEditWin.showEditDirWin(nodeSelected);
230. } 231. }, \
232. text : \233. handler : function() {
234. FormEditWin.showAddLeafWin(nodeSelected);
235. } 236. }, \
237. text : \238. handler : function() {
239. FormEditWin.showAddDirWin(nodeSelected);
240. } 241. }, \
242. text : \243. handler : this.delTreeItemComfirm
244. }] 245. }); 246. } 247. },
248. showTreeMenu : function(node, e){ 249. nodeSelected = node; 250. nodeSelected.select(); 251. if (node.isLeaf()) { 252. // 253. leafMenu.showAt(e.getPoint()); 254. } else {
255. // 256. dirMenu.showAt(e.getPoint());
编辑\
添加叶子节点\添加目录节点\删除\
显示叶子节点菜单
显示目录节点菜单
257. } 258. },
259. delTreeItemComfirm : function(){
260. Ext.Msg.confirm(\确认删除\确定要删除所选节点吗?\
261. if (btn == \
262. NavTree.delTreeItem(); 263. } 264. }); 265. },
266. delTreeItem : function(){
267. if (nodeSelected != nav.getRootNode()) { 268. removeFlag = true; 269. nodeSelected.remove(); 270. removeFlag = false; 271. } else {
272. Ext.Msg.alert(\警告\不能删除树的根节点!\
273. } 274. },
275. show : function(){
276. nav.render(Ext.getBody()); 277. nav.getRootNode().toggle(); 278. } 279. } 280. }(); 281.
282. // 文档加载完毕执行 283. Ext.onReady(function(){
284. Ext.BLANK_IMAGE_URL = \/default/s.gif\
285. if(typeof(NavigateManager)==\
286. Ext.Msg.alert(\警告提示\请先设置DWR,并实例化NavigateManager\287. }else{
288. NavTree.setMgr(NavigateManager); 289. NavTree.init(); 290. NavTree.show(); 291. } 292. });
dwr配置: dwr.xml Xml代码
1.
2. 3.
4.
5.
6. 8. value=\r\> 9. 10.
servlet配置: web.xml Xml代码
1. 2. 3. xmlns=\ 4. xmlns:xsi=\ 5. xsi:schemaLocation=\6. http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd\> 7. 8. 10. com.demo.navigate.web.NavigateJsonServlet 11. 12. 13. 14. 16. com.demo.navigate.web.NavigateEditServlet 17. 18. 19. 20. 22. com.demo.navigate.web.NavigateSaveServlet 23. 24. 25. 26. 30. 34. 38. 39. 40. 41. 45. 46. allowGetForSafariButMakeForgeryEasier 47. 48. 50. 52. 53. 57.
正在阅读:
Extjs动态树的实现以及节点拖拽07-04
精选-地理人教版必修1练习:第一章 章末总结提升 word版含解析-文档资料01-04
橡胶技术基础知识问答06-13
第5章习题答案06-06
工厂管理巡查制度 - 图文06-30
煤焦化车间管理制度岗位职责汇编104-01
2018教师个人学习计划12-11
夜行作文800字06-25
2012年模具加工车间考核制度12-28
我爱老师作文600字02-05
- 多层物业服务方案
- (审判实务)习惯法与少数民族地区民间纠纷解决问题(孙 潋)
- 人教版新课标六年级下册语文全册教案
- 词语打卡
- photoshop实习报告
- 钢结构设计原理综合测试2
- 2014年期末练习题
- 高中数学中的逆向思维解题方法探讨
- 名师原创 全国通用2014-2015学年高二寒假作业 政治(一)Word版
- 北航《建筑结构检测鉴定与加固》在线作业三
- XX县卫生监督所工程建设项目可行性研究报告
- 小学四年级观察作文经典评语
- 浅谈110KV变电站电气一次设计-程泉焱(1)
- 安全员考试题库
- 国家电网公司变电运维管理规定(试行)
- 义务教育课程标准稿征求意见提纲
- 教学秘书面试技巧
- 钢结构工程施工组织设计
- 水利工程概论论文
- 09届九年级数学第四次模拟试卷
- 节点
- 以及
- 实现
- 动态
- Extjs
- 六年级数学总复习题(五)
- 《编译原理》模拟期末试题汇总 6套,含答案
- 钢管支架贝雷梁拆除施工方案
- NetBackup备份实施方案(NBU)
- 火灾自动报警资料附录A - 图文
- 第一篇五连 - 词学习的啊学习的武器学习的武器
- 2005—2013年山东高考作文题分析解读(全面详细)
- 2018-2019灯具市场调研报告(精选多篇)-范文模板(16页)
- 土建可行性研究毕业设计 - 图文
- 丰田车型英文对照年份表-超全的 - 图文
- 标签机的正确使用方法
- 湖南文艺出版社小学一年级上册全册音乐教案
- 年产xx吨全脂乳粉工厂设计
- 癸水日干十二月令论时间吉凶
- 学校应成为精神文明建设的重要窗口
- 四轴飞行器毕业设计(论文) - 图文
- 2016新课标高考压轴卷数学解析
- 《计算机接口技术》练习题A
- 人教版八年级下册期末考试试题及答案
- 受贿罪和行贿罪是怎样量刑的