Extjs动态树的实现以及节点拖拽

更新时间:2024-07-04 09:41:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

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 getChildrenById(Integer id){ 88. List list = new ArrayList(); 89. Connection conection = null; 90. Statement stmt = null; 91. ResultSet rs = null; 92. try{

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. 7. 菜单编辑

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. 信息更新成功 8. 12. 13.

14.

15. 恭喜,信息更新成功! 16.

17. 18.

3、json Html代码

1. <%@ page contentType=\ %>

2. <%@ taglib uri=\ prefix=\ %>

3. <%@ taglib uri=\ prefix=\ %> 4.

5. 6. [

7. 8. {

9. id:'${obj.id}',

10. text:'${obj.title}',

11. 12. leaf:true, 13.

14. singleClickExpand:true 15.}

16. , 17. 18.]

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. 7.

8. value=\r\>

9.

10. 11. 12. 13. 14. 15.

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. navigatejson 9.

10. com.demo.navigate.web.NavigateJsonServlet 11. 12. 13.

14. navigateedit 15.

16. com.demo.navigate.web.NavigateEditServlet 17.

18. 19.

20. navigatesave 21.

22. com.demo.navigate.web.NavigateSaveServlet 23. 24.

25.

26. navigatejson 27. /navigatejson 28. 29.

30. navigateedit 31. /navigateedit 32. 33.

34. navigatesave 35. /navigatesave 36. 37.

38. dwr-invoker

39. uk.ltd.getahead.dwr.DWRServlet

40.

41. debug 42. true 43. 44.

45.

46. allowGetForSafariButMakeForgeryEasier 47.

48. true 49.

50. 1 51.

52.

53. dwr-invoker 54. /dwr/* 55. 56.

57. index.jsp 58. 59.

本文来源:https://www.bwwdw.com/article/16n.html

Top