lpmp 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (636) hide show
  1. data/LICENSE +3 -0
  2. data/README +3 -0
  3. data/Rakefile +45 -0
  4. data/bin/lpmp +107 -0
  5. data/config/help.yaml +1 -0
  6. data/config/hosts.yaml +2 -0
  7. data/config/log.yaml +1 -0
  8. data/config/memcache.yaml +5 -0
  9. data/erb/index.erb +62 -0
  10. data/lib/bg_pull/caichen.rb +199 -0
  11. data/lib/bg_pull/lpmp.rb +45 -0
  12. data/lib/exception.rb +8 -0
  13. data/lib/lpmp.rb +53 -0
  14. data/lib/pull/lpmp.rb +355 -0
  15. data/lib/remote_lmp.rb +129 -0
  16. data/lib/utils.rb +14 -0
  17. data/lib/xq_push/caichen.rb +174 -0
  18. data/lib/xq_push/lpmp.rb +96 -0
  19. data/log/lpmp1st.log +1 -0
  20. data/public/css/ext-portal.css +40 -0
  21. data/public/css/lpmp.css +6 -0
  22. data/public/designer/caichen.epj +1 -0
  23. data/public/designer/hostmonitor.epj +1 -0
  24. data/public/ext-3.0.0/INCLUDE_ORDER.txt +35 -0
  25. data/public/ext-3.0.0/adapter/ext/ext-base-debug.js +3589 -0
  26. data/public/ext-3.0.0/adapter/ext/ext-base.js +7 -0
  27. data/public/ext-3.0.0/adapter/jquery/ext-jquery-adapter-debug.js +2292 -0
  28. data/public/ext-3.0.0/adapter/jquery/ext-jquery-adapter.js +7 -0
  29. data/public/ext-3.0.0/adapter/prototype/ext-prototype-adapter-debug.js +2346 -0
  30. data/public/ext-3.0.0/adapter/prototype/ext-prototype-adapter.js +7 -0
  31. data/public/ext-3.0.0/adapter/yui/ext-yui-adapter-debug.js +2136 -0
  32. data/public/ext-3.0.0/adapter/yui/ext-yui-adapter.js +7 -0
  33. data/public/ext-3.0.0/ext-all-debug.js +65610 -0
  34. data/public/ext-3.0.0/ext-all.js +11 -0
  35. data/public/ext-3.0.0/license.txt +42 -0
  36. data/public/ext-3.0.0/pkgs/cmp-foundation-debug.js +11287 -0
  37. data/public/ext-3.0.0/pkgs/cmp-foundation.js +7 -0
  38. data/public/ext-3.0.0/pkgs/data-foundation-debug.js +3853 -0
  39. data/public/ext-3.0.0/pkgs/data-foundation.js +7 -0
  40. data/public/ext-3.0.0/pkgs/data-grouping-debug.js +139 -0
  41. data/public/ext-3.0.0/pkgs/data-grouping.js +7 -0
  42. data/public/ext-3.0.0/pkgs/data-json-debug.js +582 -0
  43. data/public/ext-3.0.0/pkgs/data-json.js +7 -0
  44. data/public/ext-3.0.0/pkgs/data-list-views-debug.js +1278 -0
  45. data/public/ext-3.0.0/pkgs/data-list-views.js +7 -0
  46. data/public/ext-3.0.0/pkgs/data-xml-debug.js +234 -0
  47. data/public/ext-3.0.0/pkgs/data-xml.js +7 -0
  48. data/public/ext-3.0.0/pkgs/direct-debug.js +1121 -0
  49. data/public/ext-3.0.0/pkgs/direct.js +7 -0
  50. data/public/ext-3.0.0/pkgs/ext-dd-debug.js +4567 -0
  51. data/public/ext-3.0.0/pkgs/ext-dd.js +7 -0
  52. data/public/ext-3.0.0/pkgs/ext-foundation-debug.js +13417 -0
  53. data/public/ext-3.0.0/pkgs/ext-foundation.js +7 -0
  54. data/public/ext-3.0.0/pkgs/pkg-buttons-debug.js +1060 -0
  55. data/public/ext-3.0.0/pkgs/pkg-buttons.js +7 -0
  56. data/public/ext-3.0.0/pkgs/pkg-charts-debug.js +1621 -0
  57. data/public/ext-3.0.0/pkgs/pkg-charts.js +10 -0
  58. data/public/ext-3.0.0/pkgs/pkg-forms-debug.js +7661 -0
  59. data/public/ext-3.0.0/pkgs/pkg-forms.js +7 -0
  60. data/public/ext-3.0.0/pkgs/pkg-grid-editor-debug.js +560 -0
  61. data/public/ext-3.0.0/pkgs/pkg-grid-editor.js +7 -0
  62. data/public/ext-3.0.0/pkgs/pkg-grid-foundation-debug.js +4765 -0
  63. data/public/ext-3.0.0/pkgs/pkg-grid-foundation.js +7 -0
  64. data/public/ext-3.0.0/pkgs/pkg-grid-grouping-debug.js +517 -0
  65. data/public/ext-3.0.0/pkgs/pkg-grid-grouping.js +7 -0
  66. data/public/ext-3.0.0/pkgs/pkg-grid-property-debug.js +370 -0
  67. data/public/ext-3.0.0/pkgs/pkg-grid-property.js +7 -0
  68. data/public/ext-3.0.0/pkgs/pkg-history-debug.js +203 -0
  69. data/public/ext-3.0.0/pkgs/pkg-history.js +7 -0
  70. data/public/ext-3.0.0/pkgs/pkg-menu-debug.js +1628 -0
  71. data/public/ext-3.0.0/pkgs/pkg-menu.js +7 -0
  72. data/public/ext-3.0.0/pkgs/pkg-tabs-debug.js +1100 -0
  73. data/public/ext-3.0.0/pkgs/pkg-tabs.js +7 -0
  74. data/public/ext-3.0.0/pkgs/pkg-tips-debug.js +994 -0
  75. data/public/ext-3.0.0/pkgs/pkg-tips.js +7 -0
  76. data/public/ext-3.0.0/pkgs/pkg-toolbars-debug.js +1374 -0
  77. data/public/ext-3.0.0/pkgs/pkg-toolbars.js +7 -0
  78. data/public/ext-3.0.0/pkgs/pkg-tree-debug.js +4522 -0
  79. data/public/ext-3.0.0/pkgs/pkg-tree.js +7 -0
  80. data/public/ext-3.0.0/pkgs/resizable-debug.js +760 -0
  81. data/public/ext-3.0.0/pkgs/resizable.js +7 -0
  82. data/public/ext-3.0.0/pkgs/state-debug.js +274 -0
  83. data/public/ext-3.0.0/pkgs/state.js +7 -0
  84. data/public/ext-3.0.0/pkgs/window-debug.js +1888 -0
  85. data/public/ext-3.0.0/pkgs/window.js +7 -0
  86. data/public/ext-3.0.0/resources/charts.swf +0 -0
  87. data/public/ext-3.0.0/resources/css/README.txt +3 -0
  88. data/public/ext-3.0.0/resources/css/ext-all-notheme.css +5345 -0
  89. data/public/ext-3.0.0/resources/css/ext-all.css +6990 -0
  90. data/public/ext-3.0.0/resources/css/reset-min.css +7 -0
  91. data/public/ext-3.0.0/resources/css/structure/borders.css +54 -0
  92. data/public/ext-3.0.0/resources/css/structure/box.css +80 -0
  93. data/public/ext-3.0.0/resources/css/structure/button.css +440 -0
  94. data/public/ext-3.0.0/resources/css/structure/combo.css +45 -0
  95. data/public/ext-3.0.0/resources/css/structure/core.css +326 -0
  96. data/public/ext-3.0.0/resources/css/structure/date-picker.css +265 -0
  97. data/public/ext-3.0.0/resources/css/structure/dd.css +61 -0
  98. data/public/ext-3.0.0/resources/css/structure/debug.css +26 -0
  99. data/public/ext-3.0.0/resources/css/structure/dialog.css +62 -0
  100. data/public/ext-3.0.0/resources/css/structure/editor.css +92 -0
  101. data/public/ext-3.0.0/resources/css/structure/form.css +562 -0
  102. data/public/ext-3.0.0/resources/css/structure/grid.css +552 -0
  103. data/public/ext-3.0.0/resources/css/structure/layout.css +296 -0
  104. data/public/ext-3.0.0/resources/css/structure/list-view.css +85 -0
  105. data/public/ext-3.0.0/resources/css/structure/menu.css +205 -0
  106. data/public/ext-3.0.0/resources/css/structure/panel-reset.css +130 -0
  107. data/public/ext-3.0.0/resources/css/structure/panel.css +468 -0
  108. data/public/ext-3.0.0/resources/css/structure/progress.css +42 -0
  109. data/public/ext-3.0.0/resources/css/structure/qtips.css +153 -0
  110. data/public/ext-3.0.0/resources/css/structure/reset.css +7 -0
  111. data/public/ext-3.0.0/resources/css/structure/resizable.css +149 -0
  112. data/public/ext-3.0.0/resources/css/structure/slider.css +103 -0
  113. data/public/ext-3.0.0/resources/css/structure/tabs.css +372 -0
  114. data/public/ext-3.0.0/resources/css/structure/toolbar.css +259 -0
  115. data/public/ext-3.0.0/resources/css/structure/tree.css +203 -0
  116. data/public/ext-3.0.0/resources/css/structure/window.css +222 -0
  117. data/public/ext-3.0.0/resources/css/visual/borders.css +25 -0
  118. data/public/ext-3.0.0/resources/css/visual/box.css +74 -0
  119. data/public/ext-3.0.0/resources/css/visual/button.css +94 -0
  120. data/public/ext-3.0.0/resources/css/visual/combo.css +43 -0
  121. data/public/ext-3.0.0/resources/css/visual/core.css +76 -0
  122. data/public/ext-3.0.0/resources/css/visual/date-picker.css +143 -0
  123. data/public/ext-3.0.0/resources/css/visual/dd.css +29 -0
  124. data/public/ext-3.0.0/resources/css/visual/debug.css +24 -0
  125. data/public/ext-3.0.0/resources/css/visual/dialog.css +34 -0
  126. data/public/ext-3.0.0/resources/css/visual/editor.css +13 -0
  127. data/public/ext-3.0.0/resources/css/visual/form.css +117 -0
  128. data/public/ext-3.0.0/resources/css/visual/grid.css +272 -0
  129. data/public/ext-3.0.0/resources/css/visual/layout.css +53 -0
  130. data/public/ext-3.0.0/resources/css/visual/list-view.css +37 -0
  131. data/public/ext-3.0.0/resources/css/visual/menu.css +82 -0
  132. data/public/ext-3.0.0/resources/css/visual/panel.css +87 -0
  133. data/public/ext-3.0.0/resources/css/visual/progress.css +32 -0
  134. data/public/ext-3.0.0/resources/css/visual/qtips.css +44 -0
  135. data/public/ext-3.0.0/resources/css/visual/resizable.css +43 -0
  136. data/public/ext-3.0.0/resources/css/visual/slider.css +21 -0
  137. data/public/ext-3.0.0/resources/css/visual/tabs.css +119 -0
  138. data/public/ext-3.0.0/resources/css/visual/toolbar.css +103 -0
  139. data/public/ext-3.0.0/resources/css/visual/tree.css +157 -0
  140. data/public/ext-3.0.0/resources/css/visual/window.css +86 -0
  141. data/public/ext-3.0.0/resources/css/xtheme-blue.css +1652 -0
  142. data/public/ext-3.0.0/resources/expressinstall.swf +0 -0
  143. data/public/ext-3.0.0/resources/images/default/box/corners-blue.gif +0 -0
  144. data/public/ext-3.0.0/resources/images/default/box/corners.gif +0 -0
  145. data/public/ext-3.0.0/resources/images/default/box/l-blue.gif +0 -0
  146. data/public/ext-3.0.0/resources/images/default/box/l.gif +0 -0
  147. data/public/ext-3.0.0/resources/images/default/box/r-blue.gif +0 -0
  148. data/public/ext-3.0.0/resources/images/default/box/r.gif +0 -0
  149. data/public/ext-3.0.0/resources/images/default/box/tb-blue.gif +0 -0
  150. data/public/ext-3.0.0/resources/images/default/box/tb.gif +0 -0
  151. data/public/ext-3.0.0/resources/images/default/button/arrow.gif +0 -0
  152. data/public/ext-3.0.0/resources/images/default/button/btn.gif +0 -0
  153. data/public/ext-3.0.0/resources/images/default/button/group-cs.gif +0 -0
  154. data/public/ext-3.0.0/resources/images/default/button/group-lr.gif +0 -0
  155. data/public/ext-3.0.0/resources/images/default/button/group-tb.gif +0 -0
  156. data/public/ext-3.0.0/resources/images/default/button/s-arrow-b-noline.gif +0 -0
  157. data/public/ext-3.0.0/resources/images/default/button/s-arrow-b.gif +0 -0
  158. data/public/ext-3.0.0/resources/images/default/button/s-arrow-bo.gif +0 -0
  159. data/public/ext-3.0.0/resources/images/default/button/s-arrow-noline.gif +0 -0
  160. data/public/ext-3.0.0/resources/images/default/button/s-arrow-o.gif +0 -0
  161. data/public/ext-3.0.0/resources/images/default/button/s-arrow.gif +0 -0
  162. data/public/ext-3.0.0/resources/images/default/dd/drop-add.gif +0 -0
  163. data/public/ext-3.0.0/resources/images/default/dd/drop-no.gif +0 -0
  164. data/public/ext-3.0.0/resources/images/default/dd/drop-yes.gif +0 -0
  165. data/public/ext-3.0.0/resources/images/default/editor/tb-sprite.gif +0 -0
  166. data/public/ext-3.0.0/resources/images/default/form/checkbox.gif +0 -0
  167. data/public/ext-3.0.0/resources/images/default/form/clear-trigger.gif +0 -0
  168. data/public/ext-3.0.0/resources/images/default/form/clear-trigger.psd +0 -0
  169. data/public/ext-3.0.0/resources/images/default/form/date-trigger.gif +0 -0
  170. data/public/ext-3.0.0/resources/images/default/form/date-trigger.psd +0 -0
  171. data/public/ext-3.0.0/resources/images/default/form/error-tip-corners.gif +0 -0
  172. data/public/ext-3.0.0/resources/images/default/form/exclamation.gif +0 -0
  173. data/public/ext-3.0.0/resources/images/default/form/radio.gif +0 -0
  174. data/public/ext-3.0.0/resources/images/default/form/search-trigger.gif +0 -0
  175. data/public/ext-3.0.0/resources/images/default/form/search-trigger.psd +0 -0
  176. data/public/ext-3.0.0/resources/images/default/form/text-bg.gif +0 -0
  177. data/public/ext-3.0.0/resources/images/default/form/trigger-tpl.gif +0 -0
  178. data/public/ext-3.0.0/resources/images/default/form/trigger.gif +0 -0
  179. data/public/ext-3.0.0/resources/images/default/form/trigger.psd +0 -0
  180. data/public/ext-3.0.0/resources/images/default/gradient-bg.gif +0 -0
  181. data/public/ext-3.0.0/resources/images/default/grid/arrow-left-white.gif +0 -0
  182. data/public/ext-3.0.0/resources/images/default/grid/arrow-right-white.gif +0 -0
  183. data/public/ext-3.0.0/resources/images/default/grid/col-move-bottom.gif +0 -0
  184. data/public/ext-3.0.0/resources/images/default/grid/col-move-top.gif +0 -0
  185. data/public/ext-3.0.0/resources/images/default/grid/columns.gif +0 -0
  186. data/public/ext-3.0.0/resources/images/default/grid/dirty.gif +0 -0
  187. data/public/ext-3.0.0/resources/images/default/grid/done.gif +0 -0
  188. data/public/ext-3.0.0/resources/images/default/grid/drop-no.gif +0 -0
  189. data/public/ext-3.0.0/resources/images/default/grid/drop-yes.gif +0 -0
  190. data/public/ext-3.0.0/resources/images/default/grid/footer-bg.gif +0 -0
  191. data/public/ext-3.0.0/resources/images/default/grid/grid-blue-hd.gif +0 -0
  192. data/public/ext-3.0.0/resources/images/default/grid/grid-blue-split.gif +0 -0
  193. data/public/ext-3.0.0/resources/images/default/grid/grid-hrow.gif +0 -0
  194. data/public/ext-3.0.0/resources/images/default/grid/grid-loading.gif +0 -0
  195. data/public/ext-3.0.0/resources/images/default/grid/grid-split.gif +0 -0
  196. data/public/ext-3.0.0/resources/images/default/grid/grid-vista-hd.gif +0 -0
  197. data/public/ext-3.0.0/resources/images/default/grid/grid3-hd-btn.gif +0 -0
  198. data/public/ext-3.0.0/resources/images/default/grid/grid3-hrow-over.gif +0 -0
  199. data/public/ext-3.0.0/resources/images/default/grid/grid3-hrow.gif +0 -0
  200. data/public/ext-3.0.0/resources/images/default/grid/grid3-special-col-bg.gif +0 -0
  201. data/public/ext-3.0.0/resources/images/default/grid/grid3-special-col-sel-bg.gif +0 -0
  202. data/public/ext-3.0.0/resources/images/default/grid/group-by.gif +0 -0
  203. data/public/ext-3.0.0/resources/images/default/grid/group-collapse.gif +0 -0
  204. data/public/ext-3.0.0/resources/images/default/grid/group-expand-sprite.gif +0 -0
  205. data/public/ext-3.0.0/resources/images/default/grid/group-expand.gif +0 -0
  206. data/public/ext-3.0.0/resources/images/default/grid/hd-pop.gif +0 -0
  207. data/public/ext-3.0.0/resources/images/default/grid/hmenu-asc.gif +0 -0
  208. data/public/ext-3.0.0/resources/images/default/grid/hmenu-desc.gif +0 -0
  209. data/public/ext-3.0.0/resources/images/default/grid/hmenu-lock.gif +0 -0
  210. data/public/ext-3.0.0/resources/images/default/grid/hmenu-lock.png +0 -0
  211. data/public/ext-3.0.0/resources/images/default/grid/hmenu-unlock.gif +0 -0
  212. data/public/ext-3.0.0/resources/images/default/grid/hmenu-unlock.png +0 -0
  213. data/public/ext-3.0.0/resources/images/default/grid/invalid_line.gif +0 -0
  214. data/public/ext-3.0.0/resources/images/default/grid/loading.gif +0 -0
  215. data/public/ext-3.0.0/resources/images/default/grid/mso-hd.gif +0 -0
  216. data/public/ext-3.0.0/resources/images/default/grid/nowait.gif +0 -0
  217. data/public/ext-3.0.0/resources/images/default/grid/page-first-disabled.gif +0 -0
  218. data/public/ext-3.0.0/resources/images/default/grid/page-first.gif +0 -0
  219. data/public/ext-3.0.0/resources/images/default/grid/page-last-disabled.gif +0 -0
  220. data/public/ext-3.0.0/resources/images/default/grid/page-last.gif +0 -0
  221. data/public/ext-3.0.0/resources/images/default/grid/page-next-disabled.gif +0 -0
  222. data/public/ext-3.0.0/resources/images/default/grid/page-next.gif +0 -0
  223. data/public/ext-3.0.0/resources/images/default/grid/page-prev-disabled.gif +0 -0
  224. data/public/ext-3.0.0/resources/images/default/grid/page-prev.gif +0 -0
  225. data/public/ext-3.0.0/resources/images/default/grid/pick-button.gif +0 -0
  226. data/public/ext-3.0.0/resources/images/default/grid/refresh.gif +0 -0
  227. data/public/ext-3.0.0/resources/images/default/grid/row-check-sprite.gif +0 -0
  228. data/public/ext-3.0.0/resources/images/default/grid/row-expand-sprite.gif +0 -0
  229. data/public/ext-3.0.0/resources/images/default/grid/row-over.gif +0 -0
  230. data/public/ext-3.0.0/resources/images/default/grid/row-sel.gif +0 -0
  231. data/public/ext-3.0.0/resources/images/default/grid/sort-hd.gif +0 -0
  232. data/public/ext-3.0.0/resources/images/default/grid/sort_asc.gif +0 -0
  233. data/public/ext-3.0.0/resources/images/default/grid/sort_desc.gif +0 -0
  234. data/public/ext-3.0.0/resources/images/default/grid/wait.gif +0 -0
  235. data/public/ext-3.0.0/resources/images/default/layout/collapse.gif +0 -0
  236. data/public/ext-3.0.0/resources/images/default/layout/expand.gif +0 -0
  237. data/public/ext-3.0.0/resources/images/default/layout/gradient-bg.gif +0 -0
  238. data/public/ext-3.0.0/resources/images/default/layout/mini-bottom.gif +0 -0
  239. data/public/ext-3.0.0/resources/images/default/layout/mini-left.gif +0 -0
  240. data/public/ext-3.0.0/resources/images/default/layout/mini-right.gif +0 -0
  241. data/public/ext-3.0.0/resources/images/default/layout/mini-top.gif +0 -0
  242. data/public/ext-3.0.0/resources/images/default/layout/ns-collapse.gif +0 -0
  243. data/public/ext-3.0.0/resources/images/default/layout/ns-expand.gif +0 -0
  244. data/public/ext-3.0.0/resources/images/default/layout/panel-close.gif +0 -0
  245. data/public/ext-3.0.0/resources/images/default/layout/panel-title-bg.gif +0 -0
  246. data/public/ext-3.0.0/resources/images/default/layout/panel-title-light-bg.gif +0 -0
  247. data/public/ext-3.0.0/resources/images/default/layout/stick.gif +0 -0
  248. data/public/ext-3.0.0/resources/images/default/layout/stuck.gif +0 -0
  249. data/public/ext-3.0.0/resources/images/default/layout/tab-close-on.gif +0 -0
  250. data/public/ext-3.0.0/resources/images/default/layout/tab-close.gif +0 -0
  251. data/public/ext-3.0.0/resources/images/default/menu/checked.gif +0 -0
  252. data/public/ext-3.0.0/resources/images/default/menu/group-checked.gif +0 -0
  253. data/public/ext-3.0.0/resources/images/default/menu/item-over.gif +0 -0
  254. data/public/ext-3.0.0/resources/images/default/menu/menu-parent.gif +0 -0
  255. data/public/ext-3.0.0/resources/images/default/menu/menu.gif +0 -0
  256. data/public/ext-3.0.0/resources/images/default/menu/unchecked.gif +0 -0
  257. data/public/ext-3.0.0/resources/images/default/panel/corners-sprite.gif +0 -0
  258. data/public/ext-3.0.0/resources/images/default/panel/left-right.gif +0 -0
  259. data/public/ext-3.0.0/resources/images/default/panel/light-hd.gif +0 -0
  260. data/public/ext-3.0.0/resources/images/default/panel/tool-sprite-tpl.gif +0 -0
  261. data/public/ext-3.0.0/resources/images/default/panel/tool-sprites.gif +0 -0
  262. data/public/ext-3.0.0/resources/images/default/panel/tools-sprites-trans.gif +0 -0
  263. data/public/ext-3.0.0/resources/images/default/panel/top-bottom.gif +0 -0
  264. data/public/ext-3.0.0/resources/images/default/panel/top-bottom.png +0 -0
  265. data/public/ext-3.0.0/resources/images/default/panel/white-corners-sprite.gif +0 -0
  266. data/public/ext-3.0.0/resources/images/default/panel/white-left-right.gif +0 -0
  267. data/public/ext-3.0.0/resources/images/default/panel/white-top-bottom.gif +0 -0
  268. data/public/ext-3.0.0/resources/images/default/progress/progress-bg.gif +0 -0
  269. data/public/ext-3.0.0/resources/images/default/qtip/bg.gif +0 -0
  270. data/public/ext-3.0.0/resources/images/default/qtip/close.gif +0 -0
  271. data/public/ext-3.0.0/resources/images/default/qtip/tip-anchor-sprite.gif +0 -0
  272. data/public/ext-3.0.0/resources/images/default/qtip/tip-sprite.gif +0 -0
  273. data/public/ext-3.0.0/resources/images/default/s.gif +0 -0
  274. data/public/ext-3.0.0/resources/images/default/shadow-c.png +0 -0
  275. data/public/ext-3.0.0/resources/images/default/shadow-lr.png +0 -0
  276. data/public/ext-3.0.0/resources/images/default/shadow.png +0 -0
  277. data/public/ext-3.0.0/resources/images/default/shared/blue-loading.gif +0 -0
  278. data/public/ext-3.0.0/resources/images/default/shared/calendar.gif +0 -0
  279. data/public/ext-3.0.0/resources/images/default/shared/glass-bg.gif +0 -0
  280. data/public/ext-3.0.0/resources/images/default/shared/hd-sprite.gif +0 -0
  281. data/public/ext-3.0.0/resources/images/default/shared/large-loading.gif +0 -0
  282. data/public/ext-3.0.0/resources/images/default/shared/left-btn.gif +0 -0
  283. data/public/ext-3.0.0/resources/images/default/shared/loading-balls.gif +0 -0
  284. data/public/ext-3.0.0/resources/images/default/shared/right-btn.gif +0 -0
  285. data/public/ext-3.0.0/resources/images/default/shared/warning.gif +0 -0
  286. data/public/ext-3.0.0/resources/images/default/sizer/e-handle-dark.gif +0 -0
  287. data/public/ext-3.0.0/resources/images/default/sizer/e-handle.gif +0 -0
  288. data/public/ext-3.0.0/resources/images/default/sizer/ne-handle-dark.gif +0 -0
  289. data/public/ext-3.0.0/resources/images/default/sizer/ne-handle.gif +0 -0
  290. data/public/ext-3.0.0/resources/images/default/sizer/nw-handle-dark.gif +0 -0
  291. data/public/ext-3.0.0/resources/images/default/sizer/nw-handle.gif +0 -0
  292. data/public/ext-3.0.0/resources/images/default/sizer/s-handle-dark.gif +0 -0
  293. data/public/ext-3.0.0/resources/images/default/sizer/s-handle.gif +0 -0
  294. data/public/ext-3.0.0/resources/images/default/sizer/se-handle-dark.gif +0 -0
  295. data/public/ext-3.0.0/resources/images/default/sizer/se-handle.gif +0 -0
  296. data/public/ext-3.0.0/resources/images/default/sizer/square.gif +0 -0
  297. data/public/ext-3.0.0/resources/images/default/sizer/sw-handle-dark.gif +0 -0
  298. data/public/ext-3.0.0/resources/images/default/sizer/sw-handle.gif +0 -0
  299. data/public/ext-3.0.0/resources/images/default/slider/slider-bg.png +0 -0
  300. data/public/ext-3.0.0/resources/images/default/slider/slider-thumb.png +0 -0
  301. data/public/ext-3.0.0/resources/images/default/slider/slider-v-bg.png +0 -0
  302. data/public/ext-3.0.0/resources/images/default/slider/slider-v-thumb.png +0 -0
  303. data/public/ext-3.0.0/resources/images/default/tabs/scroll-left.gif +0 -0
  304. data/public/ext-3.0.0/resources/images/default/tabs/scroll-right.gif +0 -0
  305. data/public/ext-3.0.0/resources/images/default/tabs/scroller-bg.gif +0 -0
  306. data/public/ext-3.0.0/resources/images/default/tabs/tab-btm-inactive-left-bg.gif +0 -0
  307. data/public/ext-3.0.0/resources/images/default/tabs/tab-btm-inactive-right-bg.gif +0 -0
  308. data/public/ext-3.0.0/resources/images/default/tabs/tab-btm-left-bg.gif +0 -0
  309. data/public/ext-3.0.0/resources/images/default/tabs/tab-btm-right-bg.gif +0 -0
  310. data/public/ext-3.0.0/resources/images/default/tabs/tab-close.gif +0 -0
  311. data/public/ext-3.0.0/resources/images/default/tabs/tab-strip-bg.gif +0 -0
  312. data/public/ext-3.0.0/resources/images/default/tabs/tab-strip-bg.png +0 -0
  313. data/public/ext-3.0.0/resources/images/default/tabs/tab-strip-btm-bg.gif +0 -0
  314. data/public/ext-3.0.0/resources/images/default/tabs/tabs-sprite.gif +0 -0
  315. data/public/ext-3.0.0/resources/images/default/toolbar/bg.gif +0 -0
  316. data/public/ext-3.0.0/resources/images/default/toolbar/btn-arrow-light.gif +0 -0
  317. data/public/ext-3.0.0/resources/images/default/toolbar/btn-arrow.gif +0 -0
  318. data/public/ext-3.0.0/resources/images/default/toolbar/btn-over-bg.gif +0 -0
  319. data/public/ext-3.0.0/resources/images/default/toolbar/gray-bg.gif +0 -0
  320. data/public/ext-3.0.0/resources/images/default/toolbar/more.gif +0 -0
  321. data/public/ext-3.0.0/resources/images/default/toolbar/tb-bg.gif +0 -0
  322. data/public/ext-3.0.0/resources/images/default/toolbar/tb-btn-sprite.gif +0 -0
  323. data/public/ext-3.0.0/resources/images/default/toolbar/tb-xl-btn-sprite.gif +0 -0
  324. data/public/ext-3.0.0/resources/images/default/toolbar/tb-xl-sep.gif +0 -0
  325. data/public/ext-3.0.0/resources/images/default/tree/arrows.gif +0 -0
  326. data/public/ext-3.0.0/resources/images/default/tree/drop-add.gif +0 -0
  327. data/public/ext-3.0.0/resources/images/default/tree/drop-between.gif +0 -0
  328. data/public/ext-3.0.0/resources/images/default/tree/drop-no.gif +0 -0
  329. data/public/ext-3.0.0/resources/images/default/tree/drop-over.gif +0 -0
  330. data/public/ext-3.0.0/resources/images/default/tree/drop-under.gif +0 -0
  331. data/public/ext-3.0.0/resources/images/default/tree/drop-yes.gif +0 -0
  332. data/public/ext-3.0.0/resources/images/default/tree/elbow-end-minus-nl.gif +0 -0
  333. data/public/ext-3.0.0/resources/images/default/tree/elbow-end-minus.gif +0 -0
  334. data/public/ext-3.0.0/resources/images/default/tree/elbow-end-plus-nl.gif +0 -0
  335. data/public/ext-3.0.0/resources/images/default/tree/elbow-end-plus.gif +0 -0
  336. data/public/ext-3.0.0/resources/images/default/tree/elbow-end.gif +0 -0
  337. data/public/ext-3.0.0/resources/images/default/tree/elbow-line.gif +0 -0
  338. data/public/ext-3.0.0/resources/images/default/tree/elbow-minus-nl.gif +0 -0
  339. data/public/ext-3.0.0/resources/images/default/tree/elbow-minus.gif +0 -0
  340. data/public/ext-3.0.0/resources/images/default/tree/elbow-plus-nl.gif +0 -0
  341. data/public/ext-3.0.0/resources/images/default/tree/elbow-plus.gif +0 -0
  342. data/public/ext-3.0.0/resources/images/default/tree/elbow.gif +0 -0
  343. data/public/ext-3.0.0/resources/images/default/tree/folder-open.gif +0 -0
  344. data/public/ext-3.0.0/resources/images/default/tree/folder.gif +0 -0
  345. data/public/ext-3.0.0/resources/images/default/tree/leaf.gif +0 -0
  346. data/public/ext-3.0.0/resources/images/default/tree/loading.gif +0 -0
  347. data/public/ext-3.0.0/resources/images/default/tree/s.gif +0 -0
  348. data/public/ext-3.0.0/resources/images/default/window/icon-error.gif +0 -0
  349. data/public/ext-3.0.0/resources/images/default/window/icon-info.gif +0 -0
  350. data/public/ext-3.0.0/resources/images/default/window/icon-question.gif +0 -0
  351. data/public/ext-3.0.0/resources/images/default/window/icon-warning.gif +0 -0
  352. data/public/ext-3.0.0/resources/images/default/window/left-corners.png +0 -0
  353. data/public/ext-3.0.0/resources/images/default/window/left-corners.psd +0 -0
  354. data/public/ext-3.0.0/resources/images/default/window/left-right.png +0 -0
  355. data/public/ext-3.0.0/resources/images/default/window/left-right.psd +0 -0
  356. data/public/ext-3.0.0/resources/images/default/window/right-corners.png +0 -0
  357. data/public/ext-3.0.0/resources/images/default/window/right-corners.psd +0 -0
  358. data/public/ext-3.0.0/resources/images/default/window/top-bottom.png +0 -0
  359. data/public/ext-3.0.0/resources/images/default/window/top-bottom.psd +0 -0
  360. data/public/ext-3.0.0/resources/images/icon/chart.gif +0 -0
  361. data/public/ext-3.0.0/src/adapter/core/ext-base-ajax.js +371 -0
  362. data/public/ext-3.0.0/src/adapter/core/ext-base-anim-extra.js +301 -0
  363. data/public/ext-3.0.0/src/adapter/core/ext-base-anim.js +477 -0
  364. data/public/ext-3.0.0/src/adapter/core/ext-base-begin.js +18 -0
  365. data/public/ext-3.0.0/src/adapter/core/ext-base-dom.js +157 -0
  366. data/public/ext-3.0.0/src/adapter/core/ext-base-end.js +21 -0
  367. data/public/ext-3.0.0/src/adapter/core/ext-base-event.js +453 -0
  368. data/public/ext-3.0.0/src/adapter/core/ext-base-point.js +17 -0
  369. data/public/ext-3.0.0/src/adapter/core/ext-base-region.js +81 -0
  370. data/public/ext-3.0.0/src/adapter/ext-base-dom-more.js +9 -0
  371. data/public/ext-3.0.0/src/adapter/jquery-bridge.js +546 -0
  372. data/public/ext-3.0.0/src/adapter/prototype-bridge.js +600 -0
  373. data/public/ext-3.0.0/src/adapter/yui-bridge.js +390 -0
  374. data/public/ext-3.0.0/src/core/CompositeElement.js +136 -0
  375. data/public/ext-3.0.0/src/core/CompositeElementLite-more.js +102 -0
  376. data/public/ext-3.0.0/src/core/DomHelper-more.js +179 -0
  377. data/public/ext-3.0.0/src/core/Element-more.js +192 -0
  378. data/public/ext-3.0.0/src/core/Element.alignment.js +370 -0
  379. data/public/ext-3.0.0/src/core/Element.dd.js +46 -0
  380. data/public/ext-3.0.0/src/core/Element.fx-more.js +152 -0
  381. data/public/ext-3.0.0/src/core/Element.insertion-more.js +52 -0
  382. data/public/ext-3.0.0/src/core/Element.keys.js +48 -0
  383. data/public/ext-3.0.0/src/core/Element.legacy.js +42 -0
  384. data/public/ext-3.0.0/src/core/Element.position-more.js +165 -0
  385. data/public/ext-3.0.0/src/core/Element.scroll-more.js +110 -0
  386. data/public/ext-3.0.0/src/core/Element.style-more.js +318 -0
  387. data/public/ext-3.0.0/src/core/Error.js +81 -0
  388. data/public/ext-3.0.0/src/core/EventManager-more.js +334 -0
  389. data/public/ext-3.0.0/src/core/Ext-more.js +669 -0
  390. data/public/ext-3.0.0/src/core/Template-more.js +115 -0
  391. data/public/ext-3.0.0/src/core/core/CompositeElementLite.js +197 -0
  392. data/public/ext-3.0.0/src/core/core/DomHelper.js +378 -0
  393. data/public/ext-3.0.0/src/core/core/DomQuery.js +826 -0
  394. data/public/ext-3.0.0/src/core/core/Element.fx.js +324 -0
  395. data/public/ext-3.0.0/src/core/core/Element.insertion.js +147 -0
  396. data/public/ext-3.0.0/src/core/core/Element.js +945 -0
  397. data/public/ext-3.0.0/src/core/core/Element.position.js +303 -0
  398. data/public/ext-3.0.0/src/core/core/Element.scroll.js +58 -0
  399. data/public/ext-3.0.0/src/core/core/Element.style.js +439 -0
  400. data/public/ext-3.0.0/src/core/core/Element.traversal.js +176 -0
  401. data/public/ext-3.0.0/src/core/core/EventManager.js +623 -0
  402. data/public/ext-3.0.0/src/core/core/Ext.js +922 -0
  403. data/public/ext-3.0.0/src/core/core/Fx.js +1115 -0
  404. data/public/ext-3.0.0/src/core/core/Template.js +185 -0
  405. data/public/ext-3.0.0/src/data/Api.js +210 -0
  406. data/public/ext-3.0.0/src/data/ArrayReader.js +102 -0
  407. data/public/ext-3.0.0/src/data/ArrayStore.js +70 -0
  408. data/public/ext-3.0.0/src/data/DataField.js +249 -0
  409. data/public/ext-3.0.0/src/data/DataProxy.js +427 -0
  410. data/public/ext-3.0.0/src/data/DataReader.js +160 -0
  411. data/public/ext-3.0.0/src/data/DataWriter.js +201 -0
  412. data/public/ext-3.0.0/src/data/DirectProxy.js +141 -0
  413. data/public/ext-3.0.0/src/data/DirectStore.js +52 -0
  414. data/public/ext-3.0.0/src/data/GroupingStore.js +139 -0
  415. data/public/ext-3.0.0/src/data/HttpProxy.js +276 -0
  416. data/public/ext-3.0.0/src/data/JsonReader.js +311 -0
  417. data/public/ext-3.0.0/src/data/JsonStore.js +49 -0
  418. data/public/ext-3.0.0/src/data/JsonWriter.js +77 -0
  419. data/public/ext-3.0.0/src/data/MemoryProxy.js +69 -0
  420. data/public/ext-3.0.0/src/data/Record.js +400 -0
  421. data/public/ext-3.0.0/src/data/ScriptTagProxy.js +279 -0
  422. data/public/ext-3.0.0/src/data/SortTypes.js +91 -0
  423. data/public/ext-3.0.0/src/data/Store.js +1492 -0
  424. data/public/ext-3.0.0/src/data/StoreMgr.js +72 -0
  425. data/public/ext-3.0.0/src/data/Tree.js +785 -0
  426. data/public/ext-3.0.0/src/data/XmlReader.js +128 -0
  427. data/public/ext-3.0.0/src/data/XmlStore.js +75 -0
  428. data/public/ext-3.0.0/src/data/XmlWriter.js +45 -0
  429. data/public/ext-3.0.0/src/data/core/Connection.js +575 -0
  430. data/public/ext-3.0.0/src/dd/DDCore.js +2992 -0
  431. data/public/ext-3.0.0/src/dd/DragSource.js +365 -0
  432. data/public/ext-3.0.0/src/dd/DragTracker.js +217 -0
  433. data/public/ext-3.0.0/src/dd/DragZone.js +133 -0
  434. data/public/ext-3.0.0/src/dd/DropTarget.js +115 -0
  435. data/public/ext-3.0.0/src/dd/DropZone.js +262 -0
  436. data/public/ext-3.0.0/src/dd/Registry.js +127 -0
  437. data/public/ext-3.0.0/src/dd/ScrollManager.js +201 -0
  438. data/public/ext-3.0.0/src/dd/StatusProxy.js +171 -0
  439. data/public/ext-3.0.0/src/debug.js +906 -0
  440. data/public/ext-3.0.0/src/direct/Direct.js +235 -0
  441. data/public/ext-3.0.0/src/direct/Event.js +34 -0
  442. data/public/ext-3.0.0/src/direct/JsonProvider.js +45 -0
  443. data/public/ext-3.0.0/src/direct/PollingProvider.js +151 -0
  444. data/public/ext-3.0.0/src/direct/Provider.js +110 -0
  445. data/public/ext-3.0.0/src/direct/RemotingProvider.js +373 -0
  446. data/public/ext-3.0.0/src/direct/Transaction.js +32 -0
  447. data/public/ext-3.0.0/src/locale/ext-lang-af.js +184 -0
  448. data/public/ext-3.0.0/src/locale/ext-lang-bg.js +278 -0
  449. data/public/ext-3.0.0/src/locale/ext-lang-ca.js +315 -0
  450. data/public/ext-3.0.0/src/locale/ext-lang-cs.js +293 -0
  451. data/public/ext-3.0.0/src/locale/ext-lang-da.js +296 -0
  452. data/public/ext-3.0.0/src/locale/ext-lang-de.js +326 -0
  453. data/public/ext-3.0.0/src/locale/ext-lang-el_GR.js +309 -0
  454. data/public/ext-3.0.0/src/locale/ext-lang-en.js +335 -0
  455. data/public/ext-3.0.0/src/locale/ext-lang-en_GB.js +315 -0
  456. data/public/ext-3.0.0/src/locale/ext-lang-es.js +318 -0
  457. data/public/ext-3.0.0/src/locale/ext-lang-fa.js +272 -0
  458. data/public/ext-3.0.0/src/locale/ext-lang-fi.js +302 -0
  459. data/public/ext-3.0.0/src/locale/ext-lang-fr.js +335 -0
  460. data/public/ext-3.0.0/src/locale/ext-lang-fr_CA.js +218 -0
  461. data/public/ext-3.0.0/src/locale/ext-lang-gr.js +175 -0
  462. data/public/ext-3.0.0/src/locale/ext-lang-he.js +292 -0
  463. data/public/ext-3.0.0/src/locale/ext-lang-hr.js +295 -0
  464. data/public/ext-3.0.0/src/locale/ext-lang-hu.js +296 -0
  465. data/public/ext-3.0.0/src/locale/ext-lang-id.js +302 -0
  466. data/public/ext-3.0.0/src/locale/ext-lang-it.js +295 -0
  467. data/public/ext-3.0.0/src/locale/ext-lang-ja.js +318 -0
  468. data/public/ext-3.0.0/src/locale/ext-lang-ko.js +267 -0
  469. data/public/ext-3.0.0/src/locale/ext-lang-lt.js +333 -0
  470. data/public/ext-3.0.0/src/locale/ext-lang-lv.js +176 -0
  471. data/public/ext-3.0.0/src/locale/ext-lang-mk.js +176 -0
  472. data/public/ext-3.0.0/src/locale/ext-lang-nl.js +323 -0
  473. data/public/ext-3.0.0/src/locale/ext-lang-no_NB.js +294 -0
  474. data/public/ext-3.0.0/src/locale/ext-lang-no_NN.js +294 -0
  475. data/public/ext-3.0.0/src/locale/ext-lang-pl.js +304 -0
  476. data/public/ext-3.0.0/src/locale/ext-lang-pt.js +260 -0
  477. data/public/ext-3.0.0/src/locale/ext-lang-pt_BR.js +302 -0
  478. data/public/ext-3.0.0/src/locale/ext-lang-pt_PT.js +298 -0
  479. data/public/ext-3.0.0/src/locale/ext-lang-ro.js +295 -0
  480. data/public/ext-3.0.0/src/locale/ext-lang-ru.js +319 -0
  481. data/public/ext-3.0.0/src/locale/ext-lang-sk.js +182 -0
  482. data/public/ext-3.0.0/src/locale/ext-lang-sl.js +176 -0
  483. data/public/ext-3.0.0/src/locale/ext-lang-sr.js +179 -0
  484. data/public/ext-3.0.0/src/locale/ext-lang-sr_RS.js +178 -0
  485. data/public/ext-3.0.0/src/locale/ext-lang-sv_SE.js +178 -0
  486. data/public/ext-3.0.0/src/locale/ext-lang-th.js +294 -0
  487. data/public/ext-3.0.0/src/locale/ext-lang-tr.js +306 -0
  488. data/public/ext-3.0.0/src/locale/ext-lang-ukr.js +258 -0
  489. data/public/ext-3.0.0/src/locale/ext-lang-vn.js +181 -0
  490. data/public/ext-3.0.0/src/locale/ext-lang-zh_CN.js +174 -0
  491. data/public/ext-3.0.0/src/locale/ext-lang-zh_TW.js +178 -0
  492. data/public/ext-3.0.0/src/state/CookieProvider.js +91 -0
  493. data/public/ext-3.0.0/src/state/Provider.js +127 -0
  494. data/public/ext-3.0.0/src/state/StateManager.js +69 -0
  495. data/public/ext-3.0.0/src/util/CSS.js +161 -0
  496. data/public/ext-3.0.0/src/util/ClickRepeater.js +200 -0
  497. data/public/ext-3.0.0/src/util/Cookies.js +96 -0
  498. data/public/ext-3.0.0/src/util/Date.js +1317 -0
  499. data/public/ext-3.0.0/src/util/Format.js +356 -0
  500. data/public/ext-3.0.0/src/util/History.js +203 -0
  501. data/public/ext-3.0.0/src/util/KeyMap.js +242 -0
  502. data/public/ext-3.0.0/src/util/KeyNav.js +161 -0
  503. data/public/ext-3.0.0/src/util/MixedCollection.js +576 -0
  504. data/public/ext-3.0.0/src/util/Observable-more.js +178 -0
  505. data/public/ext-3.0.0/src/util/TextMetrics.js +131 -0
  506. data/public/ext-3.0.0/src/util/UpdateManager.js +536 -0
  507. data/public/ext-3.0.0/src/util/XTemplate.js +379 -0
  508. data/public/ext-3.0.0/src/util/core/DelayedTask.js +68 -0
  509. data/public/ext-3.0.0/src/util/core/JSON.js +174 -0
  510. data/public/ext-3.0.0/src/util/core/Observable.js +483 -0
  511. data/public/ext-3.0.0/src/util/core/TaskMgr.js +174 -0
  512. data/public/ext-3.0.0/src/widgets/Action.js +252 -0
  513. data/public/ext-3.0.0/src/widgets/BoxComponent.js +519 -0
  514. data/public/ext-3.0.0/src/widgets/Button.js +762 -0
  515. data/public/ext-3.0.0/src/widgets/ButtonGroup.js +103 -0
  516. data/public/ext-3.0.0/src/widgets/ColorPalette.js +148 -0
  517. data/public/ext-3.0.0/src/widgets/Component.js +1540 -0
  518. data/public/ext-3.0.0/src/widgets/ComponentMgr.js +159 -0
  519. data/public/ext-3.0.0/src/widgets/Container.js +894 -0
  520. data/public/ext-3.0.0/src/widgets/CycleButton.js +188 -0
  521. data/public/ext-3.0.0/src/widgets/DataView.js +749 -0
  522. data/public/ext-3.0.0/src/widgets/DatePicker.js +771 -0
  523. data/public/ext-3.0.0/src/widgets/Editor.js +385 -0
  524. data/public/ext-3.0.0/src/widgets/Layer.js +466 -0
  525. data/public/ext-3.0.0/src/widgets/LoadMask.js +123 -0
  526. data/public/ext-3.0.0/src/widgets/MessageBox.js +626 -0
  527. data/public/ext-3.0.0/src/widgets/PagingToolbar.js +502 -0
  528. data/public/ext-3.0.0/src/widgets/Panel.js +1772 -0
  529. data/public/ext-3.0.0/src/widgets/PanelDD.js +154 -0
  530. data/public/ext-3.0.0/src/widgets/ProgressBar.js +289 -0
  531. data/public/ext-3.0.0/src/widgets/Resizable.js +760 -0
  532. data/public/ext-3.0.0/src/widgets/Shadow.js +192 -0
  533. data/public/ext-3.0.0/src/widgets/Slider.js +426 -0
  534. data/public/ext-3.0.0/src/widgets/SplitBar.js +436 -0
  535. data/public/ext-3.0.0/src/widgets/SplitButton.js +124 -0
  536. data/public/ext-3.0.0/src/widgets/TabPanel.js +1100 -0
  537. data/public/ext-3.0.0/src/widgets/Toolbar.js +781 -0
  538. data/public/ext-3.0.0/src/widgets/Viewport.js +124 -0
  539. data/public/ext-3.0.0/src/widgets/Window.js +941 -0
  540. data/public/ext-3.0.0/src/widgets/WindowManager.js +187 -0
  541. data/public/ext-3.0.0/src/widgets/chart/Chart.js +721 -0
  542. data/public/ext-3.0.0/src/widgets/chart/EventProxy.js +20 -0
  543. data/public/ext-3.0.0/src/widgets/chart/FlashComponent.js +117 -0
  544. data/public/ext-3.0.0/src/widgets/chart/swfobject.js +783 -0
  545. data/public/ext-3.0.0/src/widgets/form/Action.js +626 -0
  546. data/public/ext-3.0.0/src/widgets/form/BasicForm.js +735 -0
  547. data/public/ext-3.0.0/src/widgets/form/Checkbox.js +177 -0
  548. data/public/ext-3.0.0/src/widgets/form/CheckboxGroup.js +419 -0
  549. data/public/ext-3.0.0/src/widgets/form/Combo.js +1232 -0
  550. data/public/ext-3.0.0/src/widgets/form/DateField.js +389 -0
  551. data/public/ext-3.0.0/src/widgets/form/DisplayField.js +98 -0
  552. data/public/ext-3.0.0/src/widgets/form/Field.js +640 -0
  553. data/public/ext-3.0.0/src/widgets/form/FieldSet.js +305 -0
  554. data/public/ext-3.0.0/src/widgets/form/Form.js +335 -0
  555. data/public/ext-3.0.0/src/widgets/form/Hidden.js +39 -0
  556. data/public/ext-3.0.0/src/widgets/form/HtmlEditor.js +1179 -0
  557. data/public/ext-3.0.0/src/widgets/form/Label.js +64 -0
  558. data/public/ext-3.0.0/src/widgets/form/NumberField.js +139 -0
  559. data/public/ext-3.0.0/src/widgets/form/Radio.js +81 -0
  560. data/public/ext-3.0.0/src/widgets/form/RadioGroup.js +116 -0
  561. data/public/ext-3.0.0/src/widgets/form/TextArea.js +117 -0
  562. data/public/ext-3.0.0/src/widgets/form/TextField.js +491 -0
  563. data/public/ext-3.0.0/src/widgets/form/TimeField.js +146 -0
  564. data/public/ext-3.0.0/src/widgets/form/TriggerField.js +328 -0
  565. data/public/ext-3.0.0/src/widgets/form/VTypes.js +135 -0
  566. data/public/ext-3.0.0/src/widgets/grid/AbstractSelectionModel.js +57 -0
  567. data/public/ext-3.0.0/src/widgets/grid/CellSelectionModel.js +262 -0
  568. data/public/ext-3.0.0/src/widgets/grid/CheckboxSelectionModel.js +103 -0
  569. data/public/ext-3.0.0/src/widgets/grid/Column.js +406 -0
  570. data/public/ext-3.0.0/src/widgets/grid/ColumnDD.js +199 -0
  571. data/public/ext-3.0.0/src/widgets/grid/ColumnModel.js +592 -0
  572. data/public/ext-3.0.0/src/widgets/grid/ColumnSplitDD.js +62 -0
  573. data/public/ext-3.0.0/src/widgets/grid/EditorGrid.js +291 -0
  574. data/public/ext-3.0.0/src/widgets/grid/GridDD.js +95 -0
  575. data/public/ext-3.0.0/src/widgets/grid/GridEditor.js +21 -0
  576. data/public/ext-3.0.0/src/widgets/grid/GridPanel.js +952 -0
  577. data/public/ext-3.0.0/src/widgets/grid/GridView.js +1776 -0
  578. data/public/ext-3.0.0/src/widgets/grid/GroupingView.js +517 -0
  579. data/public/ext-3.0.0/src/widgets/grid/PropertyGrid.js +370 -0
  580. data/public/ext-3.0.0/src/widgets/grid/RowNumberer.js +61 -0
  581. data/public/ext-3.0.0/src/widgets/grid/RowSelectionModel.js +530 -0
  582. data/public/ext-3.0.0/src/widgets/layout/AbsoluteLayout.js +82 -0
  583. data/public/ext-3.0.0/src/widgets/layout/AccordionLayout.js +177 -0
  584. data/public/ext-3.0.0/src/widgets/layout/AnchorLayout.js +200 -0
  585. data/public/ext-3.0.0/src/widgets/layout/BorderLayout.js +1108 -0
  586. data/public/ext-3.0.0/src/widgets/layout/BoxLayout.js +417 -0
  587. data/public/ext-3.0.0/src/widgets/layout/CardLayout.js +127 -0
  588. data/public/ext-3.0.0/src/widgets/layout/ColumnLayout.js +130 -0
  589. data/public/ext-3.0.0/src/widgets/layout/ContainerLayout.js +215 -0
  590. data/public/ext-3.0.0/src/widgets/layout/FitLayout.js +48 -0
  591. data/public/ext-3.0.0/src/widgets/layout/FormLayout.js +266 -0
  592. data/public/ext-3.0.0/src/widgets/layout/TableLayout.js +194 -0
  593. data/public/ext-3.0.0/src/widgets/list/ColumnResizer.js +123 -0
  594. data/public/ext-3.0.0/src/widgets/list/ListView.js +357 -0
  595. data/public/ext-3.0.0/src/widgets/list/Sorter.js +70 -0
  596. data/public/ext-3.0.0/src/widgets/menu/BaseItem.js +160 -0
  597. data/public/ext-3.0.0/src/widgets/menu/CheckItem.js +114 -0
  598. data/public/ext-3.0.0/src/widgets/menu/ColorMenu.js +72 -0
  599. data/public/ext-3.0.0/src/widgets/menu/DateMenu.js +90 -0
  600. data/public/ext-3.0.0/src/widgets/menu/Item.js +211 -0
  601. data/public/ext-3.0.0/src/widgets/menu/Menu.js +733 -0
  602. data/public/ext-3.0.0/src/widgets/menu/MenuMgr.js +211 -0
  603. data/public/ext-3.0.0/src/widgets/menu/Separator.js +46 -0
  604. data/public/ext-3.0.0/src/widgets/menu/TextItem.js +46 -0
  605. data/public/ext-3.0.0/src/widgets/tips/QuickTip.js +207 -0
  606. data/public/ext-3.0.0/src/widgets/tips/QuickTips.js +159 -0
  607. data/public/ext-3.0.0/src/widgets/tips/Tip.js +157 -0
  608. data/public/ext-3.0.0/src/widgets/tips/ToolTip.js +492 -0
  609. data/public/ext-3.0.0/src/widgets/tree/AsyncTreeNode.js +114 -0
  610. data/public/ext-3.0.0/src/widgets/tree/TreeDragZone.js +82 -0
  611. data/public/ext-3.0.0/src/widgets/tree/TreeDropZone.js +321 -0
  612. data/public/ext-3.0.0/src/widgets/tree/TreeEditor.js +160 -0
  613. data/public/ext-3.0.0/src/widgets/tree/TreeEventModel.js +169 -0
  614. data/public/ext-3.0.0/src/widgets/tree/TreeFilter.js +114 -0
  615. data/public/ext-3.0.0/src/widgets/tree/TreeLoader.js +342 -0
  616. data/public/ext-3.0.0/src/widgets/tree/TreeNode.js +546 -0
  617. data/public/ext-3.0.0/src/widgets/tree/TreeNodeUI.js +633 -0
  618. data/public/ext-3.0.0/src/widgets/tree/TreePanel.js +918 -0
  619. data/public/ext-3.0.0/src/widgets/tree/TreeSelectionModel.js +315 -0
  620. data/public/ext-3.0.0/src/widgets/tree/TreeSorter.js +106 -0
  621. data/public/js/ext-portal.js +235 -0
  622. data/public/js/global.js +7 -0
  623. data/public/js/outerframe.js +47 -0
  624. data/public/js/portal.js +713 -0
  625. data/public/js/test_chart.js +152 -0
  626. data/test/config.rb +62 -0
  627. data/test/config/hosts.yaml +5 -0
  628. data/test/config/log.yaml +1 -0
  629. data/test/config/memcache.yaml +5 -0
  630. data/test/exception.rb +39 -0
  631. data/test/method_missing.rb +14 -0
  632. data/test/module.rb +39 -0
  633. data/test/remote_lmp.rb +126 -0
  634. data/test/sinatra.rb +29 -0
  635. data/test/sinatra_base.rb +16 -0
  636. metadata +690 -0
@@ -0,0 +1,7 @@
1
+ /*
2
+ * Ext JS Library 3.0.0
3
+ * Copyright(c) 2006-2009 Ext JS, LLC
4
+ * licensing@extjs.com
5
+ * http://www.extjs.com/license
6
+ */
7
+ Ext.layout.ToolbarLayout=Ext.extend(Ext.layout.ContainerLayout,{monitorResize:true,triggerWidth:18,lastOverflow:false,noItemsMenuText:'<div class="x-toolbar-no-items">(None)</div>',onLayout:function(d,f){if(!this.leftTr){f.addClass("x-toolbar-layout-ct");f.insertHtml("beforeEnd",'<table cellspacing="0" class="x-toolbar-ct"><tbody><tr><td class="x-toolbar-left" align="left"><table cellspacing="0"><tbody><tr class="x-toolbar-left-row"></tr></tbody></table></td><td class="x-toolbar-right" align="right"><table cellspacing="0" class="x-toolbar-right-ct"><tbody><tr><td><table cellspacing="0"><tbody><tr class="x-toolbar-right-row"></tr></tbody></table></td><td><table cellspacing="0"><tbody><tr class="x-toolbar-extras-row"></tr></tbody></table></td></tr></tbody></table></td></tr></tbody></table>');this.leftTr=f.child("tr.x-toolbar-left-row",true);this.rightTr=f.child("tr.x-toolbar-right-row",true);this.extrasTr=f.child("tr.x-toolbar-extras-row",true)}var g=this.leftTr;var k=0;var h=d.items.items;for(var b=0,e=h.length,j;b<e;b++,k++){j=h[b];if(j.isFill){g=this.rightTr;k=-1}else{if(!j.rendered){j.render(this.insertCell(j,g,k))}else{if(!j.xtbHidden&&!this.isValidParent(j,g.childNodes[k])){var a=this.insertCell(j,g,k);a.appendChild(j.getDomPositionEl().dom);j.container=Ext.get(a)}}}}this.cleanup(this.leftTr);this.cleanup(this.rightTr);this.cleanup(this.extrasTr);this.fitToSize(f)},cleanup:function(b){var e=b.childNodes;for(var a=e.length-1,d;a>=0&&(d=e[a]);a--){if(!d.firstChild){b.removeChild(d)}}},insertCell:function(e,a,d){var b=document.createElement("td");b.className="x-toolbar-cell";a.insertBefore(b,a.childNodes[d]||null);return b},hideItem:function(b){var a=(this.hiddens=this.hiddens||[]);a.push(b);b.xtbHidden=true;b.xtbWidth=b.getDomPositionEl().dom.parentNode.offsetWidth;b.hide()},unhideItem:function(a){a.show();a.xtbHidden=false;this.hiddens.remove(a);if(this.hiddens.length<1){delete this.hiddens}},getItemWidth:function(a){return a.hidden?(a.xtbWidth||0):a.getDomPositionEl().dom.parentNode.offsetWidth},fitToSize:function(m){if(this.container.enableOverflow===false){return}var l=m.dom.clientWidth;var b=this.lastWidth||0;this.lastWidth=l;var d=m.dom.firstChild.offsetWidth;var k=l-this.triggerWidth;var j=-1;if(d>l||(this.hiddens&&l>=b)){var e,g=this.container.items.items,f=g.length,h;var a=0;for(e=0;e<f;e++){h=g[e];if(!h.isFill){a+=this.getItemWidth(h);if(a>k){if(!h.xtbHidden){this.hideItem(h)}}else{if(h.xtbHidden){this.unhideItem(h)}}}}}if(this.hiddens){this.initMore();if(!this.lastOverflow){this.container.fireEvent("overflowchange",this.container,true);this.lastOverflow=true}}else{if(this.more){this.clearMenu();this.more.destroy();delete this.more;if(this.lastOverflow){this.container.fireEvent("overflowchange",this.container,false);this.lastOverflow=false}}}},createMenuConfig:function(e,b){var a=Ext.apply({},e.initialConfig),d=e.toggleGroup;Ext.apply(a,{text:e.overflowText||e.text,iconCls:e.iconCls,icon:e.icon,itemId:e.itemId,disabled:e.disabled,handler:e.handler,scope:e.scope,menu:e.menu,hideOnClick:b});if(d||e.enableToggle){Ext.apply(a,{group:d,checked:e.pressed,listeners:{checkchange:function(f,c){e.toggle(c)}}})}delete a.xtype;delete a.id;return a},addComponentToMenu:function(a,b){if(b instanceof Ext.Toolbar.Separator){a.add("-")}else{if(Ext.isFunction(b.isXType)){if(b.isXType("splitbutton")){a.add(this.createMenuConfig(b,true))}else{if(b.isXType("button")){a.add(this.createMenuConfig(b,!b.menu))}else{if(b.isXType("buttongroup")){b.items.each(function(c){this.addComponentToMenu(a,c)},this)}}}}}},clearMenu:function(){var a=this.moreMenu;if(a&&a.items){this.moreMenu.items.each(function(b){delete b.menu})}},beforeMoreShow:function(b){var f=this.container.items.items,a=f.length,j,g,d=function(h,c){return h.isXType("buttongroup")&&!(c instanceof Ext.Toolbar.Separator)};this.clearMenu();b.removeAll();for(var e=0;e<a;e++){j=f[e];if(j.xtbHidden){if(g&&(d(j,g)||d(g,j))){b.add("-")}this.addComponentToMenu(b,j);g=j}}if(b.items.length<1){b.add(this.noItemsMenuText)}},initMore:function(){if(!this.more){this.moreMenu=new Ext.menu.Menu({listeners:{beforeshow:this.beforeMoreShow,scope:this}});this.more=new Ext.Button({iconCls:"x-toolbar-more-icon",cls:"x-toolbar-more",menu:this.moreMenu});var a=this.insertCell(this.more,this.extrasTr,100);this.more.render(a)}},destroy:function(){Ext.destroy(this.more,this.moreMenu);Ext.layout.ToolbarLayout.superclass.destroy.call(this)}});Ext.Container.LAYOUTS.toolbar=Ext.layout.ToolbarLayout;Ext.Toolbar=function(a){if(Ext.isArray(a)){a={items:a,layout:"toolbar"}}else{a=Ext.apply({layout:"toolbar"},a);if(a.buttons){a.items=a.buttons}}Ext.Toolbar.superclass.constructor.call(this,a)};(function(){var a=Ext.Toolbar;Ext.extend(a,Ext.Container,{defaultType:"button",trackMenus:true,internalDefaults:{removeMode:"container",hideParent:true},toolbarCls:"x-toolbar",initComponent:function(){a.superclass.initComponent.call(this);this.addEvents("overflowchange")},onRender:function(c,b){if(!this.el){if(!this.autoCreate){this.autoCreate={cls:this.toolbarCls+" x-small-editor"}}this.el=c.createChild(Ext.apply({id:this.id},this.autoCreate),b)}},lookupComponent:function(b){if(Ext.isString(b)){if(b=="-"){b=new a.Separator()}else{if(b==" "){b=new a.Spacer()}else{if(b=="->"){b=new a.Fill()}else{b=new a.TextItem(b)}}}this.applyDefaults(b)}else{if(b.isFormField||b.render){b=this.constructItem(b)}else{if(b.tag){b=new a.Item({autoEl:b})}else{if(b.tagName){b=new a.Item({el:b})}else{if(Ext.isObject(b)){b=b.xtype?this.constructItem(b):this.constructButton(b)}}}}}return b},applyDefaults:function(e){if(!Ext.isString(e)){e=Ext.Toolbar.superclass.applyDefaults.call(this,e);var b=this.internalDefaults;if(e.events){Ext.applyIf(e.initialConfig,b);Ext.apply(e,b)}else{Ext.applyIf(e,b)}}return e},constructItem:function(c,b){return Ext.create(c,b||this.defaultType)},addSeparator:function(){return this.add(new a.Separator())},addSpacer:function(){return this.add(new a.Spacer())},addFill:function(){this.add(new a.Fill())},addElement:function(b){return this.addItem(new a.Item({el:b}))},addItem:function(b){return Ext.Toolbar.superclass.add.apply(this,arguments)},addButton:function(c){if(Ext.isArray(c)){var e=[];for(var d=0,b=c.length;d<b;d++){e.push(this.addButton(c[d]))}return e}return this.add(this.constructButton(c))},addText:function(b){return this.addItem(new a.TextItem(b))},addDom:function(b){return this.add(new a.Item({autoEl:b}))},addField:function(b){return this.add(b)},insertButton:function(c,f){if(Ext.isArray(f)){var e=[];for(var d=0,b=f.length;d<b;d++){e.push(this.insertButton(c+d,f[d]))}return e}return Ext.Toolbar.superclass.insert.call(this,c,f)},initMenuTracking:function(b){if(this.trackMenus&&b.menu){this.mon(b,{menutriggerover:this.onButtonTriggerOver,menushow:this.onButtonMenuShow,menuhide:this.onButtonMenuHide,scope:this})}},constructButton:function(d){var c=d.events?d:this.constructItem(d,d.split?"splitbutton":this.defaultType);this.initMenuTracking(c);return c},onDisable:function(){this.items.each(function(b){if(b.disable){b.disable()}})},onEnable:function(){this.items.each(function(b){if(b.enable){b.enable()}})},onButtonTriggerOver:function(b){if(this.activeMenuBtn&&this.activeMenuBtn!=b){this.activeMenuBtn.hideMenu();b.showMenu();this.activeMenuBtn=b}},onButtonMenuShow:function(b){this.activeMenuBtn=b},onButtonMenuHide:function(b){delete this.activeMenuBtn}});Ext.reg("toolbar",Ext.Toolbar);a.Item=Ext.extend(Ext.BoxComponent,{hideParent:true,enable:Ext.emptyFn,disable:Ext.emptyFn,focus:Ext.emptyFn});Ext.reg("tbitem",a.Item);a.Separator=Ext.extend(a.Item,{onRender:function(c,b){this.el=c.createChild({tag:"span",cls:"xtb-sep"},b)}});Ext.reg("tbseparator",a.Separator);a.Spacer=Ext.extend(a.Item,{onRender:function(c,b){this.el=c.createChild({tag:"div",cls:"xtb-spacer",style:this.width?"width:"+this.width+"px":""},b)}});Ext.reg("tbspacer",a.Spacer);a.Fill=Ext.extend(a.Item,{render:Ext.emptyFn,isFill:true});Ext.reg("tbfill",a.Fill);a.TextItem=Ext.extend(a.Item,{constructor:function(b){if(Ext.isString(b)){b={autoEl:{cls:"xtb-text",html:b}}}else{b.autoEl={cls:"xtb-text",html:b.text||""}}a.TextItem.superclass.constructor.call(this,b)},setText:function(b){if(this.rendered){this.el.dom.innerHTML=b}else{this.autoEl.html=b}}});Ext.reg("tbtext",a.TextItem);a.Button=Ext.extend(Ext.Button,{});a.SplitButton=Ext.extend(Ext.SplitButton,{});Ext.reg("tbbutton",a.Button);Ext.reg("tbsplit",a.SplitButton)})();Ext.ButtonGroup=Ext.extend(Ext.Panel,{baseCls:"x-btn-group",layout:"table",defaultType:"button",frame:true,internalDefaults:{removeMode:"container",hideParent:true},initComponent:function(){this.layoutConfig=this.layoutConfig||{};Ext.applyIf(this.layoutConfig,{columns:this.columns});if(!this.title){this.addClass("x-btn-group-notitle")}this.on("afterlayout",this.onAfterLayout,this);Ext.ButtonGroup.superclass.initComponent.call(this)},applyDefaults:function(b){b=Ext.ButtonGroup.superclass.applyDefaults.call(this,b);var a=this.internalDefaults;if(b.events){Ext.applyIf(b.initialConfig,a);Ext.apply(b,a)}else{Ext.applyIf(b,a)}return b},onAfterLayout:function(){var a=this.body.getFrameWidth("lr")+this.body.dom.firstChild.offsetWidth;this.body.setWidth(a);this.el.setWidth(a+this.getFrameWidth())}});Ext.reg("buttongroup",Ext.ButtonGroup);(function(){var a=Ext.Toolbar;Ext.PagingToolbar=Ext.extend(Ext.Toolbar,{pageSize:20,displayMsg:"Displaying {0} - {1} of {2}",emptyMsg:"No data to display",beforePageText:"Page",afterPageText:"of {0}",firstText:"First Page",prevText:"Previous Page",nextText:"Next Page",lastText:"Last Page",refreshText:"Refresh",initComponent:function(){var c=[this.first=new a.Button({tooltip:this.firstText,overflowText:this.firstText,iconCls:"x-tbar-page-first",disabled:true,handler:this.moveFirst,scope:this}),this.prev=new a.Button({tooltip:this.prevText,overflowText:this.prevText,iconCls:"x-tbar-page-prev",disabled:true,handler:this.movePrevious,scope:this}),"-",this.beforePageText,this.inputItem=new Ext.form.NumberField({cls:"x-tbar-page-number",allowDecimals:false,allowNegative:false,enableKeyEvents:true,selectOnFocus:true,listeners:{scope:this,keydown:this.onPagingKeyDown,blur:this.onPagingBlur}}),this.afterTextItem=new a.TextItem({text:String.format(this.afterPageText,1)}),"-",this.next=new a.Button({tooltip:this.nextText,overflowText:this.nextText,iconCls:"x-tbar-page-next",disabled:true,handler:this.moveNext,scope:this}),this.last=new a.Button({tooltip:this.lastText,overflowText:this.lastText,iconCls:"x-tbar-page-last",disabled:true,handler:this.moveLast,scope:this}),"-",this.refresh=new a.Button({tooltip:this.refreshText,overflowText:this.refreshText,iconCls:"x-tbar-loading",handler:this.refresh,scope:this})];var b=this.items||this.buttons||[];if(this.prependButtons){this.items=b.concat(c)}else{this.items=c.concat(b)}delete this.buttons;if(this.displayInfo){this.items.push("->");this.items.push(this.displayItem=new a.TextItem({}))}Ext.PagingToolbar.superclass.initComponent.call(this);this.addEvents("change","beforechange");this.on("afterlayout",this.onFirstLayout,this,{single:true});this.cursor=0;this.bindStore(this.store)},onFirstLayout:function(){if(this.dsLoaded){this.onLoad.apply(this,this.dsLoaded)}},updateInfo:function(){if(this.displayItem){var b=this.store.getCount();var c=b==0?this.emptyMsg:String.format(this.displayMsg,this.cursor+1,this.cursor+b,this.store.getTotalCount());this.displayItem.setText(c)}},onLoad:function(b,e,i){if(!this.rendered){this.dsLoaded=[b,e,i];return}var f=this.getParams();this.cursor=(i.params&&i.params[f.start])?i.params[f.start]:0;var h=this.getPageData(),c=h.activePage,g=h.pages;this.afterTextItem.setText(String.format(this.afterPageText,h.pages));this.inputItem.setValue(c);this.first.setDisabled(c==1);this.prev.setDisabled(c==1);this.next.setDisabled(c==g);this.last.setDisabled(c==g);this.refresh.enable();this.updateInfo();this.fireEvent("change",this,h)},getPageData:function(){var b=this.store.getTotalCount();return{total:b,activePage:Math.ceil((this.cursor+this.pageSize)/this.pageSize),pages:b<this.pageSize?1:Math.ceil(b/this.pageSize)}},changePage:function(b){this.doLoad(((b-1)*this.pageSize).constrain(0,this.store.getTotalCount()))},onLoadError:function(){if(!this.rendered){return}this.refresh.enable()},readPage:function(e){var b=this.inputItem.getValue(),c;if(!b||isNaN(c=parseInt(b,10))){this.inputItem.setValue(e.activePage);return false}return c},onPagingFocus:function(){this.inputItem.select()},onPagingBlur:function(b){this.inputItem.setValue(this.getPageData().activePage)},onPagingKeyDown:function(h,g){var c=g.getKey(),i=this.getPageData(),f;if(c==g.RETURN){g.stopEvent();f=this.readPage(i);if(f!==false){f=Math.min(Math.max(1,f),i.pages)-1;this.doLoad(f*this.pageSize)}}else{if(c==g.HOME||c==g.END){g.stopEvent();f=c==g.HOME?1:i.pages;h.setValue(f)}else{if(c==g.UP||c==g.PAGEUP||c==g.DOWN||c==g.PAGEDOWN){g.stopEvent();if((f=this.readPage(i))){var b=g.shiftKey?10:1;if(c==g.DOWN||c==g.PAGEDOWN){b*=-1}f+=b;if(f>=1&f<=i.pages){h.setValue(f)}}}}}},getParams:function(){return this.paramNames||this.store.paramNames},beforeLoad:function(){if(this.rendered&&this.refresh){this.refresh.disable()}},doLoad:function(d){var c={},b=this.getParams();c[b.start]=d;c[b.limit]=this.pageSize;if(this.fireEvent("beforechange",this,c)!==false){this.store.load({params:c})}},moveFirst:function(){this.doLoad(0)},movePrevious:function(){this.doLoad(Math.max(0,this.cursor-this.pageSize))},moveNext:function(){this.doLoad(this.cursor+this.pageSize)},moveLast:function(){var c=this.store.getTotalCount(),b=c%this.pageSize;this.doLoad(b?(c-b):c-this.pageSize)},refresh:function(){this.doLoad(this.cursor)},bindStore:function(c,d){var b;if(!d&&this.store){this.store.un("beforeload",this.beforeLoad,this);this.store.un("load",this.onLoad,this);this.store.un("exception",this.onLoadError,this);if(c!==this.store&&this.store.autoDestroy){this.store.destroy()}}if(c){c=Ext.StoreMgr.lookup(c);c.on({scope:this,beforeload:this.beforeLoad,load:this.onLoad,exception:this.onLoadError});b=c.getCount()>0}this.store=c;if(b){this.onLoad(c,null,{})}},unbind:function(b){this.bindStore(null)},bind:function(b){this.bindStore(b)},onDestroy:function(){this.bindStore(null);Ext.PagingToolbar.superclass.onDestroy.call(this)}})})();Ext.reg("paging",Ext.PagingToolbar);
@@ -0,0 +1,4522 @@
1
+ /*!
2
+ * Ext JS Library 3.0.0
3
+ * Copyright(c) 2006-2009 Ext JS, LLC
4
+ * licensing@extjs.com
5
+ * http://www.extjs.com/license
6
+ */
7
+ /**
8
+ * @class Ext.tree.TreePanel
9
+ * @extends Ext.Panel
10
+ * <p>The TreePanel provides tree-structured UI representation of tree-structured data.</p>
11
+ * <p>{@link Ext.tree.TreeNode TreeNode}s added to the TreePanel may each contain metadata
12
+ * used by your application in their {@link Ext.tree.TreeNode#attributes attributes} property.</p>
13
+ * <p><b>A TreePanel must have a {@link #root} node before it is rendered.</b> This may either be
14
+ * specified using the {@link #root} config option, or using the {@link #setRootNode} method.
15
+ * <p>An example of tree rendered to an existing div:</p><pre><code>
16
+ var tree = new Ext.tree.TreePanel({
17
+ renderTo: 'tree-div',
18
+ useArrows: true,
19
+ autoScroll: true,
20
+ animate: true,
21
+ enableDD: true,
22
+ containerScroll: true,
23
+ border: false,
24
+ // auto create TreeLoader
25
+ dataUrl: 'get-nodes.php',
26
+
27
+ root: {
28
+ nodeType: 'async',
29
+ text: 'Ext JS',
30
+ draggable: false,
31
+ id: 'source'
32
+ }
33
+ });
34
+
35
+ tree.getRootNode().expand();
36
+ * </code></pre>
37
+ * <p>The example above would work with a data packet similar to this:</p><pre><code>
38
+ [{
39
+ "text": "adapter",
40
+ "id": "source\/adapter",
41
+ "cls": "folder"
42
+ }, {
43
+ "text": "dd",
44
+ "id": "source\/dd",
45
+ "cls": "folder"
46
+ }, {
47
+ "text": "debug.js",
48
+ "id": "source\/debug.js",
49
+ "leaf": true,
50
+ "cls": "file"
51
+ }]
52
+ * </code></pre>
53
+ * <p>An example of tree within a Viewport:</p><pre><code>
54
+ new Ext.Viewport({
55
+ layout: 'border',
56
+ items: [{
57
+ region: 'west',
58
+ collapsible: true,
59
+ title: 'Navigation',
60
+ xtype: 'treepanel',
61
+ width: 200,
62
+ autoScroll: true,
63
+ split: true,
64
+ loader: new Ext.tree.TreeLoader(),
65
+ root: new Ext.tree.AsyncTreeNode({
66
+ expanded: true,
67
+ children: [{
68
+ text: 'Menu Option 1',
69
+ leaf: true
70
+ }, {
71
+ text: 'Menu Option 2',
72
+ leaf: true
73
+ }, {
74
+ text: 'Menu Option 3',
75
+ leaf: true
76
+ }]
77
+ }),
78
+ rootVisible: false,
79
+ listeners: {
80
+ click: function(n) {
81
+ Ext.Msg.alert('Navigation Tree Click', 'You clicked: "' + n.attributes.text + '"');
82
+ }
83
+ }
84
+ }, {
85
+ region: 'center',
86
+ xtype: 'tabpanel',
87
+ // remaining code not shown ...
88
+ }]
89
+ });
90
+ </code></pre>
91
+ *
92
+ * @cfg {Ext.tree.TreeNode} root The root node for the tree.
93
+ * @cfg {Boolean} rootVisible <tt>false</tt> to hide the root node (defaults to <tt>true</tt>)
94
+ * @cfg {Boolean} lines <tt>false</tt> to disable tree lines (defaults to <tt>true</tt>)
95
+ * @cfg {Boolean} enableDD <tt>true</tt> to enable drag and drop
96
+ * @cfg {Boolean} enableDrag <tt>true</tt> to enable just drag
97
+ * @cfg {Boolean} enableDrop <tt>true</tt> to enable just drop
98
+ * @cfg {Object} dragConfig Custom config to pass to the {@link Ext.tree.TreeDragZone} instance
99
+ * @cfg {Object} dropConfig Custom config to pass to the {@link Ext.tree.TreeDropZone} instance
100
+ * @cfg {String} ddGroup The DD group this TreePanel belongs to
101
+ * @cfg {Boolean} ddAppendOnly <tt>true</tt> if the tree should only allow append drops (use for trees which are sorted)
102
+ * @cfg {Boolean} ddScroll <tt>true</tt> to enable body scrolling
103
+ * @cfg {Boolean} containerScroll <tt>true</tt> to register this container with ScrollManager
104
+ * @cfg {Boolean} hlDrop <tt>false</tt> to disable node highlight on drop (defaults to the value of {@link Ext#enableFx})
105
+ * @cfg {String} hlColor The color of the node highlight (defaults to <tt>'C3DAF9'</tt>)
106
+ * @cfg {Boolean} animate <tt>true</tt> to enable animated expand/collapse (defaults to the value of {@link Ext#enableFx})
107
+ * @cfg {Boolean} singleExpand <tt>true</tt> if only 1 node per branch may be expanded
108
+ * @cfg {Object} selModel A tree selection model to use with this TreePanel (defaults to an {@link Ext.tree.DefaultSelectionModel})
109
+ * @cfg {Boolean} trackMouseOver <tt>false</tt> to disable mouse over highlighting
110
+ * @cfg {Ext.tree.TreeLoader} loader A {@link Ext.tree.TreeLoader} for use with this TreePanel
111
+ * @cfg {String} pathSeparator The token used to separate sub-paths in path strings (defaults to <tt>'/'</tt>)
112
+ * @cfg {Boolean} useArrows <tt>true</tt> to use Vista-style arrows in the tree (defaults to <tt>false</tt>)
113
+ * @cfg {String} requestMethod The HTTP request method for loading data (defaults to the value of {@link Ext.Ajax#method}).
114
+ *
115
+ * @constructor
116
+ * @param {Object} config
117
+ * @xtype treepanel
118
+ */
119
+ Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
120
+ rootVisible : true,
121
+ animate: Ext.enableFx,
122
+ lines : true,
123
+ enableDD : false,
124
+ hlDrop : Ext.enableFx,
125
+ pathSeparator: "/",
126
+
127
+ initComponent : function(){
128
+ Ext.tree.TreePanel.superclass.initComponent.call(this);
129
+
130
+ if(!this.eventModel){
131
+ this.eventModel = new Ext.tree.TreeEventModel(this);
132
+ }
133
+
134
+ // initialize the loader
135
+ var l = this.loader;
136
+ if(!l){
137
+ l = new Ext.tree.TreeLoader({
138
+ dataUrl: this.dataUrl,
139
+ requestMethod: this.requestMethod
140
+ });
141
+ }else if(typeof l == 'object' && !l.load){
142
+ l = new Ext.tree.TreeLoader(l);
143
+ }
144
+ this.loader = l;
145
+
146
+ this.nodeHash = {};
147
+
148
+ /**
149
+ * The root node of this tree.
150
+ * @type Ext.tree.TreeNode
151
+ * @property root
152
+ */
153
+ if(this.root){
154
+ var r = this.root;
155
+ delete this.root;
156
+ this.setRootNode(r);
157
+ }
158
+
159
+
160
+ this.addEvents(
161
+
162
+ /**
163
+ * @event append
164
+ * Fires when a new child node is appended to a node in this tree.
165
+ * @param {Tree} tree The owner tree
166
+ * @param {Node} parent The parent node
167
+ * @param {Node} node The newly appended node
168
+ * @param {Number} index The index of the newly appended node
169
+ */
170
+ "append",
171
+ /**
172
+ * @event remove
173
+ * Fires when a child node is removed from a node in this tree.
174
+ * @param {Tree} tree The owner tree
175
+ * @param {Node} parent The parent node
176
+ * @param {Node} node The child node removed
177
+ */
178
+ "remove",
179
+ /**
180
+ * @event movenode
181
+ * Fires when a node is moved to a new location in the tree
182
+ * @param {Tree} tree The owner tree
183
+ * @param {Node} node The node moved
184
+ * @param {Node} oldParent The old parent of this node
185
+ * @param {Node} newParent The new parent of this node
186
+ * @param {Number} index The index it was moved to
187
+ */
188
+ "movenode",
189
+ /**
190
+ * @event insert
191
+ * Fires when a new child node is inserted in a node in this tree.
192
+ * @param {Tree} tree The owner tree
193
+ * @param {Node} parent The parent node
194
+ * @param {Node} node The child node inserted
195
+ * @param {Node} refNode The child node the node was inserted before
196
+ */
197
+ "insert",
198
+ /**
199
+ * @event beforeappend
200
+ * Fires before a new child is appended to a node in this tree, return false to cancel the append.
201
+ * @param {Tree} tree The owner tree
202
+ * @param {Node} parent The parent node
203
+ * @param {Node} node The child node to be appended
204
+ */
205
+ "beforeappend",
206
+ /**
207
+ * @event beforeremove
208
+ * Fires before a child is removed from a node in this tree, return false to cancel the remove.
209
+ * @param {Tree} tree The owner tree
210
+ * @param {Node} parent The parent node
211
+ * @param {Node} node The child node to be removed
212
+ */
213
+ "beforeremove",
214
+ /**
215
+ * @event beforemovenode
216
+ * Fires before a node is moved to a new location in the tree. Return false to cancel the move.
217
+ * @param {Tree} tree The owner tree
218
+ * @param {Node} node The node being moved
219
+ * @param {Node} oldParent The parent of the node
220
+ * @param {Node} newParent The new parent the node is moving to
221
+ * @param {Number} index The index it is being moved to
222
+ */
223
+ "beforemovenode",
224
+ /**
225
+ * @event beforeinsert
226
+ * Fires before a new child is inserted in a node in this tree, return false to cancel the insert.
227
+ * @param {Tree} tree The owner tree
228
+ * @param {Node} parent The parent node
229
+ * @param {Node} node The child node to be inserted
230
+ * @param {Node} refNode The child node the node is being inserted before
231
+ */
232
+ "beforeinsert",
233
+
234
+ /**
235
+ * @event beforeload
236
+ * Fires before a node is loaded, return false to cancel
237
+ * @param {Node} node The node being loaded
238
+ */
239
+ "beforeload",
240
+ /**
241
+ * @event load
242
+ * Fires when a node is loaded
243
+ * @param {Node} node The node that was loaded
244
+ */
245
+ "load",
246
+ /**
247
+ * @event textchange
248
+ * Fires when the text for a node is changed
249
+ * @param {Node} node The node
250
+ * @param {String} text The new text
251
+ * @param {String} oldText The old text
252
+ */
253
+ "textchange",
254
+ /**
255
+ * @event beforeexpandnode
256
+ * Fires before a node is expanded, return false to cancel.
257
+ * @param {Node} node The node
258
+ * @param {Boolean} deep
259
+ * @param {Boolean} anim
260
+ */
261
+ "beforeexpandnode",
262
+ /**
263
+ * @event beforecollapsenode
264
+ * Fires before a node is collapsed, return false to cancel.
265
+ * @param {Node} node The node
266
+ * @param {Boolean} deep
267
+ * @param {Boolean} anim
268
+ */
269
+ "beforecollapsenode",
270
+ /**
271
+ * @event expandnode
272
+ * Fires when a node is expanded
273
+ * @param {Node} node The node
274
+ */
275
+ "expandnode",
276
+ /**
277
+ * @event disabledchange
278
+ * Fires when the disabled status of a node changes
279
+ * @param {Node} node The node
280
+ * @param {Boolean} disabled
281
+ */
282
+ "disabledchange",
283
+ /**
284
+ * @event collapsenode
285
+ * Fires when a node is collapsed
286
+ * @param {Node} node The node
287
+ */
288
+ "collapsenode",
289
+ /**
290
+ * @event beforeclick
291
+ * Fires before click processing on a node. Return false to cancel the default action.
292
+ * @param {Node} node The node
293
+ * @param {Ext.EventObject} e The event object
294
+ */
295
+ "beforeclick",
296
+ /**
297
+ * @event click
298
+ * Fires when a node is clicked
299
+ * @param {Node} node The node
300
+ * @param {Ext.EventObject} e The event object
301
+ */
302
+ "click",
303
+ /**
304
+ * @event checkchange
305
+ * Fires when a node with a checkbox's checked property changes
306
+ * @param {Node} this This node
307
+ * @param {Boolean} checked
308
+ */
309
+ "checkchange",
310
+ /**
311
+ * @event dblclick
312
+ * Fires when a node is double clicked
313
+ * @param {Node} node The node
314
+ * @param {Ext.EventObject} e The event object
315
+ */
316
+ "dblclick",
317
+ /**
318
+ * @event contextmenu
319
+ * Fires when a node is right clicked. To display a context menu in response to this
320
+ * event, first create a Menu object (see {@link Ext.menu.Menu} for details), then add
321
+ * a handler for this event:<pre><code>
322
+ new Ext.tree.TreePanel({
323
+ title: 'My TreePanel',
324
+ root: new Ext.tree.AsyncTreeNode({
325
+ text: 'The Root',
326
+ children: [
327
+ { text: 'Child node 1', leaf: true },
328
+ { text: 'Child node 2', leaf: true }
329
+ ]
330
+ }),
331
+ contextMenu: new Ext.menu.Menu({
332
+ items: [{
333
+ id: 'delete-node',
334
+ text: 'Delete Node'
335
+ }],
336
+ listeners: {
337
+ itemclick: function(item) {
338
+ switch (item.id) {
339
+ case 'delete-node':
340
+ var n = item.parentMenu.contextNode;
341
+ if (n.parentNode) {
342
+ n.remove();
343
+ }
344
+ break;
345
+ }
346
+ }
347
+ }
348
+ }),
349
+ listeners: {
350
+ contextmenu: function(node, e) {
351
+ // Register the context node with the menu so that a Menu Item's handler function can access
352
+ // it via its {@link Ext.menu.BaseItem#parentMenu parentMenu} property.
353
+ node.select();
354
+ var c = node.getOwnerTree().contextMenu;
355
+ c.contextNode = node;
356
+ c.showAt(e.getXY());
357
+ }
358
+ }
359
+ });
360
+ </code></pre>
361
+ * @param {Node} node The node
362
+ * @param {Ext.EventObject} e The event object
363
+ */
364
+ "contextmenu",
365
+ /**
366
+ * @event beforechildrenrendered
367
+ * Fires right before the child nodes for a node are rendered
368
+ * @param {Node} node The node
369
+ */
370
+ "beforechildrenrendered",
371
+ /**
372
+ * @event startdrag
373
+ * Fires when a node starts being dragged
374
+ * @param {Ext.tree.TreePanel} this
375
+ * @param {Ext.tree.TreeNode} node
376
+ * @param {event} e The raw browser event
377
+ */
378
+ "startdrag",
379
+ /**
380
+ * @event enddrag
381
+ * Fires when a drag operation is complete
382
+ * @param {Ext.tree.TreePanel} this
383
+ * @param {Ext.tree.TreeNode} node
384
+ * @param {event} e The raw browser event
385
+ */
386
+ "enddrag",
387
+ /**
388
+ * @event dragdrop
389
+ * Fires when a dragged node is dropped on a valid DD target
390
+ * @param {Ext.tree.TreePanel} this
391
+ * @param {Ext.tree.TreeNode} node
392
+ * @param {DD} dd The dd it was dropped on
393
+ * @param {event} e The raw browser event
394
+ */
395
+ "dragdrop",
396
+ /**
397
+ * @event beforenodedrop
398
+ * Fires when a DD object is dropped on a node in this tree for preprocessing. Return false to cancel the drop. The dropEvent
399
+ * passed to handlers has the following properties:<br />
400
+ * <ul style="padding:5px;padding-left:16px;">
401
+ * <li>tree - The TreePanel</li>
402
+ * <li>target - The node being targeted for the drop</li>
403
+ * <li>data - The drag data from the drag source</li>
404
+ * <li>point - The point of the drop - append, above or below</li>
405
+ * <li>source - The drag source</li>
406
+ * <li>rawEvent - Raw mouse event</li>
407
+ * <li>dropNode - Drop node(s) provided by the source <b>OR</b> you can supply node(s)
408
+ * to be inserted by setting them on this object.</li>
409
+ * <li>cancel - Set this to true to cancel the drop.</li>
410
+ * <li>dropStatus - If the default drop action is cancelled but the drop is valid, setting this to true
411
+ * will prevent the animated "repair" from appearing.</li>
412
+ * </ul>
413
+ * @param {Object} dropEvent
414
+ */
415
+ "beforenodedrop",
416
+ /**
417
+ * @event nodedrop
418
+ * Fires after a DD object is dropped on a node in this tree. The dropEvent
419
+ * passed to handlers has the following properties:<br />
420
+ * <ul style="padding:5px;padding-left:16px;">
421
+ * <li>tree - The TreePanel</li>
422
+ * <li>target - The node being targeted for the drop</li>
423
+ * <li>data - The drag data from the drag source</li>
424
+ * <li>point - The point of the drop - append, above or below</li>
425
+ * <li>source - The drag source</li>
426
+ * <li>rawEvent - Raw mouse event</li>
427
+ * <li>dropNode - Dropped node(s).</li>
428
+ * </ul>
429
+ * @param {Object} dropEvent
430
+ */
431
+ "nodedrop",
432
+ /**
433
+ * @event nodedragover
434
+ * Fires when a tree node is being targeted for a drag drop, return false to signal drop not allowed. The dragOverEvent
435
+ * passed to handlers has the following properties:<br />
436
+ * <ul style="padding:5px;padding-left:16px;">
437
+ * <li>tree - The TreePanel</li>
438
+ * <li>target - The node being targeted for the drop</li>
439
+ * <li>data - The drag data from the drag source</li>
440
+ * <li>point - The point of the drop - append, above or below</li>
441
+ * <li>source - The drag source</li>
442
+ * <li>rawEvent - Raw mouse event</li>
443
+ * <li>dropNode - Drop node(s) provided by the source.</li>
444
+ * <li>cancel - Set this to true to signal drop not allowed.</li>
445
+ * </ul>
446
+ * @param {Object} dragOverEvent
447
+ */
448
+ "nodedragover"
449
+ );
450
+ if(this.singleExpand){
451
+ this.on("beforeexpandnode", this.restrictExpand, this);
452
+ }
453
+ },
454
+
455
+ // private
456
+ proxyNodeEvent : function(ename, a1, a2, a3, a4, a5, a6){
457
+ if(ename == 'collapse' || ename == 'expand' || ename == 'beforecollapse' || ename == 'beforeexpand' || ename == 'move' || ename == 'beforemove'){
458
+ ename = ename+'node';
459
+ }
460
+ // args inline for performance while bubbling events
461
+ return this.fireEvent(ename, a1, a2, a3, a4, a5, a6);
462
+ },
463
+
464
+
465
+ /**
466
+ * Returns this root node for this tree
467
+ * @return {Node}
468
+ */
469
+ getRootNode : function(){
470
+ return this.root;
471
+ },
472
+
473
+ /**
474
+ * Sets the root node for this tree. If the TreePanel has already rendered a root node, the
475
+ * previous root node (and all of its descendants) are destroyed before the new root node is rendered.
476
+ * @param {Node} node
477
+ * @return {Node}
478
+ */
479
+ setRootNode : function(node){
480
+ Ext.destroy(this.root);
481
+ if(!node.render){ // attributes passed
482
+ node = this.loader.createNode(node);
483
+ }
484
+ this.root = node;
485
+ node.ownerTree = this;
486
+ node.isRoot = true;
487
+ this.registerNode(node);
488
+ if(!this.rootVisible){
489
+ var uiP = node.attributes.uiProvider;
490
+ node.ui = uiP ? new uiP(node) : new Ext.tree.RootTreeNodeUI(node);
491
+ }
492
+ if (this.innerCt) {
493
+ this.innerCt.update('');
494
+ this.afterRender();
495
+ }
496
+ return node;
497
+ },
498
+
499
+ /**
500
+ * Gets a node in this tree by its id
501
+ * @param {String} id
502
+ * @return {Node}
503
+ */
504
+ getNodeById : function(id){
505
+ return this.nodeHash[id];
506
+ },
507
+
508
+ // private
509
+ registerNode : function(node){
510
+ this.nodeHash[node.id] = node;
511
+ },
512
+
513
+ // private
514
+ unregisterNode : function(node){
515
+ delete this.nodeHash[node.id];
516
+ },
517
+
518
+ // private
519
+ toString : function(){
520
+ return "[Tree"+(this.id?" "+this.id:"")+"]";
521
+ },
522
+
523
+ // private
524
+ restrictExpand : function(node){
525
+ var p = node.parentNode;
526
+ if(p){
527
+ if(p.expandedChild && p.expandedChild.parentNode == p){
528
+ p.expandedChild.collapse();
529
+ }
530
+ p.expandedChild = node;
531
+ }
532
+ },
533
+
534
+ /**
535
+ * Retrieve an array of checked nodes, or an array of a specific attribute of checked nodes (e.g. "id")
536
+ * @param {String} attribute (optional) Defaults to null (return the actual nodes)
537
+ * @param {TreeNode} startNode (optional) The node to start from, defaults to the root
538
+ * @return {Array}
539
+ */
540
+ getChecked : function(a, startNode){
541
+ startNode = startNode || this.root;
542
+ var r = [];
543
+ var f = function(){
544
+ if(this.attributes.checked){
545
+ r.push(!a ? this : (a == 'id' ? this.id : this.attributes[a]));
546
+ }
547
+ };
548
+ startNode.cascade(f);
549
+ return r;
550
+ },
551
+
552
+ /**
553
+ * Returns the container element for this TreePanel.
554
+ * @return {Element} The container element for this TreePanel.
555
+ */
556
+ getEl : function(){
557
+ return this.el;
558
+ },
559
+
560
+ /**
561
+ * Returns the default {@link Ext.tree.TreeLoader} for this TreePanel.
562
+ * @return {Ext.tree.TreeLoader} The TreeLoader for this TreePanel.
563
+ */
564
+ getLoader : function(){
565
+ return this.loader;
566
+ },
567
+
568
+ /**
569
+ * Expand all nodes
570
+ */
571
+ expandAll : function(){
572
+ this.root.expand(true);
573
+ },
574
+
575
+ /**
576
+ * Collapse all nodes
577
+ */
578
+ collapseAll : function(){
579
+ this.root.collapse(true);
580
+ },
581
+
582
+ /**
583
+ * Returns the selection model used by this TreePanel.
584
+ * @return {TreeSelectionModel} The selection model used by this TreePanel
585
+ */
586
+ getSelectionModel : function(){
587
+ if(!this.selModel){
588
+ this.selModel = new Ext.tree.DefaultSelectionModel();
589
+ }
590
+ return this.selModel;
591
+ },
592
+
593
+ /**
594
+ * Expands a specified path in this TreePanel. A path can be retrieved from a node with {@link Ext.data.Node#getPath}
595
+ * @param {String} path
596
+ * @param {String} attr (optional) The attribute used in the path (see {@link Ext.data.Node#getPath} for more info)
597
+ * @param {Function} callback (optional) The callback to call when the expand is complete. The callback will be called with
598
+ * (bSuccess, oLastNode) where bSuccess is if the expand was successful and oLastNode is the last node that was expanded.
599
+ */
600
+ expandPath : function(path, attr, callback){
601
+ attr = attr || "id";
602
+ var keys = path.split(this.pathSeparator);
603
+ var curNode = this.root;
604
+ if(curNode.attributes[attr] != keys[1]){ // invalid root
605
+ if(callback){
606
+ callback(false, null);
607
+ }
608
+ return;
609
+ }
610
+ var index = 1;
611
+ var f = function(){
612
+ if(++index == keys.length){
613
+ if(callback){
614
+ callback(true, curNode);
615
+ }
616
+ return;
617
+ }
618
+ var c = curNode.findChild(attr, keys[index]);
619
+ if(!c){
620
+ if(callback){
621
+ callback(false, curNode);
622
+ }
623
+ return;
624
+ }
625
+ curNode = c;
626
+ c.expand(false, false, f);
627
+ };
628
+ curNode.expand(false, false, f);
629
+ },
630
+
631
+ /**
632
+ * Selects the node in this tree at the specified path. A path can be retrieved from a node with {@link Ext.data.Node#getPath}
633
+ * @param {String} path
634
+ * @param {String} attr (optional) The attribute used in the path (see {@link Ext.data.Node#getPath} for more info)
635
+ * @param {Function} callback (optional) The callback to call when the selection is complete. The callback will be called with
636
+ * (bSuccess, oSelNode) where bSuccess is if the selection was successful and oSelNode is the selected node.
637
+ */
638
+ selectPath : function(path, attr, callback){
639
+ attr = attr || "id";
640
+ var keys = path.split(this.pathSeparator);
641
+ var v = keys.pop();
642
+ if(keys.length > 0){
643
+ var f = function(success, node){
644
+ if(success && node){
645
+ var n = node.findChild(attr, v);
646
+ if(n){
647
+ n.select();
648
+ if(callback){
649
+ callback(true, n);
650
+ }
651
+ }else if(callback){
652
+ callback(false, n);
653
+ }
654
+ }else{
655
+ if(callback){
656
+ callback(false, n);
657
+ }
658
+ }
659
+ };
660
+ this.expandPath(keys.join(this.pathSeparator), attr, f);
661
+ }else{
662
+ this.root.select();
663
+ if(callback){
664
+ callback(true, this.root);
665
+ }
666
+ }
667
+ },
668
+
669
+ /**
670
+ * Returns the underlying Element for this tree
671
+ * @return {Ext.Element} The Element
672
+ */
673
+ getTreeEl : function(){
674
+ return this.body;
675
+ },
676
+
677
+ // private
678
+ onRender : function(ct, position){
679
+ Ext.tree.TreePanel.superclass.onRender.call(this, ct, position);
680
+ this.el.addClass('x-tree');
681
+ this.innerCt = this.body.createChild({tag:"ul",
682
+ cls:"x-tree-root-ct " +
683
+ (this.useArrows ? 'x-tree-arrows' : this.lines ? "x-tree-lines" : "x-tree-no-lines")});
684
+ },
685
+
686
+ // private
687
+ initEvents : function(){
688
+ Ext.tree.TreePanel.superclass.initEvents.call(this);
689
+
690
+ if(this.containerScroll){
691
+ Ext.dd.ScrollManager.register(this.body);
692
+ }
693
+ if((this.enableDD || this.enableDrop) && !this.dropZone){
694
+ /**
695
+ * The dropZone used by this tree if drop is enabled (see {@link #enableDD} or {@link #enableDrop})
696
+ * @property dropZone
697
+ * @type Ext.tree.TreeDropZone
698
+ */
699
+ this.dropZone = new Ext.tree.TreeDropZone(this, this.dropConfig || {
700
+ ddGroup: this.ddGroup || "TreeDD", appendOnly: this.ddAppendOnly === true
701
+ });
702
+ }
703
+ if((this.enableDD || this.enableDrag) && !this.dragZone){
704
+ /**
705
+ * The dragZone used by this tree if drag is enabled (see {@link #enableDD} or {@link #enableDrag})
706
+ * @property dragZone
707
+ * @type Ext.tree.TreeDragZone
708
+ */
709
+ this.dragZone = new Ext.tree.TreeDragZone(this, this.dragConfig || {
710
+ ddGroup: this.ddGroup || "TreeDD",
711
+ scroll: this.ddScroll
712
+ });
713
+ }
714
+ this.getSelectionModel().init(this);
715
+ },
716
+
717
+ // private
718
+ afterRender : function(){
719
+ Ext.tree.TreePanel.superclass.afterRender.call(this);
720
+ this.root.render();
721
+ if(!this.rootVisible){
722
+ this.root.renderChildren();
723
+ }
724
+ },
725
+
726
+ onDestroy : function(){
727
+ if(this.rendered){
728
+ this.body.removeAllListeners();
729
+ Ext.dd.ScrollManager.unregister(this.body);
730
+ if(this.dropZone){
731
+ this.dropZone.unreg();
732
+ }
733
+ if(this.dragZone){
734
+ this.dragZone.unreg();
735
+ }
736
+ }
737
+ this.root.destroy();
738
+ this.nodeHash = null;
739
+ Ext.tree.TreePanel.superclass.onDestroy.call(this);
740
+ }
741
+
742
+ /**
743
+ * @cfg {String/Number} activeItem
744
+ * @hide
745
+ */
746
+ /**
747
+ * @cfg {Boolean} autoDestroy
748
+ * @hide
749
+ */
750
+ /**
751
+ * @cfg {Object/String/Function} autoLoad
752
+ * @hide
753
+ */
754
+ /**
755
+ * @cfg {Boolean} autoWidth
756
+ * @hide
757
+ */
758
+ /**
759
+ * @cfg {Boolean/Number} bufferResize
760
+ * @hide
761
+ */
762
+ /**
763
+ * @cfg {String} defaultType
764
+ * @hide
765
+ */
766
+ /**
767
+ * @cfg {Object} defaults
768
+ * @hide
769
+ */
770
+ /**
771
+ * @cfg {Boolean} hideBorders
772
+ * @hide
773
+ */
774
+ /**
775
+ * @cfg {Mixed} items
776
+ * @hide
777
+ */
778
+ /**
779
+ * @cfg {String} layout
780
+ * @hide
781
+ */
782
+ /**
783
+ * @cfg {Object} layoutConfig
784
+ * @hide
785
+ */
786
+ /**
787
+ * @cfg {Boolean} monitorResize
788
+ * @hide
789
+ */
790
+ /**
791
+ * @property items
792
+ * @hide
793
+ */
794
+ /**
795
+ * @method cascade
796
+ * @hide
797
+ */
798
+ /**
799
+ * @method doLayout
800
+ * @hide
801
+ */
802
+ /**
803
+ * @method find
804
+ * @hide
805
+ */
806
+ /**
807
+ * @method findBy
808
+ * @hide
809
+ */
810
+ /**
811
+ * @method findById
812
+ * @hide
813
+ */
814
+ /**
815
+ * @method findByType
816
+ * @hide
817
+ */
818
+ /**
819
+ * @method getComponent
820
+ * @hide
821
+ */
822
+ /**
823
+ * @method getLayout
824
+ * @hide
825
+ */
826
+ /**
827
+ * @method getUpdater
828
+ * @hide
829
+ */
830
+ /**
831
+ * @method insert
832
+ * @hide
833
+ */
834
+ /**
835
+ * @method load
836
+ * @hide
837
+ */
838
+ /**
839
+ * @method remove
840
+ * @hide
841
+ */
842
+ /**
843
+ * @event add
844
+ * @hide
845
+ */
846
+ /**
847
+ * @method removeAll
848
+ * @hide
849
+ */
850
+ /**
851
+ * @event afterLayout
852
+ * @hide
853
+ */
854
+ /**
855
+ * @event beforeadd
856
+ * @hide
857
+ */
858
+ /**
859
+ * @event beforeremove
860
+ * @hide
861
+ */
862
+ /**
863
+ * @event remove
864
+ * @hide
865
+ */
866
+
867
+
868
+
869
+ /**
870
+ * @cfg {String} allowDomMove @hide
871
+ */
872
+ /**
873
+ * @cfg {String} autoEl @hide
874
+ */
875
+ /**
876
+ * @cfg {String} applyTo @hide
877
+ */
878
+ /**
879
+ * @cfg {String} contentEl @hide
880
+ */
881
+ /**
882
+ * @cfg {String} disabledClass @hide
883
+ */
884
+ /**
885
+ * @cfg {String} elements @hide
886
+ */
887
+ /**
888
+ * @cfg {String} html @hide
889
+ */
890
+ /**
891
+ * @cfg {Boolean} preventBodyReset
892
+ * @hide
893
+ */
894
+ /**
895
+ * @property disabled
896
+ * @hide
897
+ */
898
+ /**
899
+ * @method applyToMarkup
900
+ * @hide
901
+ */
902
+ /**
903
+ * @method enable
904
+ * @hide
905
+ */
906
+ /**
907
+ * @method disable
908
+ * @hide
909
+ */
910
+ /**
911
+ * @method setDisabled
912
+ * @hide
913
+ */
914
+ });
915
+
916
+ Ext.tree.TreePanel.nodeTypes = {};
917
+
918
+ Ext.reg('treepanel', Ext.tree.TreePanel);Ext.tree.TreeEventModel = function(tree){
919
+ this.tree = tree;
920
+ this.tree.on('render', this.initEvents, this);
921
+ }
922
+
923
+ Ext.tree.TreeEventModel.prototype = {
924
+ initEvents : function(){
925
+ var el = this.tree.getTreeEl();
926
+ el.on('click', this.delegateClick, this);
927
+ if(this.tree.trackMouseOver !== false){
928
+ this.tree.innerCt.on('mouseover', this.delegateOver, this);
929
+ this.tree.innerCt.on('mouseout', this.delegateOut, this);
930
+ }
931
+ el.on('dblclick', this.delegateDblClick, this);
932
+ el.on('contextmenu', this.delegateContextMenu, this);
933
+ },
934
+
935
+ getNode : function(e){
936
+ var t;
937
+ if(t = e.getTarget('.x-tree-node-el', 10)){
938
+ var id = Ext.fly(t, '_treeEvents').getAttribute('tree-node-id', 'ext');
939
+ if(id){
940
+ return this.tree.getNodeById(id);
941
+ }
942
+ }
943
+ return null;
944
+ },
945
+
946
+ getNodeTarget : function(e){
947
+ var t = e.getTarget('.x-tree-node-icon', 1);
948
+ if(!t){
949
+ t = e.getTarget('.x-tree-node-el', 6);
950
+ }
951
+ return t;
952
+ },
953
+
954
+ delegateOut : function(e, t){
955
+ if(!this.beforeEvent(e)){
956
+ return;
957
+ }
958
+ if(e.getTarget('.x-tree-ec-icon', 1)){
959
+ var n = this.getNode(e);
960
+ this.onIconOut(e, n);
961
+ if(n == this.lastEcOver){
962
+ delete this.lastEcOver;
963
+ }
964
+ }
965
+ if((t = this.getNodeTarget(e)) && !e.within(t, true)){
966
+ this.onNodeOut(e, this.getNode(e));
967
+ }
968
+ },
969
+
970
+ delegateOver : function(e, t){
971
+ if(!this.beforeEvent(e)){
972
+ return;
973
+ }
974
+ if(Ext.isGecko && !this.trackingDoc){ // prevent hanging in FF
975
+ Ext.getBody().on('mouseover', this.trackExit, this);
976
+ this.trackingDoc = true;
977
+ }
978
+ if(this.lastEcOver){ // prevent hung highlight
979
+ this.onIconOut(e, this.lastEcOver);
980
+ delete this.lastEcOver;
981
+ }
982
+ if(e.getTarget('.x-tree-ec-icon', 1)){
983
+ this.lastEcOver = this.getNode(e);
984
+ this.onIconOver(e, this.lastEcOver);
985
+ }
986
+ if(t = this.getNodeTarget(e)){
987
+ this.onNodeOver(e, this.getNode(e));
988
+ }
989
+ },
990
+
991
+ trackExit : function(e){
992
+ if(this.lastOverNode && !e.within(this.lastOverNode.ui.getEl())){
993
+ this.onNodeOut(e, this.lastOverNode);
994
+ delete this.lastOverNode;
995
+ Ext.getBody().un('mouseover', this.trackExit, this);
996
+ this.trackingDoc = false;
997
+ }
998
+ },
999
+
1000
+ delegateClick : function(e, t){
1001
+ if(!this.beforeEvent(e)){
1002
+ return;
1003
+ }
1004
+
1005
+ if(e.getTarget('input[type=checkbox]', 1)){
1006
+ this.onCheckboxClick(e, this.getNode(e));
1007
+ }
1008
+ else if(e.getTarget('.x-tree-ec-icon', 1)){
1009
+ this.onIconClick(e, this.getNode(e));
1010
+ }
1011
+ else if(this.getNodeTarget(e)){
1012
+ this.onNodeClick(e, this.getNode(e));
1013
+ }
1014
+ },
1015
+
1016
+ delegateDblClick : function(e, t){
1017
+ if(this.beforeEvent(e) && this.getNodeTarget(e)){
1018
+ this.onNodeDblClick(e, this.getNode(e));
1019
+ }
1020
+ },
1021
+
1022
+ delegateContextMenu : function(e, t){
1023
+ if(this.beforeEvent(e) && this.getNodeTarget(e)){
1024
+ this.onNodeContextMenu(e, this.getNode(e));
1025
+ }
1026
+ },
1027
+
1028
+ onNodeClick : function(e, node){
1029
+ node.ui.onClick(e);
1030
+ },
1031
+
1032
+ onNodeOver : function(e, node){
1033
+ this.lastOverNode = node;
1034
+ node.ui.onOver(e);
1035
+ },
1036
+
1037
+ onNodeOut : function(e, node){
1038
+ node.ui.onOut(e);
1039
+ },
1040
+
1041
+ onIconOver : function(e, node){
1042
+ node.ui.addClass('x-tree-ec-over');
1043
+ },
1044
+
1045
+ onIconOut : function(e, node){
1046
+ node.ui.removeClass('x-tree-ec-over');
1047
+ },
1048
+
1049
+ onIconClick : function(e, node){
1050
+ node.ui.ecClick(e);
1051
+ },
1052
+
1053
+ onCheckboxClick : function(e, node){
1054
+ node.ui.onCheckChange(e);
1055
+ },
1056
+
1057
+ onNodeDblClick : function(e, node){
1058
+ node.ui.onDblClick(e);
1059
+ },
1060
+
1061
+ onNodeContextMenu : function(e, node){
1062
+ node.ui.onContextMenu(e);
1063
+ },
1064
+
1065
+ beforeEvent : function(e){
1066
+ if(this.disabled){
1067
+ e.stopEvent();
1068
+ return false;
1069
+ }
1070
+ return true;
1071
+ },
1072
+
1073
+ disable: function(){
1074
+ this.disabled = true;
1075
+ },
1076
+
1077
+ enable: function(){
1078
+ this.disabled = false;
1079
+ }
1080
+ };/**
1081
+ * @class Ext.tree.DefaultSelectionModel
1082
+ * @extends Ext.util.Observable
1083
+ * The default single selection for a TreePanel.
1084
+ */
1085
+ Ext.tree.DefaultSelectionModel = function(config){
1086
+ this.selNode = null;
1087
+
1088
+ this.addEvents(
1089
+ /**
1090
+ * @event selectionchange
1091
+ * Fires when the selected node changes
1092
+ * @param {DefaultSelectionModel} this
1093
+ * @param {TreeNode} node the new selection
1094
+ */
1095
+ "selectionchange",
1096
+
1097
+ /**
1098
+ * @event beforeselect
1099
+ * Fires before the selected node changes, return false to cancel the change
1100
+ * @param {DefaultSelectionModel} this
1101
+ * @param {TreeNode} node the new selection
1102
+ * @param {TreeNode} node the old selection
1103
+ */
1104
+ "beforeselect"
1105
+ );
1106
+
1107
+ Ext.apply(this, config);
1108
+ Ext.tree.DefaultSelectionModel.superclass.constructor.call(this);
1109
+ };
1110
+
1111
+ Ext.extend(Ext.tree.DefaultSelectionModel, Ext.util.Observable, {
1112
+ init : function(tree){
1113
+ this.tree = tree;
1114
+ tree.getTreeEl().on("keydown", this.onKeyDown, this);
1115
+ tree.on("click", this.onNodeClick, this);
1116
+ },
1117
+
1118
+ onNodeClick : function(node, e){
1119
+ this.select(node);
1120
+ },
1121
+
1122
+ /**
1123
+ * Select a node.
1124
+ * @param {TreeNode} node The node to select
1125
+ * @return {TreeNode} The selected node
1126
+ */
1127
+ select : function(node){
1128
+ var last = this.selNode;
1129
+ if(node == last){
1130
+ node.ui.onSelectedChange(true);
1131
+ }else if(this.fireEvent('beforeselect', this, node, last) !== false){
1132
+ if(last){
1133
+ last.ui.onSelectedChange(false);
1134
+ }
1135
+ this.selNode = node;
1136
+ node.ui.onSelectedChange(true);
1137
+ this.fireEvent("selectionchange", this, node, last);
1138
+ }
1139
+ return node;
1140
+ },
1141
+
1142
+ /**
1143
+ * Deselect a node.
1144
+ * @param {TreeNode} node The node to unselect
1145
+ */
1146
+ unselect : function(node){
1147
+ if(this.selNode == node){
1148
+ this.clearSelections();
1149
+ }
1150
+ },
1151
+
1152
+ /**
1153
+ * Clear all selections
1154
+ */
1155
+ clearSelections : function(){
1156
+ var n = this.selNode;
1157
+ if(n){
1158
+ n.ui.onSelectedChange(false);
1159
+ this.selNode = null;
1160
+ this.fireEvent("selectionchange", this, null);
1161
+ }
1162
+ return n;
1163
+ },
1164
+
1165
+ /**
1166
+ * Get the selected node
1167
+ * @return {TreeNode} The selected node
1168
+ */
1169
+ getSelectedNode : function(){
1170
+ return this.selNode;
1171
+ },
1172
+
1173
+ /**
1174
+ * Returns true if the node is selected
1175
+ * @param {TreeNode} node The node to check
1176
+ * @return {Boolean}
1177
+ */
1178
+ isSelected : function(node){
1179
+ return this.selNode == node;
1180
+ },
1181
+
1182
+ /**
1183
+ * Selects the node above the selected node in the tree, intelligently walking the nodes
1184
+ * @return TreeNode The new selection
1185
+ */
1186
+ selectPrevious : function(){
1187
+ var s = this.selNode || this.lastSelNode;
1188
+ if(!s){
1189
+ return null;
1190
+ }
1191
+ var ps = s.previousSibling;
1192
+ if(ps){
1193
+ if(!ps.isExpanded() || ps.childNodes.length < 1){
1194
+ return this.select(ps);
1195
+ } else{
1196
+ var lc = ps.lastChild;
1197
+ while(lc && lc.isExpanded() && lc.childNodes.length > 0){
1198
+ lc = lc.lastChild;
1199
+ }
1200
+ return this.select(lc);
1201
+ }
1202
+ } else if(s.parentNode && (this.tree.rootVisible || !s.parentNode.isRoot)){
1203
+ return this.select(s.parentNode);
1204
+ }
1205
+ return null;
1206
+ },
1207
+
1208
+ /**
1209
+ * Selects the node above the selected node in the tree, intelligently walking the nodes
1210
+ * @return TreeNode The new selection
1211
+ */
1212
+ selectNext : function(){
1213
+ var s = this.selNode || this.lastSelNode;
1214
+ if(!s){
1215
+ return null;
1216
+ }
1217
+ if(s.firstChild && s.isExpanded()){
1218
+ return this.select(s.firstChild);
1219
+ }else if(s.nextSibling){
1220
+ return this.select(s.nextSibling);
1221
+ }else if(s.parentNode){
1222
+ var newS = null;
1223
+ s.parentNode.bubble(function(){
1224
+ if(this.nextSibling){
1225
+ newS = this.getOwnerTree().selModel.select(this.nextSibling);
1226
+ return false;
1227
+ }
1228
+ });
1229
+ return newS;
1230
+ }
1231
+ return null;
1232
+ },
1233
+
1234
+ onKeyDown : function(e){
1235
+ var s = this.selNode || this.lastSelNode;
1236
+ // undesirable, but required
1237
+ var sm = this;
1238
+ if(!s){
1239
+ return;
1240
+ }
1241
+ var k = e.getKey();
1242
+ switch(k){
1243
+ case e.DOWN:
1244
+ e.stopEvent();
1245
+ this.selectNext();
1246
+ break;
1247
+ case e.UP:
1248
+ e.stopEvent();
1249
+ this.selectPrevious();
1250
+ break;
1251
+ case e.RIGHT:
1252
+ e.preventDefault();
1253
+ if(s.hasChildNodes()){
1254
+ if(!s.isExpanded()){
1255
+ s.expand();
1256
+ }else if(s.firstChild){
1257
+ this.select(s.firstChild, e);
1258
+ }
1259
+ }
1260
+ break;
1261
+ case e.LEFT:
1262
+ e.preventDefault();
1263
+ if(s.hasChildNodes() && s.isExpanded()){
1264
+ s.collapse();
1265
+ }else if(s.parentNode && (this.tree.rootVisible || s.parentNode != this.tree.getRootNode())){
1266
+ this.select(s.parentNode, e);
1267
+ }
1268
+ break;
1269
+ };
1270
+ }
1271
+ });
1272
+
1273
+ /**
1274
+ * @class Ext.tree.MultiSelectionModel
1275
+ * @extends Ext.util.Observable
1276
+ * Multi selection for a TreePanel.
1277
+ */
1278
+ Ext.tree.MultiSelectionModel = function(config){
1279
+ this.selNodes = [];
1280
+ this.selMap = {};
1281
+ this.addEvents(
1282
+ /**
1283
+ * @event selectionchange
1284
+ * Fires when the selected nodes change
1285
+ * @param {MultiSelectionModel} this
1286
+ * @param {Array} nodes Array of the selected nodes
1287
+ */
1288
+ "selectionchange"
1289
+ );
1290
+ Ext.apply(this, config);
1291
+ Ext.tree.MultiSelectionModel.superclass.constructor.call(this);
1292
+ };
1293
+
1294
+ Ext.extend(Ext.tree.MultiSelectionModel, Ext.util.Observable, {
1295
+ init : function(tree){
1296
+ this.tree = tree;
1297
+ tree.getTreeEl().on("keydown", this.onKeyDown, this);
1298
+ tree.on("click", this.onNodeClick, this);
1299
+ },
1300
+
1301
+ onNodeClick : function(node, e){
1302
+ if(e.ctrlKey && this.isSelected(node)){
1303
+ this.unselect(node);
1304
+ }else{
1305
+ this.select(node, e, e.ctrlKey);
1306
+ }
1307
+ },
1308
+
1309
+ /**
1310
+ * Select a node.
1311
+ * @param {TreeNode} node The node to select
1312
+ * @param {EventObject} e (optional) An event associated with the selection
1313
+ * @param {Boolean} keepExisting True to retain existing selections
1314
+ * @return {TreeNode} The selected node
1315
+ */
1316
+ select : function(node, e, keepExisting){
1317
+ if(keepExisting !== true){
1318
+ this.clearSelections(true);
1319
+ }
1320
+ if(this.isSelected(node)){
1321
+ this.lastSelNode = node;
1322
+ return node;
1323
+ }
1324
+ this.selNodes.push(node);
1325
+ this.selMap[node.id] = node;
1326
+ this.lastSelNode = node;
1327
+ node.ui.onSelectedChange(true);
1328
+ this.fireEvent("selectionchange", this, this.selNodes);
1329
+ return node;
1330
+ },
1331
+
1332
+ /**
1333
+ * Deselect a node.
1334
+ * @param {TreeNode} node The node to unselect
1335
+ */
1336
+ unselect : function(node){
1337
+ if(this.selMap[node.id]){
1338
+ node.ui.onSelectedChange(false);
1339
+ var sn = this.selNodes;
1340
+ var index = sn.indexOf(node);
1341
+ if(index != -1){
1342
+ this.selNodes.splice(index, 1);
1343
+ }
1344
+ delete this.selMap[node.id];
1345
+ this.fireEvent("selectionchange", this, this.selNodes);
1346
+ }
1347
+ },
1348
+
1349
+ /**
1350
+ * Clear all selections
1351
+ */
1352
+ clearSelections : function(suppressEvent){
1353
+ var sn = this.selNodes;
1354
+ if(sn.length > 0){
1355
+ for(var i = 0, len = sn.length; i < len; i++){
1356
+ sn[i].ui.onSelectedChange(false);
1357
+ }
1358
+ this.selNodes = [];
1359
+ this.selMap = {};
1360
+ if(suppressEvent !== true){
1361
+ this.fireEvent("selectionchange", this, this.selNodes);
1362
+ }
1363
+ }
1364
+ },
1365
+
1366
+ /**
1367
+ * Returns true if the node is selected
1368
+ * @param {TreeNode} node The node to check
1369
+ * @return {Boolean}
1370
+ */
1371
+ isSelected : function(node){
1372
+ return this.selMap[node.id] ? true : false;
1373
+ },
1374
+
1375
+ /**
1376
+ * Returns an array of the selected nodes
1377
+ * @return {Array}
1378
+ */
1379
+ getSelectedNodes : function(){
1380
+ return this.selNodes;
1381
+ },
1382
+
1383
+ onKeyDown : Ext.tree.DefaultSelectionModel.prototype.onKeyDown,
1384
+
1385
+ selectNext : Ext.tree.DefaultSelectionModel.prototype.selectNext,
1386
+
1387
+ selectPrevious : Ext.tree.DefaultSelectionModel.prototype.selectPrevious
1388
+ });/**
1389
+ * @class Ext.data.Tree
1390
+ * @extends Ext.util.Observable
1391
+ * Represents a tree data structure and bubbles all the events for its nodes. The nodes
1392
+ * in the tree have most standard DOM functionality.
1393
+ * @constructor
1394
+ * @param {Node} root (optional) The root node
1395
+ */
1396
+ Ext.data.Tree = function(root){
1397
+ this.nodeHash = {};
1398
+ /**
1399
+ * The root node for this tree
1400
+ * @type Node
1401
+ */
1402
+ this.root = null;
1403
+ if(root){
1404
+ this.setRootNode(root);
1405
+ }
1406
+ this.addEvents(
1407
+ /**
1408
+ * @event append
1409
+ * Fires when a new child node is appended to a node in this tree.
1410
+ * @param {Tree} tree The owner tree
1411
+ * @param {Node} parent The parent node
1412
+ * @param {Node} node The newly appended node
1413
+ * @param {Number} index The index of the newly appended node
1414
+ */
1415
+ "append",
1416
+ /**
1417
+ * @event remove
1418
+ * Fires when a child node is removed from a node in this tree.
1419
+ * @param {Tree} tree The owner tree
1420
+ * @param {Node} parent The parent node
1421
+ * @param {Node} node The child node removed
1422
+ */
1423
+ "remove",
1424
+ /**
1425
+ * @event move
1426
+ * Fires when a node is moved to a new location in the tree
1427
+ * @param {Tree} tree The owner tree
1428
+ * @param {Node} node The node moved
1429
+ * @param {Node} oldParent The old parent of this node
1430
+ * @param {Node} newParent The new parent of this node
1431
+ * @param {Number} index The index it was moved to
1432
+ */
1433
+ "move",
1434
+ /**
1435
+ * @event insert
1436
+ * Fires when a new child node is inserted in a node in this tree.
1437
+ * @param {Tree} tree The owner tree
1438
+ * @param {Node} parent The parent node
1439
+ * @param {Node} node The child node inserted
1440
+ * @param {Node} refNode The child node the node was inserted before
1441
+ */
1442
+ "insert",
1443
+ /**
1444
+ * @event beforeappend
1445
+ * Fires before a new child is appended to a node in this tree, return false to cancel the append.
1446
+ * @param {Tree} tree The owner tree
1447
+ * @param {Node} parent The parent node
1448
+ * @param {Node} node The child node to be appended
1449
+ */
1450
+ "beforeappend",
1451
+ /**
1452
+ * @event beforeremove
1453
+ * Fires before a child is removed from a node in this tree, return false to cancel the remove.
1454
+ * @param {Tree} tree The owner tree
1455
+ * @param {Node} parent The parent node
1456
+ * @param {Node} node The child node to be removed
1457
+ */
1458
+ "beforeremove",
1459
+ /**
1460
+ * @event beforemove
1461
+ * Fires before a node is moved to a new location in the tree. Return false to cancel the move.
1462
+ * @param {Tree} tree The owner tree
1463
+ * @param {Node} node The node being moved
1464
+ * @param {Node} oldParent The parent of the node
1465
+ * @param {Node} newParent The new parent the node is moving to
1466
+ * @param {Number} index The index it is being moved to
1467
+ */
1468
+ "beforemove",
1469
+ /**
1470
+ * @event beforeinsert
1471
+ * Fires before a new child is inserted in a node in this tree, return false to cancel the insert.
1472
+ * @param {Tree} tree The owner tree
1473
+ * @param {Node} parent The parent node
1474
+ * @param {Node} node The child node to be inserted
1475
+ * @param {Node} refNode The child node the node is being inserted before
1476
+ */
1477
+ "beforeinsert"
1478
+ );
1479
+
1480
+ Ext.data.Tree.superclass.constructor.call(this);
1481
+ };
1482
+
1483
+ Ext.extend(Ext.data.Tree, Ext.util.Observable, {
1484
+ /**
1485
+ * @cfg {String} pathSeparator
1486
+ * The token used to separate paths in node ids (defaults to '/').
1487
+ */
1488
+ pathSeparator: "/",
1489
+
1490
+ // private
1491
+ proxyNodeEvent : function(){
1492
+ return this.fireEvent.apply(this, arguments);
1493
+ },
1494
+
1495
+ /**
1496
+ * Returns the root node for this tree.
1497
+ * @return {Node}
1498
+ */
1499
+ getRootNode : function(){
1500
+ return this.root;
1501
+ },
1502
+
1503
+ /**
1504
+ * Sets the root node for this tree.
1505
+ * @param {Node} node
1506
+ * @return {Node}
1507
+ */
1508
+ setRootNode : function(node){
1509
+ this.root = node;
1510
+ node.ownerTree = this;
1511
+ node.isRoot = true;
1512
+ this.registerNode(node);
1513
+ return node;
1514
+ },
1515
+
1516
+ /**
1517
+ * Gets a node in this tree by its id.
1518
+ * @param {String} id
1519
+ * @return {Node}
1520
+ */
1521
+ getNodeById : function(id){
1522
+ return this.nodeHash[id];
1523
+ },
1524
+
1525
+ // private
1526
+ registerNode : function(node){
1527
+ this.nodeHash[node.id] = node;
1528
+ },
1529
+
1530
+ // private
1531
+ unregisterNode : function(node){
1532
+ delete this.nodeHash[node.id];
1533
+ },
1534
+
1535
+ toString : function(){
1536
+ return "[Tree"+(this.id?" "+this.id:"")+"]";
1537
+ }
1538
+ });
1539
+
1540
+ /**
1541
+ * @class Ext.data.Node
1542
+ * @extends Ext.util.Observable
1543
+ * @cfg {Boolean} leaf true if this node is a leaf and does not have children
1544
+ * @cfg {String} id The id for this node. If one is not specified, one is generated.
1545
+ * @constructor
1546
+ * @param {Object} attributes The attributes/config for the node
1547
+ */
1548
+ Ext.data.Node = function(attributes){
1549
+ /**
1550
+ * The attributes supplied for the node. You can use this property to access any custom attributes you supplied.
1551
+ * @type {Object}
1552
+ */
1553
+ this.attributes = attributes || {};
1554
+ this.leaf = this.attributes.leaf;
1555
+ /**
1556
+ * The node id. @type String
1557
+ */
1558
+ this.id = this.attributes.id;
1559
+ if(!this.id){
1560
+ this.id = Ext.id(null, "xnode-");
1561
+ this.attributes.id = this.id;
1562
+ }
1563
+ /**
1564
+ * All child nodes of this node. @type Array
1565
+ */
1566
+ this.childNodes = [];
1567
+ if(!this.childNodes.indexOf){ // indexOf is a must
1568
+ this.childNodes.indexOf = function(o){
1569
+ for(var i = 0, len = this.length; i < len; i++){
1570
+ if(this[i] == o){
1571
+ return i;
1572
+ }
1573
+ }
1574
+ return -1;
1575
+ };
1576
+ }
1577
+ /**
1578
+ * The parent node for this node. @type Node
1579
+ */
1580
+ this.parentNode = null;
1581
+ /**
1582
+ * The first direct child node of this node, or null if this node has no child nodes. @type Node
1583
+ */
1584
+ this.firstChild = null;
1585
+ /**
1586
+ * The last direct child node of this node, or null if this node has no child nodes. @type Node
1587
+ */
1588
+ this.lastChild = null;
1589
+ /**
1590
+ * The node immediately preceding this node in the tree, or null if there is no sibling node. @type Node
1591
+ */
1592
+ this.previousSibling = null;
1593
+ /**
1594
+ * The node immediately following this node in the tree, or null if there is no sibling node. @type Node
1595
+ */
1596
+ this.nextSibling = null;
1597
+
1598
+ this.addEvents({
1599
+ /**
1600
+ * @event append
1601
+ * Fires when a new child node is appended
1602
+ * @param {Tree} tree The owner tree
1603
+ * @param {Node} this This node
1604
+ * @param {Node} node The newly appended node
1605
+ * @param {Number} index The index of the newly appended node
1606
+ */
1607
+ "append" : true,
1608
+ /**
1609
+ * @event remove
1610
+ * Fires when a child node is removed
1611
+ * @param {Tree} tree The owner tree
1612
+ * @param {Node} this This node
1613
+ * @param {Node} node The removed node
1614
+ */
1615
+ "remove" : true,
1616
+ /**
1617
+ * @event move
1618
+ * Fires when this node is moved to a new location in the tree
1619
+ * @param {Tree} tree The owner tree
1620
+ * @param {Node} this This node
1621
+ * @param {Node} oldParent The old parent of this node
1622
+ * @param {Node} newParent The new parent of this node
1623
+ * @param {Number} index The index it was moved to
1624
+ */
1625
+ "move" : true,
1626
+ /**
1627
+ * @event insert
1628
+ * Fires when a new child node is inserted.
1629
+ * @param {Tree} tree The owner tree
1630
+ * @param {Node} this This node
1631
+ * @param {Node} node The child node inserted
1632
+ * @param {Node} refNode The child node the node was inserted before
1633
+ */
1634
+ "insert" : true,
1635
+ /**
1636
+ * @event beforeappend
1637
+ * Fires before a new child is appended, return false to cancel the append.
1638
+ * @param {Tree} tree The owner tree
1639
+ * @param {Node} this This node
1640
+ * @param {Node} node The child node to be appended
1641
+ */
1642
+ "beforeappend" : true,
1643
+ /**
1644
+ * @event beforeremove
1645
+ * Fires before a child is removed, return false to cancel the remove.
1646
+ * @param {Tree} tree The owner tree
1647
+ * @param {Node} this This node
1648
+ * @param {Node} node The child node to be removed
1649
+ */
1650
+ "beforeremove" : true,
1651
+ /**
1652
+ * @event beforemove
1653
+ * Fires before this node is moved to a new location in the tree. Return false to cancel the move.
1654
+ * @param {Tree} tree The owner tree
1655
+ * @param {Node} this This node
1656
+ * @param {Node} oldParent The parent of this node
1657
+ * @param {Node} newParent The new parent this node is moving to
1658
+ * @param {Number} index The index it is being moved to
1659
+ */
1660
+ "beforemove" : true,
1661
+ /**
1662
+ * @event beforeinsert
1663
+ * Fires before a new child is inserted, return false to cancel the insert.
1664
+ * @param {Tree} tree The owner tree
1665
+ * @param {Node} this This node
1666
+ * @param {Node} node The child node to be inserted
1667
+ * @param {Node} refNode The child node the node is being inserted before
1668
+ */
1669
+ "beforeinsert" : true
1670
+ });
1671
+ this.listeners = this.attributes.listeners;
1672
+ Ext.data.Node.superclass.constructor.call(this);
1673
+ };
1674
+
1675
+ Ext.extend(Ext.data.Node, Ext.util.Observable, {
1676
+ // private
1677
+ fireEvent : function(evtName){
1678
+ // first do standard event for this node
1679
+ if(Ext.data.Node.superclass.fireEvent.apply(this, arguments) === false){
1680
+ return false;
1681
+ }
1682
+ // then bubble it up to the tree if the event wasn't cancelled
1683
+ var ot = this.getOwnerTree();
1684
+ if(ot){
1685
+ if(ot.proxyNodeEvent.apply(ot, arguments) === false){
1686
+ return false;
1687
+ }
1688
+ }
1689
+ return true;
1690
+ },
1691
+
1692
+ /**
1693
+ * Returns true if this node is a leaf
1694
+ * @return {Boolean}
1695
+ */
1696
+ isLeaf : function(){
1697
+ return this.leaf === true;
1698
+ },
1699
+
1700
+ // private
1701
+ setFirstChild : function(node){
1702
+ this.firstChild = node;
1703
+ },
1704
+
1705
+ //private
1706
+ setLastChild : function(node){
1707
+ this.lastChild = node;
1708
+ },
1709
+
1710
+
1711
+ /**
1712
+ * Returns true if this node is the last child of its parent
1713
+ * @return {Boolean}
1714
+ */
1715
+ isLast : function(){
1716
+ return (!this.parentNode ? true : this.parentNode.lastChild == this);
1717
+ },
1718
+
1719
+ /**
1720
+ * Returns true if this node is the first child of its parent
1721
+ * @return {Boolean}
1722
+ */
1723
+ isFirst : function(){
1724
+ return (!this.parentNode ? true : this.parentNode.firstChild == this);
1725
+ },
1726
+
1727
+ /**
1728
+ * Returns true if this node has one or more child nodes, else false.
1729
+ * @return {Boolean}
1730
+ */
1731
+ hasChildNodes : function(){
1732
+ return !this.isLeaf() && this.childNodes.length > 0;
1733
+ },
1734
+
1735
+ /**
1736
+ * Returns true if this node has one or more child nodes, or if the <tt>expandable</tt>
1737
+ * node attribute is explicitly specified as true (see {@link #attributes}), otherwise returns false.
1738
+ * @return {Boolean}
1739
+ */
1740
+ isExpandable : function(){
1741
+ return this.attributes.expandable || this.hasChildNodes();
1742
+ },
1743
+
1744
+ /**
1745
+ * Insert node(s) as the last child node of this node.
1746
+ * @param {Node/Array} node The node or Array of nodes to append
1747
+ * @return {Node} The appended node if single append, or null if an array was passed
1748
+ */
1749
+ appendChild : function(node){
1750
+ var multi = false;
1751
+ if(Ext.isArray(node)){
1752
+ multi = node;
1753
+ }else if(arguments.length > 1){
1754
+ multi = arguments;
1755
+ }
1756
+ // if passed an array or multiple args do them one by one
1757
+ if(multi){
1758
+ for(var i = 0, len = multi.length; i < len; i++) {
1759
+ this.appendChild(multi[i]);
1760
+ }
1761
+ }else{
1762
+ if(this.fireEvent("beforeappend", this.ownerTree, this, node) === false){
1763
+ return false;
1764
+ }
1765
+ var index = this.childNodes.length;
1766
+ var oldParent = node.parentNode;
1767
+ // it's a move, make sure we move it cleanly
1768
+ if(oldParent){
1769
+ if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index) === false){
1770
+ return false;
1771
+ }
1772
+ oldParent.removeChild(node);
1773
+ }
1774
+ index = this.childNodes.length;
1775
+ if(index === 0){
1776
+ this.setFirstChild(node);
1777
+ }
1778
+ this.childNodes.push(node);
1779
+ node.parentNode = this;
1780
+ var ps = this.childNodes[index-1];
1781
+ if(ps){
1782
+ node.previousSibling = ps;
1783
+ ps.nextSibling = node;
1784
+ }else{
1785
+ node.previousSibling = null;
1786
+ }
1787
+ node.nextSibling = null;
1788
+ this.setLastChild(node);
1789
+ node.setOwnerTree(this.getOwnerTree());
1790
+ this.fireEvent("append", this.ownerTree, this, node, index);
1791
+ if(oldParent){
1792
+ node.fireEvent("move", this.ownerTree, node, oldParent, this, index);
1793
+ }
1794
+ return node;
1795
+ }
1796
+ },
1797
+
1798
+ /**
1799
+ * Removes a child node from this node.
1800
+ * @param {Node} node The node to remove
1801
+ * @return {Node} The removed node
1802
+ */
1803
+ removeChild : function(node){
1804
+ var index = this.childNodes.indexOf(node);
1805
+ if(index == -1){
1806
+ return false;
1807
+ }
1808
+ if(this.fireEvent("beforeremove", this.ownerTree, this, node) === false){
1809
+ return false;
1810
+ }
1811
+
1812
+ // remove it from childNodes collection
1813
+ this.childNodes.splice(index, 1);
1814
+
1815
+ // update siblings
1816
+ if(node.previousSibling){
1817
+ node.previousSibling.nextSibling = node.nextSibling;
1818
+ }
1819
+ if(node.nextSibling){
1820
+ node.nextSibling.previousSibling = node.previousSibling;
1821
+ }
1822
+
1823
+ // update child refs
1824
+ if(this.firstChild == node){
1825
+ this.setFirstChild(node.nextSibling);
1826
+ }
1827
+ if(this.lastChild == node){
1828
+ this.setLastChild(node.previousSibling);
1829
+ }
1830
+
1831
+ node.setOwnerTree(null);
1832
+ // clear any references from the node
1833
+ node.parentNode = null;
1834
+ node.previousSibling = null;
1835
+ node.nextSibling = null;
1836
+ this.fireEvent("remove", this.ownerTree, this, node);
1837
+ return node;
1838
+ },
1839
+
1840
+ /**
1841
+ * Inserts the first node before the second node in this nodes childNodes collection.
1842
+ * @param {Node} node The node to insert
1843
+ * @param {Node} refNode The node to insert before (if null the node is appended)
1844
+ * @return {Node} The inserted node
1845
+ */
1846
+ insertBefore : function(node, refNode){
1847
+ if(!refNode){ // like standard Dom, refNode can be null for append
1848
+ return this.appendChild(node);
1849
+ }
1850
+ // nothing to do
1851
+ if(node == refNode){
1852
+ return false;
1853
+ }
1854
+
1855
+ if(this.fireEvent("beforeinsert", this.ownerTree, this, node, refNode) === false){
1856
+ return false;
1857
+ }
1858
+ var index = this.childNodes.indexOf(refNode);
1859
+ var oldParent = node.parentNode;
1860
+ var refIndex = index;
1861
+
1862
+ // when moving internally, indexes will change after remove
1863
+ if(oldParent == this && this.childNodes.indexOf(node) < index){
1864
+ refIndex--;
1865
+ }
1866
+
1867
+ // it's a move, make sure we move it cleanly
1868
+ if(oldParent){
1869
+ if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index, refNode) === false){
1870
+ return false;
1871
+ }
1872
+ oldParent.removeChild(node);
1873
+ }
1874
+ if(refIndex === 0){
1875
+ this.setFirstChild(node);
1876
+ }
1877
+ this.childNodes.splice(refIndex, 0, node);
1878
+ node.parentNode = this;
1879
+ var ps = this.childNodes[refIndex-1];
1880
+ if(ps){
1881
+ node.previousSibling = ps;
1882
+ ps.nextSibling = node;
1883
+ }else{
1884
+ node.previousSibling = null;
1885
+ }
1886
+ node.nextSibling = refNode;
1887
+ refNode.previousSibling = node;
1888
+ node.setOwnerTree(this.getOwnerTree());
1889
+ this.fireEvent("insert", this.ownerTree, this, node, refNode);
1890
+ if(oldParent){
1891
+ node.fireEvent("move", this.ownerTree, node, oldParent, this, refIndex, refNode);
1892
+ }
1893
+ return node;
1894
+ },
1895
+
1896
+ /**
1897
+ * Removes this node from its parent
1898
+ * @return {Node} this
1899
+ */
1900
+ remove : function(){
1901
+ this.parentNode.removeChild(this);
1902
+ return this;
1903
+ },
1904
+
1905
+ /**
1906
+ * Returns the child node at the specified index.
1907
+ * @param {Number} index
1908
+ * @return {Node}
1909
+ */
1910
+ item : function(index){
1911
+ return this.childNodes[index];
1912
+ },
1913
+
1914
+ /**
1915
+ * Replaces one child node in this node with another.
1916
+ * @param {Node} newChild The replacement node
1917
+ * @param {Node} oldChild The node to replace
1918
+ * @return {Node} The replaced node
1919
+ */
1920
+ replaceChild : function(newChild, oldChild){
1921
+ var s = oldChild ? oldChild.nextSibling : null;
1922
+ this.removeChild(oldChild);
1923
+ this.insertBefore(newChild, s);
1924
+ return oldChild;
1925
+ },
1926
+
1927
+ /**
1928
+ * Returns the index of a child node
1929
+ * @param {Node} node
1930
+ * @return {Number} The index of the node or -1 if it was not found
1931
+ */
1932
+ indexOf : function(child){
1933
+ return this.childNodes.indexOf(child);
1934
+ },
1935
+
1936
+ /**
1937
+ * Returns the tree this node is in.
1938
+ * @return {Tree}
1939
+ */
1940
+ getOwnerTree : function(){
1941
+ // if it doesn't have one, look for one
1942
+ if(!this.ownerTree){
1943
+ var p = this;
1944
+ while(p){
1945
+ if(p.ownerTree){
1946
+ this.ownerTree = p.ownerTree;
1947
+ break;
1948
+ }
1949
+ p = p.parentNode;
1950
+ }
1951
+ }
1952
+ return this.ownerTree;
1953
+ },
1954
+
1955
+ /**
1956
+ * Returns depth of this node (the root node has a depth of 0)
1957
+ * @return {Number}
1958
+ */
1959
+ getDepth : function(){
1960
+ var depth = 0;
1961
+ var p = this;
1962
+ while(p.parentNode){
1963
+ ++depth;
1964
+ p = p.parentNode;
1965
+ }
1966
+ return depth;
1967
+ },
1968
+
1969
+ // private
1970
+ setOwnerTree : function(tree){
1971
+ // if it is a move, we need to update everyone
1972
+ if(tree != this.ownerTree){
1973
+ if(this.ownerTree){
1974
+ this.ownerTree.unregisterNode(this);
1975
+ }
1976
+ this.ownerTree = tree;
1977
+ var cs = this.childNodes;
1978
+ for(var i = 0, len = cs.length; i < len; i++) {
1979
+ cs[i].setOwnerTree(tree);
1980
+ }
1981
+ if(tree){
1982
+ tree.registerNode(this);
1983
+ }
1984
+ }
1985
+ },
1986
+
1987
+ /**
1988
+ * Changes the id of this node.
1989
+ * @param {String} id The new id for the node.
1990
+ */
1991
+ setId: function(id){
1992
+ if(id !== this.id){
1993
+ var t = this.ownerTree;
1994
+ if(t){
1995
+ t.unregisterNode(this);
1996
+ }
1997
+ this.id = id;
1998
+ if(t){
1999
+ t.registerNode(this);
2000
+ }
2001
+ this.onIdChange(id);
2002
+ }
2003
+ },
2004
+
2005
+ // private
2006
+ onIdChange: Ext.emptyFn,
2007
+
2008
+ /**
2009
+ * Returns the path for this node. The path can be used to expand or select this node programmatically.
2010
+ * @param {String} attr (optional) The attr to use for the path (defaults to the node's id)
2011
+ * @return {String} The path
2012
+ */
2013
+ getPath : function(attr){
2014
+ attr = attr || "id";
2015
+ var p = this.parentNode;
2016
+ var b = [this.attributes[attr]];
2017
+ while(p){
2018
+ b.unshift(p.attributes[attr]);
2019
+ p = p.parentNode;
2020
+ }
2021
+ var sep = this.getOwnerTree().pathSeparator;
2022
+ return sep + b.join(sep);
2023
+ },
2024
+
2025
+ /**
2026
+ * Bubbles up the tree from this node, calling the specified function with each node. The scope (<i>this</i>) of
2027
+ * function call will be the scope provided or the current node. The arguments to the function
2028
+ * will be the args provided or the current node. If the function returns false at any point,
2029
+ * the bubble is stopped.
2030
+ * @param {Function} fn The function to call
2031
+ * @param {Object} scope (optional) The scope of the function (defaults to current node)
2032
+ * @param {Array} args (optional) The args to call the function with (default to passing the current node)
2033
+ */
2034
+ bubble : function(fn, scope, args){
2035
+ var p = this;
2036
+ while(p){
2037
+ if(fn.apply(scope || p, args || [p]) === false){
2038
+ break;
2039
+ }
2040
+ p = p.parentNode;
2041
+ }
2042
+ },
2043
+
2044
+ /**
2045
+ * Cascades down the tree from this node, calling the specified function with each node. The scope (<i>this</i>) of
2046
+ * function call will be the scope provided or the current node. The arguments to the function
2047
+ * will be the args provided or the current node. If the function returns false at any point,
2048
+ * the cascade is stopped on that branch.
2049
+ * @param {Function} fn The function to call
2050
+ * @param {Object} scope (optional) The scope of the function (defaults to current node)
2051
+ * @param {Array} args (optional) The args to call the function with (default to passing the current node)
2052
+ */
2053
+ cascade : function(fn, scope, args){
2054
+ if(fn.apply(scope || this, args || [this]) !== false){
2055
+ var cs = this.childNodes;
2056
+ for(var i = 0, len = cs.length; i < len; i++) {
2057
+ cs[i].cascade(fn, scope, args);
2058
+ }
2059
+ }
2060
+ },
2061
+
2062
+ /**
2063
+ * Interates the child nodes of this node, calling the specified function with each node. The scope (<i>this</i>) of
2064
+ * function call will be the scope provided or the current node. The arguments to the function
2065
+ * will be the args provided or the current node. If the function returns false at any point,
2066
+ * the iteration stops.
2067
+ * @param {Function} fn The function to call
2068
+ * @param {Object} scope (optional) The scope of the function (defaults to current node)
2069
+ * @param {Array} args (optional) The args to call the function with (default to passing the current node)
2070
+ */
2071
+ eachChild : function(fn, scope, args){
2072
+ var cs = this.childNodes;
2073
+ for(var i = 0, len = cs.length; i < len; i++) {
2074
+ if(fn.apply(scope || this, args || [cs[i]]) === false){
2075
+ break;
2076
+ }
2077
+ }
2078
+ },
2079
+
2080
+ /**
2081
+ * Finds the first child that has the attribute with the specified value.
2082
+ * @param {String} attribute The attribute name
2083
+ * @param {Mixed} value The value to search for
2084
+ * @return {Node} The found child or null if none was found
2085
+ */
2086
+ findChild : function(attribute, value){
2087
+ var cs = this.childNodes;
2088
+ for(var i = 0, len = cs.length; i < len; i++) {
2089
+ if(cs[i].attributes[attribute] == value){
2090
+ return cs[i];
2091
+ }
2092
+ }
2093
+ return null;
2094
+ },
2095
+
2096
+ /**
2097
+ * Finds the first child by a custom function. The child matches if the function passed
2098
+ * returns true.
2099
+ * @param {Function} fn
2100
+ * @param {Object} scope (optional)
2101
+ * @return {Node} The found child or null if none was found
2102
+ */
2103
+ findChildBy : function(fn, scope){
2104
+ var cs = this.childNodes;
2105
+ for(var i = 0, len = cs.length; i < len; i++) {
2106
+ if(fn.call(scope||cs[i], cs[i]) === true){
2107
+ return cs[i];
2108
+ }
2109
+ }
2110
+ return null;
2111
+ },
2112
+
2113
+ /**
2114
+ * Sorts this nodes children using the supplied sort function
2115
+ * @param {Function} fn
2116
+ * @param {Object} scope (optional)
2117
+ */
2118
+ sort : function(fn, scope){
2119
+ var cs = this.childNodes;
2120
+ var len = cs.length;
2121
+ if(len > 0){
2122
+ var sortFn = scope ? function(){fn.apply(scope, arguments);} : fn;
2123
+ cs.sort(sortFn);
2124
+ for(var i = 0; i < len; i++){
2125
+ var n = cs[i];
2126
+ n.previousSibling = cs[i-1];
2127
+ n.nextSibling = cs[i+1];
2128
+ if(i === 0){
2129
+ this.setFirstChild(n);
2130
+ }
2131
+ if(i == len-1){
2132
+ this.setLastChild(n);
2133
+ }
2134
+ }
2135
+ }
2136
+ },
2137
+
2138
+ /**
2139
+ * Returns true if this node is an ancestor (at any point) of the passed node.
2140
+ * @param {Node} node
2141
+ * @return {Boolean}
2142
+ */
2143
+ contains : function(node){
2144
+ return node.isAncestor(this);
2145
+ },
2146
+
2147
+ /**
2148
+ * Returns true if the passed node is an ancestor (at any point) of this node.
2149
+ * @param {Node} node
2150
+ * @return {Boolean}
2151
+ */
2152
+ isAncestor : function(node){
2153
+ var p = this.parentNode;
2154
+ while(p){
2155
+ if(p == node){
2156
+ return true;
2157
+ }
2158
+ p = p.parentNode;
2159
+ }
2160
+ return false;
2161
+ },
2162
+
2163
+ toString : function(){
2164
+ return "[Node"+(this.id?" "+this.id:"")+"]";
2165
+ }
2166
+ });/**
2167
+ * @class Ext.tree.TreeNode
2168
+ * @extends Ext.data.Node
2169
+ * @cfg {String} text The text for this node
2170
+ * @cfg {Boolean} expanded true to start the node expanded
2171
+ * @cfg {Boolean} allowDrag False to make this node undraggable if {@link #draggable} = true (defaults to true)
2172
+ * @cfg {Boolean} allowDrop False if this node cannot have child nodes dropped on it (defaults to true)
2173
+ * @cfg {Boolean} disabled true to start the node disabled
2174
+ * @cfg {String} icon The path to an icon for the node. The preferred way to do this
2175
+ * is to use the cls or iconCls attributes and add the icon via a CSS background image.
2176
+ * @cfg {String} cls A css class to be added to the node
2177
+ * @cfg {String} iconCls A css class to be added to the nodes icon element for applying css background images
2178
+ * @cfg {String} href URL of the link used for the node (defaults to #)
2179
+ * @cfg {String} hrefTarget target frame for the link
2180
+ * @cfg {Boolean} hidden True to render hidden. (Defaults to false).
2181
+ * @cfg {String} qtip An Ext QuickTip for the node
2182
+ * @cfg {Boolean} expandable If set to true, the node will always show a plus/minus icon, even when empty
2183
+ * @cfg {String} qtipCfg An Ext QuickTip config for the node (used instead of qtip)
2184
+ * @cfg {Boolean} singleClickExpand True for single click expand on this node
2185
+ * @cfg {Function} uiProvider A UI <b>class</b> to use for this node (defaults to Ext.tree.TreeNodeUI)
2186
+ * @cfg {Boolean} checked True to render a checked checkbox for this node, false to render an unchecked checkbox
2187
+ * (defaults to undefined with no checkbox rendered)
2188
+ * @cfg {Boolean} draggable True to make this node draggable (defaults to false)
2189
+ * @cfg {Boolean} isTarget False to not allow this node to act as a drop target (defaults to true)
2190
+ * @cfg {Boolean} allowChildren False to not allow this node to have child nodes (defaults to true)
2191
+ * @cfg {Boolean} editable False to not allow this node to be edited by an (@link Ext.tree.TreeEditor} (defaults to true)
2192
+ * @constructor
2193
+ * @param {Object/String} attributes The attributes/config for the node or just a string with the text for the node
2194
+ */
2195
+ Ext.tree.TreeNode = function(attributes){
2196
+ attributes = attributes || {};
2197
+ if(typeof attributes == "string"){
2198
+ attributes = {text: attributes};
2199
+ }
2200
+ this.childrenRendered = false;
2201
+ this.rendered = false;
2202
+ Ext.tree.TreeNode.superclass.constructor.call(this, attributes);
2203
+ this.expanded = attributes.expanded === true;
2204
+ this.isTarget = attributes.isTarget !== false;
2205
+ this.draggable = attributes.draggable !== false && attributes.allowDrag !== false;
2206
+ this.allowChildren = attributes.allowChildren !== false && attributes.allowDrop !== false;
2207
+
2208
+ /**
2209
+ * Read-only. The text for this node. To change it use setText().
2210
+ * @type String
2211
+ */
2212
+ this.text = attributes.text;
2213
+ /**
2214
+ * True if this node is disabled.
2215
+ * @type Boolean
2216
+ */
2217
+ this.disabled = attributes.disabled === true;
2218
+ /**
2219
+ * True if this node is hidden.
2220
+ * @type Boolean
2221
+ */
2222
+ this.hidden = attributes.hidden === true;
2223
+
2224
+ this.addEvents(
2225
+ /**
2226
+ * @event textchange
2227
+ * Fires when the text for this node is changed
2228
+ * @param {Node} this This node
2229
+ * @param {String} text The new text
2230
+ * @param {String} oldText The old text
2231
+ */
2232
+ "textchange",
2233
+ /**
2234
+ * @event beforeexpand
2235
+ * Fires before this node is expanded, return false to cancel.
2236
+ * @param {Node} this This node
2237
+ * @param {Boolean} deep
2238
+ * @param {Boolean} anim
2239
+ */
2240
+ "beforeexpand",
2241
+ /**
2242
+ * @event beforecollapse
2243
+ * Fires before this node is collapsed, return false to cancel.
2244
+ * @param {Node} this This node
2245
+ * @param {Boolean} deep
2246
+ * @param {Boolean} anim
2247
+ */
2248
+ "beforecollapse",
2249
+ /**
2250
+ * @event expand
2251
+ * Fires when this node is expanded
2252
+ * @param {Node} this This node
2253
+ */
2254
+ "expand",
2255
+ /**
2256
+ * @event disabledchange
2257
+ * Fires when the disabled status of this node changes
2258
+ * @param {Node} this This node
2259
+ * @param {Boolean} disabled
2260
+ */
2261
+ "disabledchange",
2262
+ /**
2263
+ * @event collapse
2264
+ * Fires when this node is collapsed
2265
+ * @param {Node} this This node
2266
+ */
2267
+ "collapse",
2268
+ /**
2269
+ * @event beforeclick
2270
+ * Fires before click processing. Return false to cancel the default action.
2271
+ * @param {Node} this This node
2272
+ * @param {Ext.EventObject} e The event object
2273
+ */
2274
+ "beforeclick",
2275
+ /**
2276
+ * @event click
2277
+ * Fires when this node is clicked
2278
+ * @param {Node} this This node
2279
+ * @param {Ext.EventObject} e The event object
2280
+ */
2281
+ "click",
2282
+ /**
2283
+ * @event checkchange
2284
+ * Fires when a node with a checkbox's checked property changes
2285
+ * @param {Node} this This node
2286
+ * @param {Boolean} checked
2287
+ */
2288
+ "checkchange",
2289
+ /**
2290
+ * @event dblclick
2291
+ * Fires when this node is double clicked
2292
+ * @param {Node} this This node
2293
+ * @param {Ext.EventObject} e The event object
2294
+ */
2295
+ "dblclick",
2296
+ /**
2297
+ * @event contextmenu
2298
+ * Fires when this node is right clicked
2299
+ * @param {Node} this This node
2300
+ * @param {Ext.EventObject} e The event object
2301
+ */
2302
+ "contextmenu",
2303
+ /**
2304
+ * @event beforechildrenrendered
2305
+ * Fires right before the child nodes for this node are rendered
2306
+ * @param {Node} this This node
2307
+ */
2308
+ "beforechildrenrendered"
2309
+ );
2310
+
2311
+ var uiClass = this.attributes.uiProvider || this.defaultUI || Ext.tree.TreeNodeUI;
2312
+
2313
+ /**
2314
+ * Read-only. The UI for this node
2315
+ * @type TreeNodeUI
2316
+ */
2317
+ this.ui = new uiClass(this);
2318
+ };
2319
+ Ext.extend(Ext.tree.TreeNode, Ext.data.Node, {
2320
+ preventHScroll: true,
2321
+ /**
2322
+ * Returns true if this node is expanded
2323
+ * @return {Boolean}
2324
+ */
2325
+ isExpanded : function(){
2326
+ return this.expanded;
2327
+ },
2328
+
2329
+ /**
2330
+ * Returns the UI object for this node.
2331
+ * @return {TreeNodeUI} The object which is providing the user interface for this tree
2332
+ * node. Unless otherwise specified in the {@link #uiProvider}, this will be an instance
2333
+ * of {@link Ext.tree.TreeNodeUI}
2334
+ */
2335
+ getUI : function(){
2336
+ return this.ui;
2337
+ },
2338
+
2339
+ getLoader : function(){
2340
+ var owner;
2341
+ return this.loader || ((owner = this.getOwnerTree()) && owner.loader ? owner.loader : new Ext.tree.TreeLoader());
2342
+ },
2343
+
2344
+ // private override
2345
+ setFirstChild : function(node){
2346
+ var of = this.firstChild;
2347
+ Ext.tree.TreeNode.superclass.setFirstChild.call(this, node);
2348
+ if(this.childrenRendered && of && node != of){
2349
+ of.renderIndent(true, true);
2350
+ }
2351
+ if(this.rendered){
2352
+ this.renderIndent(true, true);
2353
+ }
2354
+ },
2355
+
2356
+ // private override
2357
+ setLastChild : function(node){
2358
+ var ol = this.lastChild;
2359
+ Ext.tree.TreeNode.superclass.setLastChild.call(this, node);
2360
+ if(this.childrenRendered && ol && node != ol){
2361
+ ol.renderIndent(true, true);
2362
+ }
2363
+ if(this.rendered){
2364
+ this.renderIndent(true, true);
2365
+ }
2366
+ },
2367
+
2368
+ // these methods are overridden to provide lazy rendering support
2369
+ // private override
2370
+ appendChild : function(n){
2371
+ if(!n.render && !Ext.isArray(n)){
2372
+ n = this.getLoader().createNode(n);
2373
+ }
2374
+ var node = Ext.tree.TreeNode.superclass.appendChild.call(this, n);
2375
+ if(node && this.childrenRendered){
2376
+ node.render();
2377
+ }
2378
+ this.ui.updateExpandIcon();
2379
+ return node;
2380
+ },
2381
+
2382
+ // private override
2383
+ removeChild : function(node){
2384
+ this.ownerTree.getSelectionModel().unselect(node);
2385
+ Ext.tree.TreeNode.superclass.removeChild.apply(this, arguments);
2386
+ // if it's been rendered remove dom node
2387
+ if(this.childrenRendered){
2388
+ node.ui.remove();
2389
+ }
2390
+ if(this.childNodes.length < 1){
2391
+ this.collapse(false, false);
2392
+ }else{
2393
+ this.ui.updateExpandIcon();
2394
+ }
2395
+ if(!this.firstChild && !this.isHiddenRoot()) {
2396
+ this.childrenRendered = false;
2397
+ }
2398
+ return node;
2399
+ },
2400
+
2401
+ // private override
2402
+ insertBefore : function(node, refNode){
2403
+ if(!node.render){
2404
+ node = this.getLoader().createNode(node);
2405
+ }
2406
+ var newNode = Ext.tree.TreeNode.superclass.insertBefore.call(this, node, refNode);
2407
+ if(newNode && refNode && this.childrenRendered){
2408
+ node.render();
2409
+ }
2410
+ this.ui.updateExpandIcon();
2411
+ return newNode;
2412
+ },
2413
+
2414
+ /**
2415
+ * Sets the text for this node
2416
+ * @param {String} text
2417
+ */
2418
+ setText : function(text){
2419
+ var oldText = this.text;
2420
+ this.text = text;
2421
+ this.attributes.text = text;
2422
+ if(this.rendered){ // event without subscribing
2423
+ this.ui.onTextChange(this, text, oldText);
2424
+ }
2425
+ this.fireEvent("textchange", this, text, oldText);
2426
+ },
2427
+
2428
+ /**
2429
+ * Triggers selection of this node
2430
+ */
2431
+ select : function(){
2432
+ this.getOwnerTree().getSelectionModel().select(this);
2433
+ },
2434
+
2435
+ /**
2436
+ * Triggers deselection of this node
2437
+ */
2438
+ unselect : function(){
2439
+ this.getOwnerTree().getSelectionModel().unselect(this);
2440
+ },
2441
+
2442
+ /**
2443
+ * Returns true if this node is selected
2444
+ * @return {Boolean}
2445
+ */
2446
+ isSelected : function(){
2447
+ return this.getOwnerTree().getSelectionModel().isSelected(this);
2448
+ },
2449
+
2450
+ /**
2451
+ * Expand this node.
2452
+ * @param {Boolean} deep (optional) True to expand all children as well
2453
+ * @param {Boolean} anim (optional) false to cancel the default animation
2454
+ * @param {Function} callback (optional) A callback to be called when
2455
+ * expanding this node completes (does not wait for deep expand to complete).
2456
+ * Called with 1 parameter, this node.
2457
+ * @param {Object} scope (optional) The scope in which to execute the callback.
2458
+ */
2459
+ expand : function(deep, anim, callback, scope){
2460
+ if(!this.expanded){
2461
+ if(this.fireEvent("beforeexpand", this, deep, anim) === false){
2462
+ return;
2463
+ }
2464
+ if(!this.childrenRendered){
2465
+ this.renderChildren();
2466
+ }
2467
+ this.expanded = true;
2468
+ if(!this.isHiddenRoot() && (this.getOwnerTree().animate && anim !== false) || anim){
2469
+ this.ui.animExpand(function(){
2470
+ this.fireEvent("expand", this);
2471
+ this.runCallback(callback, scope || this, [this]);
2472
+ if(deep === true){
2473
+ this.expandChildNodes(true);
2474
+ }
2475
+ }.createDelegate(this));
2476
+ return;
2477
+ }else{
2478
+ this.ui.expand();
2479
+ this.fireEvent("expand", this);
2480
+ this.runCallback(callback, scope || this, [this]);
2481
+ }
2482
+ }else{
2483
+ this.runCallback(callback, scope || this, [this]);
2484
+ }
2485
+ if(deep === true){
2486
+ this.expandChildNodes(true);
2487
+ }
2488
+ },
2489
+
2490
+ runCallback: function(cb, scope, args){
2491
+ if(Ext.isFunction(cb)){
2492
+ cb.apply(scope, args);
2493
+ }
2494
+ },
2495
+
2496
+ isHiddenRoot : function(){
2497
+ return this.isRoot && !this.getOwnerTree().rootVisible;
2498
+ },
2499
+
2500
+ /**
2501
+ * Collapse this node.
2502
+ * @param {Boolean} deep (optional) True to collapse all children as well
2503
+ * @param {Boolean} anim (optional) false to cancel the default animation
2504
+ * @param {Function} callback (optional) A callback to be called when
2505
+ * expanding this node completes (does not wait for deep expand to complete).
2506
+ * Called with 1 parameter, this node.
2507
+ * @param {Object} scope (optional) The scope in which to execute the callback.
2508
+ */
2509
+ collapse : function(deep, anim, callback, scope){
2510
+ if(this.expanded && !this.isHiddenRoot()){
2511
+ if(this.fireEvent("beforecollapse", this, deep, anim) === false){
2512
+ return;
2513
+ }
2514
+ this.expanded = false;
2515
+ if((this.getOwnerTree().animate && anim !== false) || anim){
2516
+ this.ui.animCollapse(function(){
2517
+ this.fireEvent("collapse", this);
2518
+ this.runCallback(callback, scope || this, [this]);
2519
+ if(deep === true){
2520
+ this.collapseChildNodes(true);
2521
+ }
2522
+ }.createDelegate(this));
2523
+ return;
2524
+ }else{
2525
+ this.ui.collapse();
2526
+ this.fireEvent("collapse", this);
2527
+ this.runCallback(callback, scope || this, [this]);
2528
+ }
2529
+ }else if(!this.expanded){
2530
+ this.runCallback(callback, scope || this, [this]);
2531
+ }
2532
+ if(deep === true){
2533
+ var cs = this.childNodes;
2534
+ for(var i = 0, len = cs.length; i < len; i++) {
2535
+ cs[i].collapse(true, false);
2536
+ }
2537
+ }
2538
+ },
2539
+
2540
+ // private
2541
+ delayedExpand : function(delay){
2542
+ if(!this.expandProcId){
2543
+ this.expandProcId = this.expand.defer(delay, this);
2544
+ }
2545
+ },
2546
+
2547
+ // private
2548
+ cancelExpand : function(){
2549
+ if(this.expandProcId){
2550
+ clearTimeout(this.expandProcId);
2551
+ }
2552
+ this.expandProcId = false;
2553
+ },
2554
+
2555
+ /**
2556
+ * Toggles expanded/collapsed state of the node
2557
+ */
2558
+ toggle : function(){
2559
+ if(this.expanded){
2560
+ this.collapse();
2561
+ }else{
2562
+ this.expand();
2563
+ }
2564
+ },
2565
+
2566
+ /**
2567
+ * Ensures all parent nodes are expanded, and if necessary, scrolls
2568
+ * the node into view.
2569
+ * @param {Function} callback (optional) A function to call when the node has been made visible.
2570
+ * @param {Object} scope (optional) The scope in which to execute the callback.
2571
+ */
2572
+ ensureVisible : function(callback, scope){
2573
+ var tree = this.getOwnerTree();
2574
+ tree.expandPath(this.parentNode ? this.parentNode.getPath() : this.getPath(), false, function(){
2575
+ var node = tree.getNodeById(this.id); // Somehow if we don't do this, we lose changes that happened to node in the meantime
2576
+ tree.getTreeEl().scrollChildIntoView(node.ui.anchor);
2577
+ this.runCallback(callback, scope || this, [this]);
2578
+ }.createDelegate(this));
2579
+ },
2580
+
2581
+ /**
2582
+ * Expand all child nodes
2583
+ * @param {Boolean} deep (optional) true if the child nodes should also expand their child nodes
2584
+ */
2585
+ expandChildNodes : function(deep){
2586
+ var cs = this.childNodes;
2587
+ for(var i = 0, len = cs.length; i < len; i++) {
2588
+ cs[i].expand(deep);
2589
+ }
2590
+ },
2591
+
2592
+ /**
2593
+ * Collapse all child nodes
2594
+ * @param {Boolean} deep (optional) true if the child nodes should also collapse their child nodes
2595
+ */
2596
+ collapseChildNodes : function(deep){
2597
+ var cs = this.childNodes;
2598
+ for(var i = 0, len = cs.length; i < len; i++) {
2599
+ cs[i].collapse(deep);
2600
+ }
2601
+ },
2602
+
2603
+ /**
2604
+ * Disables this node
2605
+ */
2606
+ disable : function(){
2607
+ this.disabled = true;
2608
+ this.unselect();
2609
+ if(this.rendered && this.ui.onDisableChange){ // event without subscribing
2610
+ this.ui.onDisableChange(this, true);
2611
+ }
2612
+ this.fireEvent("disabledchange", this, true);
2613
+ },
2614
+
2615
+ /**
2616
+ * Enables this node
2617
+ */
2618
+ enable : function(){
2619
+ this.disabled = false;
2620
+ if(this.rendered && this.ui.onDisableChange){ // event without subscribing
2621
+ this.ui.onDisableChange(this, false);
2622
+ }
2623
+ this.fireEvent("disabledchange", this, false);
2624
+ },
2625
+
2626
+ // private
2627
+ renderChildren : function(suppressEvent){
2628
+ if(suppressEvent !== false){
2629
+ this.fireEvent("beforechildrenrendered", this);
2630
+ }
2631
+ var cs = this.childNodes;
2632
+ for(var i = 0, len = cs.length; i < len; i++){
2633
+ cs[i].render(true);
2634
+ }
2635
+ this.childrenRendered = true;
2636
+ },
2637
+
2638
+ // private
2639
+ sort : function(fn, scope){
2640
+ Ext.tree.TreeNode.superclass.sort.apply(this, arguments);
2641
+ if(this.childrenRendered){
2642
+ var cs = this.childNodes;
2643
+ for(var i = 0, len = cs.length; i < len; i++){
2644
+ cs[i].render(true);
2645
+ }
2646
+ }
2647
+ },
2648
+
2649
+ // private
2650
+ render : function(bulkRender){
2651
+ this.ui.render(bulkRender);
2652
+ if(!this.rendered){
2653
+ // make sure it is registered
2654
+ this.getOwnerTree().registerNode(this);
2655
+ this.rendered = true;
2656
+ if(this.expanded){
2657
+ this.expanded = false;
2658
+ this.expand(false, false);
2659
+ }
2660
+ }
2661
+ },
2662
+
2663
+ // private
2664
+ renderIndent : function(deep, refresh){
2665
+ if(refresh){
2666
+ this.ui.childIndent = null;
2667
+ }
2668
+ this.ui.renderIndent();
2669
+ if(deep === true && this.childrenRendered){
2670
+ var cs = this.childNodes;
2671
+ for(var i = 0, len = cs.length; i < len; i++){
2672
+ cs[i].renderIndent(true, refresh);
2673
+ }
2674
+ }
2675
+ },
2676
+
2677
+ beginUpdate : function(){
2678
+ this.childrenRendered = false;
2679
+ },
2680
+
2681
+ endUpdate : function(){
2682
+ if(this.expanded && this.rendered){
2683
+ this.renderChildren();
2684
+ }
2685
+ },
2686
+
2687
+ destroy : function(){
2688
+ if(this.childNodes){
2689
+ for(var i = 0,l = this.childNodes.length; i < l; i++){
2690
+ this.childNodes[i].destroy();
2691
+ }
2692
+ this.childNodes = null;
2693
+ }
2694
+ if(this.ui.destroy){
2695
+ this.ui.destroy();
2696
+ }
2697
+ },
2698
+
2699
+ // private
2700
+ onIdChange: function(id){
2701
+ this.ui.onIdChange(id);
2702
+ }
2703
+ });
2704
+
2705
+ Ext.tree.TreePanel.nodeTypes.node = Ext.tree.TreeNode;/**
2706
+ * @class Ext.tree.AsyncTreeNode
2707
+ * @extends Ext.tree.TreeNode
2708
+ * @cfg {TreeLoader} loader A TreeLoader to be used by this node (defaults to the loader defined on the tree)
2709
+ * @constructor
2710
+ * @param {Object/String} attributes The attributes/config for the node or just a string with the text for the node
2711
+ */
2712
+ Ext.tree.AsyncTreeNode = function(config){
2713
+ this.loaded = config && config.loaded === true;
2714
+ this.loading = false;
2715
+ Ext.tree.AsyncTreeNode.superclass.constructor.apply(this, arguments);
2716
+ /**
2717
+ * @event beforeload
2718
+ * Fires before this node is loaded, return false to cancel
2719
+ * @param {Node} this This node
2720
+ */
2721
+ this.addEvents('beforeload', 'load');
2722
+ /**
2723
+ * @event load
2724
+ * Fires when this node is loaded
2725
+ * @param {Node} this This node
2726
+ */
2727
+ /**
2728
+ * The loader used by this node (defaults to using the tree's defined loader)
2729
+ * @type TreeLoader
2730
+ * @property loader
2731
+ */
2732
+ };
2733
+ Ext.extend(Ext.tree.AsyncTreeNode, Ext.tree.TreeNode, {
2734
+ expand : function(deep, anim, callback, scope){
2735
+ if(this.loading){ // if an async load is already running, waiting til it's done
2736
+ var timer;
2737
+ var f = function(){
2738
+ if(!this.loading){ // done loading
2739
+ clearInterval(timer);
2740
+ this.expand(deep, anim, callback, scope);
2741
+ }
2742
+ }.createDelegate(this);
2743
+ timer = setInterval(f, 200);
2744
+ return;
2745
+ }
2746
+ if(!this.loaded){
2747
+ if(this.fireEvent("beforeload", this) === false){
2748
+ return;
2749
+ }
2750
+ this.loading = true;
2751
+ this.ui.beforeLoad(this);
2752
+ var loader = this.loader || this.attributes.loader || this.getOwnerTree().getLoader();
2753
+ if(loader){
2754
+ loader.load(this, this.loadComplete.createDelegate(this, [deep, anim, callback, scope]), this);
2755
+ return;
2756
+ }
2757
+ }
2758
+ Ext.tree.AsyncTreeNode.superclass.expand.call(this, deep, anim, callback, scope);
2759
+ },
2760
+
2761
+ /**
2762
+ * Returns true if this node is currently loading
2763
+ * @return {Boolean}
2764
+ */
2765
+ isLoading : function(){
2766
+ return this.loading;
2767
+ },
2768
+
2769
+ loadComplete : function(deep, anim, callback, scope){
2770
+ this.loading = false;
2771
+ this.loaded = true;
2772
+ this.ui.afterLoad(this);
2773
+ this.fireEvent("load", this);
2774
+ this.expand(deep, anim, callback, scope);
2775
+ },
2776
+
2777
+ /**
2778
+ * Returns true if this node has been loaded
2779
+ * @return {Boolean}
2780
+ */
2781
+ isLoaded : function(){
2782
+ return this.loaded;
2783
+ },
2784
+
2785
+ hasChildNodes : function(){
2786
+ if(!this.isLeaf() && !this.loaded){
2787
+ return true;
2788
+ }else{
2789
+ return Ext.tree.AsyncTreeNode.superclass.hasChildNodes.call(this);
2790
+ }
2791
+ },
2792
+
2793
+ /**
2794
+ * Trigger a reload for this node
2795
+ * @param {Function} callback
2796
+ * @param {Object} scope (optional) The scope in which to execute the callback.
2797
+ */
2798
+ reload : function(callback, scope){
2799
+ this.collapse(false, false);
2800
+ while(this.firstChild){
2801
+ this.removeChild(this.firstChild).destroy();
2802
+ }
2803
+ this.childrenRendered = false;
2804
+ this.loaded = false;
2805
+ if(this.isHiddenRoot()){
2806
+ this.expanded = false;
2807
+ }
2808
+ this.expand(false, false, callback, scope);
2809
+ }
2810
+ });
2811
+
2812
+ Ext.tree.TreePanel.nodeTypes.async = Ext.tree.AsyncTreeNode;/**
2813
+ * @class Ext.tree.TreeNodeUI
2814
+ * This class provides the default UI implementation for Ext TreeNodes.
2815
+ * The TreeNode UI implementation is separate from the
2816
+ * tree implementation, and allows customizing of the appearance of
2817
+ * tree nodes.<br>
2818
+ * <p>
2819
+ * If you are customizing the Tree's user interface, you
2820
+ * may need to extend this class, but you should never need to instantiate this class.<br>
2821
+ * <p>
2822
+ * This class provides access to the user interface components of an Ext TreeNode, through
2823
+ * {@link Ext.tree.TreeNode#getUI}
2824
+ */
2825
+ Ext.tree.TreeNodeUI = function(node){
2826
+ this.node = node;
2827
+ this.rendered = false;
2828
+ this.animating = false;
2829
+ this.wasLeaf = true;
2830
+ this.ecc = 'x-tree-ec-icon x-tree-elbow';
2831
+ this.emptyIcon = Ext.BLANK_IMAGE_URL;
2832
+ };
2833
+
2834
+ Ext.tree.TreeNodeUI.prototype = {
2835
+ // private
2836
+ removeChild : function(node){
2837
+ if(this.rendered){
2838
+ this.ctNode.removeChild(node.ui.getEl());
2839
+ }
2840
+ },
2841
+
2842
+ // private
2843
+ beforeLoad : function(){
2844
+ this.addClass("x-tree-node-loading");
2845
+ },
2846
+
2847
+ // private
2848
+ afterLoad : function(){
2849
+ this.removeClass("x-tree-node-loading");
2850
+ },
2851
+
2852
+ // private
2853
+ onTextChange : function(node, text, oldText){
2854
+ if(this.rendered){
2855
+ this.textNode.innerHTML = text;
2856
+ }
2857
+ },
2858
+
2859
+ // private
2860
+ onDisableChange : function(node, state){
2861
+ this.disabled = state;
2862
+ if (this.checkbox) {
2863
+ this.checkbox.disabled = state;
2864
+ }
2865
+ if(state){
2866
+ this.addClass("x-tree-node-disabled");
2867
+ }else{
2868
+ this.removeClass("x-tree-node-disabled");
2869
+ }
2870
+ },
2871
+
2872
+ // private
2873
+ onSelectedChange : function(state){
2874
+ if(state){
2875
+ this.focus();
2876
+ this.addClass("x-tree-selected");
2877
+ }else{
2878
+ //this.blur();
2879
+ this.removeClass("x-tree-selected");
2880
+ }
2881
+ },
2882
+
2883
+ // private
2884
+ onMove : function(tree, node, oldParent, newParent, index, refNode){
2885
+ this.childIndent = null;
2886
+ if(this.rendered){
2887
+ var targetNode = newParent.ui.getContainer();
2888
+ if(!targetNode){//target not rendered
2889
+ this.holder = document.createElement("div");
2890
+ this.holder.appendChild(this.wrap);
2891
+ return;
2892
+ }
2893
+ var insertBefore = refNode ? refNode.ui.getEl() : null;
2894
+ if(insertBefore){
2895
+ targetNode.insertBefore(this.wrap, insertBefore);
2896
+ }else{
2897
+ targetNode.appendChild(this.wrap);
2898
+ }
2899
+ this.node.renderIndent(true, oldParent != newParent);
2900
+ }
2901
+ },
2902
+
2903
+ /**
2904
+ * Adds one or more CSS classes to the node's UI element.
2905
+ * Duplicate classes are automatically filtered out.
2906
+ * @param {String/Array} className The CSS class to add, or an array of classes
2907
+ */
2908
+ addClass : function(cls){
2909
+ if(this.elNode){
2910
+ Ext.fly(this.elNode).addClass(cls);
2911
+ }
2912
+ },
2913
+
2914
+ /**
2915
+ * Removes one or more CSS classes from the node's UI element.
2916
+ * @param {String/Array} className The CSS class to remove, or an array of classes
2917
+ */
2918
+ removeClass : function(cls){
2919
+ if(this.elNode){
2920
+ Ext.fly(this.elNode).removeClass(cls);
2921
+ }
2922
+ },
2923
+
2924
+ // private
2925
+ remove : function(){
2926
+ if(this.rendered){
2927
+ this.holder = document.createElement("div");
2928
+ this.holder.appendChild(this.wrap);
2929
+ }
2930
+ },
2931
+
2932
+ // private
2933
+ fireEvent : function(){
2934
+ return this.node.fireEvent.apply(this.node, arguments);
2935
+ },
2936
+
2937
+ // private
2938
+ initEvents : function(){
2939
+ this.node.on("move", this.onMove, this);
2940
+
2941
+ if(this.node.disabled){
2942
+ this.addClass("x-tree-node-disabled");
2943
+ if (this.checkbox) {
2944
+ this.checkbox.disabled = true;
2945
+ }
2946
+ }
2947
+ if(this.node.hidden){
2948
+ this.hide();
2949
+ }
2950
+ var ot = this.node.getOwnerTree();
2951
+ var dd = ot.enableDD || ot.enableDrag || ot.enableDrop;
2952
+ if(dd && (!this.node.isRoot || ot.rootVisible)){
2953
+ Ext.dd.Registry.register(this.elNode, {
2954
+ node: this.node,
2955
+ handles: this.getDDHandles(),
2956
+ isHandle: false
2957
+ });
2958
+ }
2959
+ },
2960
+
2961
+ // private
2962
+ getDDHandles : function(){
2963
+ return [this.iconNode, this.textNode, this.elNode];
2964
+ },
2965
+
2966
+ /**
2967
+ * Hides this node.
2968
+ */
2969
+ hide : function(){
2970
+ this.node.hidden = true;
2971
+ if(this.wrap){
2972
+ this.wrap.style.display = "none";
2973
+ }
2974
+ },
2975
+
2976
+ /**
2977
+ * Shows this node.
2978
+ */
2979
+ show : function(){
2980
+ this.node.hidden = false;
2981
+ if(this.wrap){
2982
+ this.wrap.style.display = "";
2983
+ }
2984
+ },
2985
+
2986
+ // private
2987
+ onContextMenu : function(e){
2988
+ if (this.node.hasListener("contextmenu") || this.node.getOwnerTree().hasListener("contextmenu")) {
2989
+ e.preventDefault();
2990
+ this.focus();
2991
+ this.fireEvent("contextmenu", this.node, e);
2992
+ }
2993
+ },
2994
+
2995
+ // private
2996
+ onClick : function(e){
2997
+ if(this.dropping){
2998
+ e.stopEvent();
2999
+ return;
3000
+ }
3001
+ if(this.fireEvent("beforeclick", this.node, e) !== false){
3002
+ var a = e.getTarget('a');
3003
+ if(!this.disabled && this.node.attributes.href && a){
3004
+ this.fireEvent("click", this.node, e);
3005
+ return;
3006
+ }else if(a && e.ctrlKey){
3007
+ e.stopEvent();
3008
+ }
3009
+ e.preventDefault();
3010
+ if(this.disabled){
3011
+ return;
3012
+ }
3013
+
3014
+ if(this.node.attributes.singleClickExpand && !this.animating && this.node.isExpandable()){
3015
+ this.node.toggle();
3016
+ }
3017
+
3018
+ this.fireEvent("click", this.node, e);
3019
+ }else{
3020
+ e.stopEvent();
3021
+ }
3022
+ },
3023
+
3024
+ // private
3025
+ onDblClick : function(e){
3026
+ e.preventDefault();
3027
+ if(this.disabled){
3028
+ return;
3029
+ }
3030
+ if(this.checkbox){
3031
+ this.toggleCheck();
3032
+ }
3033
+ if(!this.animating && this.node.isExpandable()){
3034
+ this.node.toggle();
3035
+ }
3036
+ this.fireEvent("dblclick", this.node, e);
3037
+ },
3038
+
3039
+ onOver : function(e){
3040
+ this.addClass('x-tree-node-over');
3041
+ },
3042
+
3043
+ onOut : function(e){
3044
+ this.removeClass('x-tree-node-over');
3045
+ },
3046
+
3047
+ // private
3048
+ onCheckChange : function(){
3049
+ var checked = this.checkbox.checked;
3050
+ // fix for IE6
3051
+ this.checkbox.defaultChecked = checked;
3052
+ this.node.attributes.checked = checked;
3053
+ this.fireEvent('checkchange', this.node, checked);
3054
+ },
3055
+
3056
+ // private
3057
+ ecClick : function(e){
3058
+ if(!this.animating && this.node.isExpandable()){
3059
+ this.node.toggle();
3060
+ }
3061
+ },
3062
+
3063
+ // private
3064
+ startDrop : function(){
3065
+ this.dropping = true;
3066
+ },
3067
+
3068
+ // delayed drop so the click event doesn't get fired on a drop
3069
+ endDrop : function(){
3070
+ setTimeout(function(){
3071
+ this.dropping = false;
3072
+ }.createDelegate(this), 50);
3073
+ },
3074
+
3075
+ // private
3076
+ expand : function(){
3077
+ this.updateExpandIcon();
3078
+ this.ctNode.style.display = "";
3079
+ },
3080
+
3081
+ // private
3082
+ focus : function(){
3083
+ if(!this.node.preventHScroll){
3084
+ try{this.anchor.focus();
3085
+ }catch(e){}
3086
+ }else{
3087
+ try{
3088
+ var noscroll = this.node.getOwnerTree().getTreeEl().dom;
3089
+ var l = noscroll.scrollLeft;
3090
+ this.anchor.focus();
3091
+ noscroll.scrollLeft = l;
3092
+ }catch(e){}
3093
+ }
3094
+ },
3095
+
3096
+ /**
3097
+ * Sets the checked status of the tree node to the passed value, or, if no value was passed,
3098
+ * toggles the checked status. If the node was rendered with no checkbox, this has no effect.
3099
+ * @param {Boolean} (optional) The new checked status.
3100
+ */
3101
+ toggleCheck : function(value){
3102
+ var cb = this.checkbox;
3103
+ if(cb){
3104
+ cb.checked = (value === undefined ? !cb.checked : value);
3105
+ this.onCheckChange();
3106
+ }
3107
+ },
3108
+
3109
+ // private
3110
+ blur : function(){
3111
+ try{
3112
+ this.anchor.blur();
3113
+ }catch(e){}
3114
+ },
3115
+
3116
+ // private
3117
+ animExpand : function(callback){
3118
+ var ct = Ext.get(this.ctNode);
3119
+ ct.stopFx();
3120
+ if(!this.node.isExpandable()){
3121
+ this.updateExpandIcon();
3122
+ this.ctNode.style.display = "";
3123
+ Ext.callback(callback);
3124
+ return;
3125
+ }
3126
+ this.animating = true;
3127
+ this.updateExpandIcon();
3128
+
3129
+ ct.slideIn('t', {
3130
+ callback : function(){
3131
+ this.animating = false;
3132
+ Ext.callback(callback);
3133
+ },
3134
+ scope: this,
3135
+ duration: this.node.ownerTree.duration || .25
3136
+ });
3137
+ },
3138
+
3139
+ // private
3140
+ highlight : function(){
3141
+ var tree = this.node.getOwnerTree();
3142
+ Ext.fly(this.wrap).highlight(
3143
+ tree.hlColor || "C3DAF9",
3144
+ {endColor: tree.hlBaseColor}
3145
+ );
3146
+ },
3147
+
3148
+ // private
3149
+ collapse : function(){
3150
+ this.updateExpandIcon();
3151
+ this.ctNode.style.display = "none";
3152
+ },
3153
+
3154
+ // private
3155
+ animCollapse : function(callback){
3156
+ var ct = Ext.get(this.ctNode);
3157
+ ct.enableDisplayMode('block');
3158
+ ct.stopFx();
3159
+
3160
+ this.animating = true;
3161
+ this.updateExpandIcon();
3162
+
3163
+ ct.slideOut('t', {
3164
+ callback : function(){
3165
+ this.animating = false;
3166
+ Ext.callback(callback);
3167
+ },
3168
+ scope: this,
3169
+ duration: this.node.ownerTree.duration || .25
3170
+ });
3171
+ },
3172
+
3173
+ // private
3174
+ getContainer : function(){
3175
+ return this.ctNode;
3176
+ },
3177
+
3178
+ // private
3179
+ getEl : function(){
3180
+ return this.wrap;
3181
+ },
3182
+
3183
+ // private
3184
+ appendDDGhost : function(ghostNode){
3185
+ ghostNode.appendChild(this.elNode.cloneNode(true));
3186
+ },
3187
+
3188
+ // private
3189
+ getDDRepairXY : function(){
3190
+ return Ext.lib.Dom.getXY(this.iconNode);
3191
+ },
3192
+
3193
+ // private
3194
+ onRender : function(){
3195
+ this.render();
3196
+ },
3197
+
3198
+ // private
3199
+ render : function(bulkRender){
3200
+ var n = this.node, a = n.attributes;
3201
+ var targetNode = n.parentNode ?
3202
+ n.parentNode.ui.getContainer() : n.ownerTree.innerCt.dom;
3203
+
3204
+ if(!this.rendered){
3205
+ this.rendered = true;
3206
+
3207
+ this.renderElements(n, a, targetNode, bulkRender);
3208
+
3209
+ if(a.qtip){
3210
+ if(this.textNode.setAttributeNS){
3211
+ this.textNode.setAttributeNS("ext", "qtip", a.qtip);
3212
+ if(a.qtipTitle){
3213
+ this.textNode.setAttributeNS("ext", "qtitle", a.qtipTitle);
3214
+ }
3215
+ }else{
3216
+ this.textNode.setAttribute("ext:qtip", a.qtip);
3217
+ if(a.qtipTitle){
3218
+ this.textNode.setAttribute("ext:qtitle", a.qtipTitle);
3219
+ }
3220
+ }
3221
+ }else if(a.qtipCfg){
3222
+ a.qtipCfg.target = Ext.id(this.textNode);
3223
+ Ext.QuickTips.register(a.qtipCfg);
3224
+ }
3225
+ this.initEvents();
3226
+ if(!this.node.expanded){
3227
+ this.updateExpandIcon(true);
3228
+ }
3229
+ }else{
3230
+ if(bulkRender === true) {
3231
+ targetNode.appendChild(this.wrap);
3232
+ }
3233
+ }
3234
+ },
3235
+
3236
+ // private
3237
+ renderElements : function(n, a, targetNode, bulkRender){
3238
+ // add some indent caching, this helps performance when rendering a large tree
3239
+ this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
3240
+
3241
+ var cb = typeof a.checked == 'boolean';
3242
+
3243
+ var href = a.href ? a.href : Ext.isGecko ? "" : "#";
3244
+ var buf = ['<li class="x-tree-node"><div ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf x-unselectable ', a.cls,'" unselectable="on">',
3245
+ '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
3246
+ '<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow" />',
3247
+ '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on" />',
3248
+ cb ? ('<input class="x-tree-node-cb" type="checkbox" ' + (a.checked ? 'checked="checked" />' : '/>')) : '',
3249
+ '<a hidefocus="on" class="x-tree-node-anchor" href="',href,'" tabIndex="1" ',
3250
+ a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '><span unselectable="on">',n.text,"</span></a></div>",
3251
+ '<ul class="x-tree-node-ct" style="display:none;"></ul>',
3252
+ "</li>"].join('');
3253
+
3254
+ var nel;
3255
+ if(bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())){
3256
+ this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);
3257
+ }else{
3258
+ this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf);
3259
+ }
3260
+
3261
+ this.elNode = this.wrap.childNodes[0];
3262
+ this.ctNode = this.wrap.childNodes[1];
3263
+ var cs = this.elNode.childNodes;
3264
+ this.indentNode = cs[0];
3265
+ this.ecNode = cs[1];
3266
+ this.iconNode = cs[2];
3267
+ var index = 3;
3268
+ if(cb){
3269
+ this.checkbox = cs[3];
3270
+ // fix for IE6
3271
+ this.checkbox.defaultChecked = this.checkbox.checked;
3272
+ index++;
3273
+ }
3274
+ this.anchor = cs[index];
3275
+ this.textNode = cs[index].firstChild;
3276
+ },
3277
+
3278
+ /**
3279
+ * Returns the &lt;a> element that provides focus for the node's UI.
3280
+ * @return {HtmlElement} The DOM anchor element.
3281
+ */
3282
+ getAnchor : function(){
3283
+ return this.anchor;
3284
+ },
3285
+
3286
+ /**
3287
+ * Returns the text node.
3288
+ * @return {HtmlNode} The DOM text node.
3289
+ */
3290
+ getTextEl : function(){
3291
+ return this.textNode;
3292
+ },
3293
+
3294
+ /**
3295
+ * Returns the icon &lt;img> element.
3296
+ * @return {HtmlElement} The DOM image element.
3297
+ */
3298
+ getIconEl : function(){
3299
+ return this.iconNode;
3300
+ },
3301
+
3302
+ /**
3303
+ * Returns the checked status of the node. If the node was rendered with no
3304
+ * checkbox, it returns false.
3305
+ * @return {Boolean} The checked flag.
3306
+ */
3307
+ isChecked : function(){
3308
+ return this.checkbox ? this.checkbox.checked : false;
3309
+ },
3310
+
3311
+ // private
3312
+ updateExpandIcon : function(){
3313
+ if(this.rendered){
3314
+ var n = this.node, c1, c2;
3315
+ var cls = n.isLast() ? "x-tree-elbow-end" : "x-tree-elbow";
3316
+ var hasChild = n.hasChildNodes();
3317
+ if(hasChild || n.attributes.expandable){
3318
+ if(n.expanded){
3319
+ cls += "-minus";
3320
+ c1 = "x-tree-node-collapsed";
3321
+ c2 = "x-tree-node-expanded";
3322
+ }else{
3323
+ cls += "-plus";
3324
+ c1 = "x-tree-node-expanded";
3325
+ c2 = "x-tree-node-collapsed";
3326
+ }
3327
+ if(this.wasLeaf){
3328
+ this.removeClass("x-tree-node-leaf");
3329
+ this.wasLeaf = false;
3330
+ }
3331
+ if(this.c1 != c1 || this.c2 != c2){
3332
+ Ext.fly(this.elNode).replaceClass(c1, c2);
3333
+ this.c1 = c1; this.c2 = c2;
3334
+ }
3335
+ }else{
3336
+ if(!this.wasLeaf){
3337
+ Ext.fly(this.elNode).replaceClass("x-tree-node-expanded", "x-tree-node-leaf");
3338
+ delete this.c1;
3339
+ delete this.c2;
3340
+ this.wasLeaf = true;
3341
+ }
3342
+ }
3343
+ var ecc = "x-tree-ec-icon "+cls;
3344
+ if(this.ecc != ecc){
3345
+ this.ecNode.className = ecc;
3346
+ this.ecc = ecc;
3347
+ }
3348
+ }
3349
+ },
3350
+
3351
+ // private
3352
+ onIdChange: function(id){
3353
+ if(this.rendered){
3354
+ this.elNode.setAttribute('ext:tree-node-id', id);
3355
+ }
3356
+ },
3357
+
3358
+ // private
3359
+ getChildIndent : function(){
3360
+ if(!this.childIndent){
3361
+ var buf = [];
3362
+ var p = this.node;
3363
+ while(p){
3364
+ if(!p.isRoot || (p.isRoot && p.ownerTree.rootVisible)){
3365
+ if(!p.isLast()) {
3366
+ buf.unshift('<img src="'+this.emptyIcon+'" class="x-tree-elbow-line" />');
3367
+ } else {
3368
+ buf.unshift('<img src="'+this.emptyIcon+'" class="x-tree-icon" />');
3369
+ }
3370
+ }
3371
+ p = p.parentNode;
3372
+ }
3373
+ this.childIndent = buf.join("");
3374
+ }
3375
+ return this.childIndent;
3376
+ },
3377
+
3378
+ // private
3379
+ renderIndent : function(){
3380
+ if(this.rendered){
3381
+ var indent = "";
3382
+ var p = this.node.parentNode;
3383
+ if(p){
3384
+ indent = p.ui.getChildIndent();
3385
+ }
3386
+ if(this.indentMarkup != indent){ // don't rerender if not required
3387
+ this.indentNode.innerHTML = indent;
3388
+ this.indentMarkup = indent;
3389
+ }
3390
+ this.updateExpandIcon();
3391
+ }
3392
+ },
3393
+
3394
+ destroy : function(){
3395
+ if(this.elNode){
3396
+ Ext.dd.Registry.unregister(this.elNode.id);
3397
+ }
3398
+ delete this.elNode;
3399
+ delete this.ctNode;
3400
+ delete this.indentNode;
3401
+ delete this.ecNode;
3402
+ delete this.iconNode;
3403
+ delete this.checkbox;
3404
+ delete this.anchor;
3405
+ delete this.textNode;
3406
+
3407
+ if (this.holder){
3408
+ delete this.wrap;
3409
+ Ext.removeNode(this.holder);
3410
+ delete this.holder;
3411
+ }else{
3412
+ Ext.removeNode(this.wrap);
3413
+ delete this.wrap;
3414
+ }
3415
+ }
3416
+ };
3417
+
3418
+ /**
3419
+ * @class Ext.tree.RootTreeNodeUI
3420
+ * This class provides the default UI implementation for <b>root</b> Ext TreeNodes.
3421
+ * The RootTreeNode UI implementation allows customizing the appearance of the root tree node.<br>
3422
+ * <p>
3423
+ * If you are customizing the Tree's user interface, you
3424
+ * may need to extend this class, but you should never need to instantiate this class.<br>
3425
+ */
3426
+ Ext.tree.RootTreeNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
3427
+ // private
3428
+ render : function(){
3429
+ if(!this.rendered){
3430
+ var targetNode = this.node.ownerTree.innerCt.dom;
3431
+ this.node.expanded = true;
3432
+ targetNode.innerHTML = '<div class="x-tree-root-node"></div>';
3433
+ this.wrap = this.ctNode = targetNode.firstChild;
3434
+ }
3435
+ },
3436
+ collapse : Ext.emptyFn,
3437
+ expand : Ext.emptyFn
3438
+ });/**
3439
+ * @class Ext.tree.TreeLoader
3440
+ * @extends Ext.util.Observable
3441
+ * A TreeLoader provides for lazy loading of an {@link Ext.tree.TreeNode}'s child
3442
+ * nodes from a specified URL. The response must be a JavaScript Array definition
3443
+ * whose elements are node definition objects. e.g.:
3444
+ * <pre><code>
3445
+ [{
3446
+ id: 1,
3447
+ text: 'A leaf Node',
3448
+ leaf: true
3449
+ },{
3450
+ id: 2,
3451
+ text: 'A folder Node',
3452
+ children: [{
3453
+ id: 3,
3454
+ text: 'A child Node',
3455
+ leaf: true
3456
+ }]
3457
+ }]
3458
+ </code></pre>
3459
+ * <br><br>
3460
+ * A server request is sent, and child nodes are loaded only when a node is expanded.
3461
+ * The loading node's id is passed to the server under the parameter name "node" to
3462
+ * enable the server to produce the correct child nodes.
3463
+ * <br><br>
3464
+ * To pass extra parameters, an event handler may be attached to the "beforeload"
3465
+ * event, and the parameters specified in the TreeLoader's baseParams property:
3466
+ * <pre><code>
3467
+ myTreeLoader.on("beforeload", function(treeLoader, node) {
3468
+ this.baseParams.category = node.attributes.category;
3469
+ }, this);
3470
+ </code></pre>
3471
+ * This would pass an HTTP parameter called "category" to the server containing
3472
+ * the value of the Node's "category" attribute.
3473
+ * @constructor
3474
+ * Creates a new Treeloader.
3475
+ * @param {Object} config A config object containing config properties.
3476
+ */
3477
+ Ext.tree.TreeLoader = function(config){
3478
+ this.baseParams = {};
3479
+ Ext.apply(this, config);
3480
+
3481
+ this.addEvents(
3482
+ /**
3483
+ * @event beforeload
3484
+ * Fires before a network request is made to retrieve the Json text which specifies a node's children.
3485
+ * @param {Object} This TreeLoader object.
3486
+ * @param {Object} node The {@link Ext.tree.TreeNode} object being loaded.
3487
+ * @param {Object} callback The callback function specified in the {@link #load} call.
3488
+ */
3489
+ "beforeload",
3490
+ /**
3491
+ * @event load
3492
+ * Fires when the node has been successfuly loaded.
3493
+ * @param {Object} This TreeLoader object.
3494
+ * @param {Object} node The {@link Ext.tree.TreeNode} object being loaded.
3495
+ * @param {Object} response The response object containing the data from the server.
3496
+ */
3497
+ "load",
3498
+ /**
3499
+ * @event loadexception
3500
+ * Fires if the network request failed.
3501
+ * @param {Object} This TreeLoader object.
3502
+ * @param {Object} node The {@link Ext.tree.TreeNode} object being loaded.
3503
+ * @param {Object} response The response object containing the data from the server.
3504
+ */
3505
+ "loadexception"
3506
+ );
3507
+ Ext.tree.TreeLoader.superclass.constructor.call(this);
3508
+ if(typeof this.paramOrder == 'string'){
3509
+ this.paramOrder = this.paramOrder.split(/[\s,|]/);
3510
+ }
3511
+ };
3512
+
3513
+ Ext.extend(Ext.tree.TreeLoader, Ext.util.Observable, {
3514
+ /**
3515
+ * @cfg {String} dataUrl The URL from which to request a Json string which
3516
+ * specifies an array of node definition objects representing the child nodes
3517
+ * to be loaded.
3518
+ */
3519
+ /**
3520
+ * @cfg {String} requestMethod The HTTP request method for loading data (defaults to the value of {@link Ext.Ajax#method}).
3521
+ */
3522
+ /**
3523
+ * @cfg {String} url Equivalent to {@link #dataUrl}.
3524
+ */
3525
+ /**
3526
+ * @cfg {Boolean} preloadChildren If set to true, the loader recursively loads "children" attributes when doing the first load on nodes.
3527
+ */
3528
+ /**
3529
+ * @cfg {Object} baseParams (optional) An object containing properties which
3530
+ * specify HTTP parameters to be passed to each request for child nodes.
3531
+ */
3532
+ /**
3533
+ * @cfg {Object} baseAttrs (optional) An object containing attributes to be added to all nodes
3534
+ * created by this loader. If the attributes sent by the server have an attribute in this object,
3535
+ * they take priority.
3536
+ */
3537
+ /**
3538
+ * @cfg {Object} uiProviders (optional) An object containing properties which
3539
+ * specify custom {@link Ext.tree.TreeNodeUI} implementations. If the optional
3540
+ * <i>uiProvider</i> attribute of a returned child node is a string rather
3541
+ * than a reference to a TreeNodeUI implementation, then that string value
3542
+ * is used as a property name in the uiProviders object.
3543
+ */
3544
+ uiProviders : {},
3545
+
3546
+ /**
3547
+ * @cfg {Boolean} clearOnLoad (optional) Default to true. Remove previously existing
3548
+ * child nodes before loading.
3549
+ */
3550
+ clearOnLoad : true,
3551
+
3552
+ /**
3553
+ * @cfg {Array/String} paramOrder Defaults to <tt>undefined</tt>. Only used when using directFn.
3554
+ * A list of params to be executed
3555
+ * server side. Specify the params in the order in which they must be executed on the server-side
3556
+ * as either (1) an Array of String values, or (2) a String of params delimited by either whitespace,
3557
+ * comma, or pipe. For example,
3558
+ * any of the following would be acceptable:<pre><code>
3559
+ paramOrder: ['param1','param2','param3']
3560
+ paramOrder: 'param1 param2 param3'
3561
+ paramOrder: 'param1,param2,param3'
3562
+ paramOrder: 'param1|param2|param'
3563
+ </code></pre>
3564
+ */
3565
+ paramOrder: undefined,
3566
+
3567
+ /**
3568
+ * @cfg {Boolean} paramsAsHash Only used when using directFn.
3569
+ * Send parameters as a collection of named arguments (defaults to <tt>false</tt>). Providing a
3570
+ * <tt>{@link #paramOrder}</tt> nullifies this configuration.
3571
+ */
3572
+ paramsAsHash: false,
3573
+
3574
+ /**
3575
+ * @cfg {Function} directFn
3576
+ * Function to call when executing a request.
3577
+ */
3578
+ directFn : undefined,
3579
+
3580
+ /**
3581
+ * Load an {@link Ext.tree.TreeNode} from the URL specified in the constructor.
3582
+ * This is called automatically when a node is expanded, but may be used to reload
3583
+ * a node (or append new children if the {@link #clearOnLoad} option is false.)
3584
+ * @param {Ext.tree.TreeNode} node
3585
+ * @param {Function} callback
3586
+ * @param (Object) scope
3587
+ */
3588
+ load : function(node, callback, scope){
3589
+ if(this.clearOnLoad){
3590
+ while(node.firstChild){
3591
+ node.removeChild(node.firstChild);
3592
+ }
3593
+ }
3594
+ if(this.doPreload(node)){ // preloaded json children
3595
+ this.runCallback(callback, scope || node, []);
3596
+ }else if(this.directFn || this.dataUrl || this.url){
3597
+ this.requestData(node, callback, scope || node);
3598
+ }
3599
+ },
3600
+
3601
+ doPreload : function(node){
3602
+ if(node.attributes.children){
3603
+ if(node.childNodes.length < 1){ // preloaded?
3604
+ var cs = node.attributes.children;
3605
+ node.beginUpdate();
3606
+ for(var i = 0, len = cs.length; i < len; i++){
3607
+ var cn = node.appendChild(this.createNode(cs[i]));
3608
+ if(this.preloadChildren){
3609
+ this.doPreload(cn);
3610
+ }
3611
+ }
3612
+ node.endUpdate();
3613
+ }
3614
+ return true;
3615
+ }
3616
+ return false;
3617
+ },
3618
+
3619
+ getParams: function(node){
3620
+ var buf = [], bp = this.baseParams;
3621
+ if(this.directFn){
3622
+ buf.push(node.id);
3623
+ if(bp){
3624
+ if(this.paramOrder){
3625
+ for(var i = 0, len = this.paramOrder.length; i < len; i++){
3626
+ buf.push(bp[this.paramOrder[i]]);
3627
+ }
3628
+ }else if(this.paramsAsHash){
3629
+ buf.push(bp);
3630
+ }
3631
+ }
3632
+ return buf;
3633
+ }else{
3634
+ for(var key in bp){
3635
+ if(!Ext.isFunction(bp[key])){
3636
+ buf.push(encodeURIComponent(key), "=", encodeURIComponent(bp[key]), "&");
3637
+ }
3638
+ }
3639
+ buf.push("node=", encodeURIComponent(node.id));
3640
+ return buf.join("");
3641
+ }
3642
+ },
3643
+
3644
+ requestData : function(node, callback, scope){
3645
+ if(this.fireEvent("beforeload", this, node, callback) !== false){
3646
+ if(this.directFn){
3647
+ var args = this.getParams(node);
3648
+ args.push(this.processDirectResponse.createDelegate(this, [{callback: callback, node: node, scope: scope}], true));
3649
+ this.directFn.apply(window, args);
3650
+ }else{
3651
+ this.transId = Ext.Ajax.request({
3652
+ method:this.requestMethod,
3653
+ url: this.dataUrl||this.url,
3654
+ success: this.handleResponse,
3655
+ failure: this.handleFailure,
3656
+ scope: this,
3657
+ argument: {callback: callback, node: node, scope: scope},
3658
+ params: this.getParams(node)
3659
+ });
3660
+ }
3661
+ }else{
3662
+ // if the load is cancelled, make sure we notify
3663
+ // the node that we are done
3664
+ this.runCallback(callback, scope || node, []);
3665
+ }
3666
+ },
3667
+
3668
+ processDirectResponse: function(result, response, args){
3669
+ if(response.status){
3670
+ this.handleResponse({
3671
+ responseData: Ext.isArray(result) ? result : null,
3672
+ responseText: result,
3673
+ argument: args
3674
+ });
3675
+ }else{
3676
+ this.handleFailure({
3677
+ argument: args
3678
+ });
3679
+ }
3680
+ },
3681
+
3682
+ // private
3683
+ runCallback: function(cb, scope, args){
3684
+ if(Ext.isFunction(cb)){
3685
+ cb.apply(scope, args);
3686
+ }
3687
+ },
3688
+
3689
+ isLoading : function(){
3690
+ return !!this.transId;
3691
+ },
3692
+
3693
+ abort : function(){
3694
+ if(this.isLoading()){
3695
+ Ext.Ajax.abort(this.transId);
3696
+ }
3697
+ },
3698
+
3699
+ /**
3700
+ * <p>Override this function for custom TreeNode node implementation, or to
3701
+ * modify the attributes at creation time.</p>
3702
+ * Example:<pre><code>
3703
+ new Ext.tree.TreePanel({
3704
+ ...
3705
+ new Ext.tree.TreeLoader({
3706
+ url: 'dataUrl',
3707
+ createNode: function(attr) {
3708
+ // Allow consolidation consignments to have
3709
+ // consignments dropped into them.
3710
+ if (attr.isConsolidation) {
3711
+ attr.iconCls = 'x-consol',
3712
+ attr.allowDrop = true;
3713
+ }
3714
+ return Ext.tree.TreeLoader.prototype.call(this, attr);
3715
+ }
3716
+ }),
3717
+ ...
3718
+ });
3719
+ </code></pre>
3720
+ * @param attr {Object} The attributes from which to create the new node.
3721
+ */
3722
+ createNode : function(attr){
3723
+ // apply baseAttrs, nice idea Corey!
3724
+ if(this.baseAttrs){
3725
+ Ext.applyIf(attr, this.baseAttrs);
3726
+ }
3727
+ if(this.applyLoader !== false){
3728
+ attr.loader = this;
3729
+ }
3730
+ if(typeof attr.uiProvider == 'string'){
3731
+ attr.uiProvider = this.uiProviders[attr.uiProvider] || eval(attr.uiProvider);
3732
+ }
3733
+ if(attr.nodeType){
3734
+ return new Ext.tree.TreePanel.nodeTypes[attr.nodeType](attr);
3735
+ }else{
3736
+ return attr.leaf ?
3737
+ new Ext.tree.TreeNode(attr) :
3738
+ new Ext.tree.AsyncTreeNode(attr);
3739
+ }
3740
+ },
3741
+
3742
+ processResponse : function(response, node, callback, scope){
3743
+ var json = response.responseText;
3744
+ try {
3745
+ var o = response.responseData || Ext.decode(json);
3746
+ node.beginUpdate();
3747
+ for(var i = 0, len = o.length; i < len; i++){
3748
+ var n = this.createNode(o[i]);
3749
+ if(n){
3750
+ node.appendChild(n);
3751
+ }
3752
+ }
3753
+ node.endUpdate();
3754
+ this.runCallback(callback, scope || node, [node]);
3755
+ }catch(e){
3756
+ this.handleFailure(response);
3757
+ }
3758
+ },
3759
+
3760
+ handleResponse : function(response){
3761
+ this.transId = false;
3762
+ var a = response.argument;
3763
+ this.processResponse(response, a.node, a.callback, a.scope);
3764
+ this.fireEvent("load", this, a.node, response);
3765
+ },
3766
+
3767
+ handleFailure : function(response){
3768
+ this.transId = false;
3769
+ var a = response.argument;
3770
+ this.fireEvent("loadexception", this, a.node, response);
3771
+ this.runCallback(a.callback, a.scope || a.node, [a.node]);
3772
+ }
3773
+ });/**
3774
+ * @class Ext.tree.TreeFilter
3775
+ * Note this class is experimental and doesn't update the indent (lines) or expand collapse icons of the nodes
3776
+ * @param {TreePanel} tree
3777
+ * @param {Object} config (optional)
3778
+ */
3779
+ Ext.tree.TreeFilter = function(tree, config){
3780
+ this.tree = tree;
3781
+ this.filtered = {};
3782
+ Ext.apply(this, config);
3783
+ };
3784
+
3785
+ Ext.tree.TreeFilter.prototype = {
3786
+ clearBlank:false,
3787
+ reverse:false,
3788
+ autoClear:false,
3789
+ remove:false,
3790
+
3791
+ /**
3792
+ * Filter the data by a specific attribute.
3793
+ * @param {String/RegExp} value Either string that the attribute value
3794
+ * should start with or a RegExp to test against the attribute
3795
+ * @param {String} attr (optional) The attribute passed in your node's attributes collection. Defaults to "text".
3796
+ * @param {TreeNode} startNode (optional) The node to start the filter at.
3797
+ */
3798
+ filter : function(value, attr, startNode){
3799
+ attr = attr || "text";
3800
+ var f;
3801
+ if(typeof value == "string"){
3802
+ var vlen = value.length;
3803
+ // auto clear empty filter
3804
+ if(vlen == 0 && this.clearBlank){
3805
+ this.clear();
3806
+ return;
3807
+ }
3808
+ value = value.toLowerCase();
3809
+ f = function(n){
3810
+ return n.attributes[attr].substr(0, vlen).toLowerCase() == value;
3811
+ };
3812
+ }else if(value.exec){ // regex?
3813
+ f = function(n){
3814
+ return value.test(n.attributes[attr]);
3815
+ };
3816
+ }else{
3817
+ throw 'Illegal filter type, must be string or regex';
3818
+ }
3819
+ this.filterBy(f, null, startNode);
3820
+ },
3821
+
3822
+ /**
3823
+ * Filter by a function. The passed function will be called with each
3824
+ * node in the tree (or from the startNode). If the function returns true, the node is kept
3825
+ * otherwise it is filtered. If a node is filtered, its children are also filtered.
3826
+ * @param {Function} fn The filter function
3827
+ * @param {Object} scope (optional) The scope of the function (defaults to the current node)
3828
+ */
3829
+ filterBy : function(fn, scope, startNode){
3830
+ startNode = startNode || this.tree.root;
3831
+ if(this.autoClear){
3832
+ this.clear();
3833
+ }
3834
+ var af = this.filtered, rv = this.reverse;
3835
+ var f = function(n){
3836
+ if(n == startNode){
3837
+ return true;
3838
+ }
3839
+ if(af[n.id]){
3840
+ return false;
3841
+ }
3842
+ var m = fn.call(scope || n, n);
3843
+ if(!m || rv){
3844
+ af[n.id] = n;
3845
+ n.ui.hide();
3846
+ return false;
3847
+ }
3848
+ return true;
3849
+ };
3850
+ startNode.cascade(f);
3851
+ if(this.remove){
3852
+ for(var id in af){
3853
+ if(typeof id != "function"){
3854
+ var n = af[id];
3855
+ if(n && n.parentNode){
3856
+ n.parentNode.removeChild(n);
3857
+ }
3858
+ }
3859
+ }
3860
+ }
3861
+ },
3862
+
3863
+ /**
3864
+ * Clears the current filter. Note: with the "remove" option
3865
+ * set a filter cannot be cleared.
3866
+ */
3867
+ clear : function(){
3868
+ var t = this.tree;
3869
+ var af = this.filtered;
3870
+ for(var id in af){
3871
+ if(typeof id != "function"){
3872
+ var n = af[id];
3873
+ if(n){
3874
+ n.ui.show();
3875
+ }
3876
+ }
3877
+ }
3878
+ this.filtered = {};
3879
+ }
3880
+ };
3881
+ /**
3882
+ * @class Ext.tree.TreeSorter
3883
+ * Provides sorting of nodes in a {@link Ext.tree.TreePanel}. The TreeSorter automatically monitors events on the
3884
+ * associated TreePanel that might affect the tree's sort order (beforechildrenrendered, append, insert and textchange).
3885
+ * Example usage:<br />
3886
+ * <pre><code>
3887
+ new Ext.tree.TreeSorter(myTree, {
3888
+ folderSort: true,
3889
+ dir: "desc",
3890
+ sortType: function(node) {
3891
+ // sort by a custom, typed attribute:
3892
+ return parseInt(node.id, 10);
3893
+ }
3894
+ });
3895
+ </code></pre>
3896
+ * @constructor
3897
+ * @param {TreePanel} tree
3898
+ * @param {Object} config
3899
+ */
3900
+ Ext.tree.TreeSorter = function(tree, config){
3901
+ /**
3902
+ * @cfg {Boolean} folderSort True to sort leaf nodes under non-leaf nodes (defaults to false)
3903
+ */
3904
+ /**
3905
+ * @cfg {String} property The named attribute on the node to sort by (defaults to "text"). Note that this
3906
+ * property is only used if no {@link #sortType} function is specified, otherwise it is ignored.
3907
+ */
3908
+ /**
3909
+ * @cfg {String} dir The direction to sort ("asc" or "desc," case-insensitive, defaults to "asc")
3910
+ */
3911
+ /**
3912
+ * @cfg {String} leafAttr The attribute used to determine leaf nodes when {@link #folderSort} = true (defaults to "leaf")
3913
+ */
3914
+ /**
3915
+ * @cfg {Boolean} caseSensitive true for case-sensitive sort (defaults to false)
3916
+ */
3917
+ /**
3918
+ * @cfg {Function} sortType A custom "casting" function used to convert node values before sorting. The function
3919
+ * will be called with a single parameter (the {@link Ext.tree.TreeNode} being evaluated) and is expected to return
3920
+ * the node's sort value cast to the specific data type required for sorting. This could be used, for example, when
3921
+ * a node's text (or other attribute) should be sorted as a date or numeric value. See the class description for
3922
+ * example usage. Note that if a sortType is specified, any {@link #property} config will be ignored.
3923
+ */
3924
+
3925
+ Ext.apply(this, config);
3926
+ tree.on("beforechildrenrendered", this.doSort, this);
3927
+ tree.on("append", this.updateSort, this);
3928
+ tree.on("insert", this.updateSort, this);
3929
+ tree.on("textchange", this.updateSortParent, this);
3930
+
3931
+ var dsc = this.dir && this.dir.toLowerCase() == "desc";
3932
+ var p = this.property || "text";
3933
+ var sortType = this.sortType;
3934
+ var fs = this.folderSort;
3935
+ var cs = this.caseSensitive === true;
3936
+ var leafAttr = this.leafAttr || 'leaf';
3937
+
3938
+ this.sortFn = function(n1, n2){
3939
+ if(fs){
3940
+ if(n1.attributes[leafAttr] && !n2.attributes[leafAttr]){
3941
+ return 1;
3942
+ }
3943
+ if(!n1.attributes[leafAttr] && n2.attributes[leafAttr]){
3944
+ return -1;
3945
+ }
3946
+ }
3947
+ var v1 = sortType ? sortType(n1) : (cs ? n1.attributes[p] : n1.attributes[p].toUpperCase());
3948
+ var v2 = sortType ? sortType(n2) : (cs ? n2.attributes[p] : n2.attributes[p].toUpperCase());
3949
+ if(v1 < v2){
3950
+ return dsc ? +1 : -1;
3951
+ }else if(v1 > v2){
3952
+ return dsc ? -1 : +1;
3953
+ }else{
3954
+ return 0;
3955
+ }
3956
+ };
3957
+ };
3958
+
3959
+ Ext.tree.TreeSorter.prototype = {
3960
+ doSort : function(node){
3961
+ node.sort(this.sortFn);
3962
+ },
3963
+
3964
+ compareNodes : function(n1, n2){
3965
+ return (n1.text.toUpperCase() > n2.text.toUpperCase() ? 1 : -1);
3966
+ },
3967
+
3968
+ updateSort : function(tree, node){
3969
+ if(node.childrenRendered){
3970
+ this.doSort.defer(1, this, [node]);
3971
+ }
3972
+ },
3973
+
3974
+ updateSortParent : function(node){
3975
+ var p = node.parentNode;
3976
+ if(p && p.childrenRendered){
3977
+ this.doSort.defer(1, this, [p]);
3978
+ }
3979
+ }
3980
+ };/**
3981
+ * @class Ext.tree.TreeDropZone
3982
+ * @extends Ext.dd.DropZone
3983
+ * @constructor
3984
+ * @param {String/HTMLElement/Element} tree The {@link Ext.tree.TreePanel} for which to enable dropping
3985
+ * @param {Object} config
3986
+ */
3987
+ if(Ext.dd.DropZone){
3988
+
3989
+ Ext.tree.TreeDropZone = function(tree, config){
3990
+ /**
3991
+ * @cfg {Boolean} allowParentInsert
3992
+ * Allow inserting a dragged node between an expanded parent node and its first child that will become a
3993
+ * sibling of the parent when dropped (defaults to false)
3994
+ */
3995
+ this.allowParentInsert = config.allowParentInsert || false;
3996
+ /**
3997
+ * @cfg {String} allowContainerDrop
3998
+ * True if drops on the tree container (outside of a specific tree node) are allowed (defaults to false)
3999
+ */
4000
+ this.allowContainerDrop = config.allowContainerDrop || false;
4001
+ /**
4002
+ * @cfg {String} appendOnly
4003
+ * True if the tree should only allow append drops (use for trees which are sorted, defaults to false)
4004
+ */
4005
+ this.appendOnly = config.appendOnly || false;
4006
+
4007
+ Ext.tree.TreeDropZone.superclass.constructor.call(this, tree.getTreeEl(), config);
4008
+ /**
4009
+ * The TreePanel for this drop zone
4010
+ * @type Ext.tree.TreePanel
4011
+ * @property
4012
+ */
4013
+ this.tree = tree;
4014
+ /**
4015
+ * Arbitrary data that can be associated with this tree and will be included in the event object that gets
4016
+ * passed to any nodedragover event handler (defaults to {})
4017
+ * @type Ext.tree.TreePanel
4018
+ * @property
4019
+ */
4020
+ this.dragOverData = {};
4021
+ // private
4022
+ this.lastInsertClass = "x-tree-no-status";
4023
+ };
4024
+
4025
+ Ext.extend(Ext.tree.TreeDropZone, Ext.dd.DropZone, {
4026
+ /**
4027
+ * @cfg {String} ddGroup
4028
+ * A named drag drop group to which this object belongs. If a group is specified, then this object will only
4029
+ * interact with other drag drop objects in the same group (defaults to 'TreeDD').
4030
+ */
4031
+ ddGroup : "TreeDD",
4032
+
4033
+ /**
4034
+ * @cfg {String} expandDelay
4035
+ * The delay in milliseconds to wait before expanding a target tree node while dragging a droppable node
4036
+ * over the target (defaults to 1000)
4037
+ */
4038
+ expandDelay : 1000,
4039
+
4040
+ // private
4041
+ expandNode : function(node){
4042
+ if(node.hasChildNodes() && !node.isExpanded()){
4043
+ node.expand(false, null, this.triggerCacheRefresh.createDelegate(this));
4044
+ }
4045
+ },
4046
+
4047
+ // private
4048
+ queueExpand : function(node){
4049
+ this.expandProcId = this.expandNode.defer(this.expandDelay, this, [node]);
4050
+ },
4051
+
4052
+ // private
4053
+ cancelExpand : function(){
4054
+ if(this.expandProcId){
4055
+ clearTimeout(this.expandProcId);
4056
+ this.expandProcId = false;
4057
+ }
4058
+ },
4059
+
4060
+ // private
4061
+ isValidDropPoint : function(n, pt, dd, e, data){
4062
+ if(!n || !data){ return false; }
4063
+ var targetNode = n.node;
4064
+ var dropNode = data.node;
4065
+ // default drop rules
4066
+ if(!(targetNode && targetNode.isTarget && pt)){
4067
+ return false;
4068
+ }
4069
+ if(pt == "append" && targetNode.allowChildren === false){
4070
+ return false;
4071
+ }
4072
+ if((pt == "above" || pt == "below") && (targetNode.parentNode && targetNode.parentNode.allowChildren === false)){
4073
+ return false;
4074
+ }
4075
+ if(dropNode && (targetNode == dropNode || dropNode.contains(targetNode))){
4076
+ return false;
4077
+ }
4078
+ // reuse the object
4079
+ var overEvent = this.dragOverData;
4080
+ overEvent.tree = this.tree;
4081
+ overEvent.target = targetNode;
4082
+ overEvent.data = data;
4083
+ overEvent.point = pt;
4084
+ overEvent.source = dd;
4085
+ overEvent.rawEvent = e;
4086
+ overEvent.dropNode = dropNode;
4087
+ overEvent.cancel = false;
4088
+ var result = this.tree.fireEvent("nodedragover", overEvent);
4089
+ return overEvent.cancel === false && result !== false;
4090
+ },
4091
+
4092
+ // private
4093
+ getDropPoint : function(e, n, dd){
4094
+ var tn = n.node;
4095
+ if(tn.isRoot){
4096
+ return tn.allowChildren !== false ? "append" : false; // always append for root
4097
+ }
4098
+ var dragEl = n.ddel;
4099
+ var t = Ext.lib.Dom.getY(dragEl), b = t + dragEl.offsetHeight;
4100
+ var y = Ext.lib.Event.getPageY(e);
4101
+ var noAppend = tn.allowChildren === false || tn.isLeaf();
4102
+ if(this.appendOnly || tn.parentNode.allowChildren === false){
4103
+ return noAppend ? false : "append";
4104
+ }
4105
+ var noBelow = false;
4106
+ if(!this.allowParentInsert){
4107
+ noBelow = tn.hasChildNodes() && tn.isExpanded();
4108
+ }
4109
+ var q = (b - t) / (noAppend ? 2 : 3);
4110
+ if(y >= t && y < (t + q)){
4111
+ return "above";
4112
+ }else if(!noBelow && (noAppend || y >= b-q && y <= b)){
4113
+ return "below";
4114
+ }else{
4115
+ return "append";
4116
+ }
4117
+ },
4118
+
4119
+ // private
4120
+ onNodeEnter : function(n, dd, e, data){
4121
+ this.cancelExpand();
4122
+ },
4123
+
4124
+ onContainerOver : function(dd, e, data) {
4125
+ if (this.allowContainerDrop && this.isValidDropPoint({ ddel: this.tree.getRootNode().ui.elNode, node: this.tree.getRootNode() }, "append", dd, e, data)) {
4126
+ return this.dropAllowed;
4127
+ }
4128
+ return this.dropNotAllowed;
4129
+ },
4130
+
4131
+ // private
4132
+ onNodeOver : function(n, dd, e, data){
4133
+ var pt = this.getDropPoint(e, n, dd);
4134
+ var node = n.node;
4135
+
4136
+ // auto node expand check
4137
+ if(!this.expandProcId && pt == "append" && node.hasChildNodes() && !n.node.isExpanded()){
4138
+ this.queueExpand(node);
4139
+ }else if(pt != "append"){
4140
+ this.cancelExpand();
4141
+ }
4142
+
4143
+ // set the insert point style on the target node
4144
+ var returnCls = this.dropNotAllowed;
4145
+ if(this.isValidDropPoint(n, pt, dd, e, data)){
4146
+ if(pt){
4147
+ var el = n.ddel;
4148
+ var cls;
4149
+ if(pt == "above"){
4150
+ returnCls = n.node.isFirst() ? "x-tree-drop-ok-above" : "x-tree-drop-ok-between";
4151
+ cls = "x-tree-drag-insert-above";
4152
+ }else if(pt == "below"){
4153
+ returnCls = n.node.isLast() ? "x-tree-drop-ok-below" : "x-tree-drop-ok-between";
4154
+ cls = "x-tree-drag-insert-below";
4155
+ }else{
4156
+ returnCls = "x-tree-drop-ok-append";
4157
+ cls = "x-tree-drag-append";
4158
+ }
4159
+ if(this.lastInsertClass != cls){
4160
+ Ext.fly(el).replaceClass(this.lastInsertClass, cls);
4161
+ this.lastInsertClass = cls;
4162
+ }
4163
+ }
4164
+ }
4165
+ return returnCls;
4166
+ },
4167
+
4168
+ // private
4169
+ onNodeOut : function(n, dd, e, data){
4170
+ this.cancelExpand();
4171
+ this.removeDropIndicators(n);
4172
+ },
4173
+
4174
+ // private
4175
+ onNodeDrop : function(n, dd, e, data){
4176
+ var point = this.getDropPoint(e, n, dd);
4177
+ var targetNode = n.node;
4178
+ targetNode.ui.startDrop();
4179
+ if(!this.isValidDropPoint(n, point, dd, e, data)){
4180
+ targetNode.ui.endDrop();
4181
+ return false;
4182
+ }
4183
+ // first try to find the drop node
4184
+ var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, point, e) : null);
4185
+ return this.processDrop(targetNode, data, point, dd, e, dropNode);
4186
+ },
4187
+
4188
+ onContainerDrop : function(dd, e, data){
4189
+ if (this.allowContainerDrop && this.isValidDropPoint({ ddel: this.tree.getRootNode().ui.elNode, node: this.tree.getRootNode() }, "append", dd, e, data)) {
4190
+ var targetNode = this.tree.getRootNode();
4191
+ targetNode.ui.startDrop();
4192
+ var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, 'append', e) : null);
4193
+ return this.processDrop(targetNode, data, 'append', dd, e, dropNode);
4194
+ }
4195
+ return false;
4196
+ },
4197
+
4198
+ // private
4199
+ processDrop: function(target, data, point, dd, e, dropNode){
4200
+ var dropEvent = {
4201
+ tree : this.tree,
4202
+ target: target,
4203
+ data: data,
4204
+ point: point,
4205
+ source: dd,
4206
+ rawEvent: e,
4207
+ dropNode: dropNode,
4208
+ cancel: !dropNode,
4209
+ dropStatus: false
4210
+ };
4211
+ var retval = this.tree.fireEvent("beforenodedrop", dropEvent);
4212
+ if(retval === false || dropEvent.cancel === true || !dropEvent.dropNode){
4213
+ target.ui.endDrop();
4214
+ return dropEvent.dropStatus;
4215
+ }
4216
+
4217
+ target = dropEvent.target;
4218
+ if(point == 'append' && !target.isExpanded()){
4219
+ target.expand(false, null, function(){
4220
+ this.completeDrop(dropEvent);
4221
+ }.createDelegate(this));
4222
+ }else{
4223
+ this.completeDrop(dropEvent);
4224
+ }
4225
+ return true;
4226
+ },
4227
+
4228
+ // private
4229
+ completeDrop : function(de){
4230
+ var ns = de.dropNode, p = de.point, t = de.target;
4231
+ if(!Ext.isArray(ns)){
4232
+ ns = [ns];
4233
+ }
4234
+ var n;
4235
+ for(var i = 0, len = ns.length; i < len; i++){
4236
+ n = ns[i];
4237
+ if(p == "above"){
4238
+ t.parentNode.insertBefore(n, t);
4239
+ }else if(p == "below"){
4240
+ t.parentNode.insertBefore(n, t.nextSibling);
4241
+ }else{
4242
+ t.appendChild(n);
4243
+ }
4244
+ }
4245
+ n.ui.focus();
4246
+ if(Ext.enableFx && this.tree.hlDrop){
4247
+ n.ui.highlight();
4248
+ }
4249
+ t.ui.endDrop();
4250
+ this.tree.fireEvent("nodedrop", de);
4251
+ },
4252
+
4253
+ // private
4254
+ afterNodeMoved : function(dd, data, e, targetNode, dropNode){
4255
+ if(Ext.enableFx && this.tree.hlDrop){
4256
+ dropNode.ui.focus();
4257
+ dropNode.ui.highlight();
4258
+ }
4259
+ this.tree.fireEvent("nodedrop", this.tree, targetNode, data, dd, e);
4260
+ },
4261
+
4262
+ // private
4263
+ getTree : function(){
4264
+ return this.tree;
4265
+ },
4266
+
4267
+ // private
4268
+ removeDropIndicators : function(n){
4269
+ if(n && n.ddel){
4270
+ var el = n.ddel;
4271
+ Ext.fly(el).removeClass([
4272
+ "x-tree-drag-insert-above",
4273
+ "x-tree-drag-insert-below",
4274
+ "x-tree-drag-append"]);
4275
+ this.lastInsertClass = "_noclass";
4276
+ }
4277
+ },
4278
+
4279
+ // private
4280
+ beforeDragDrop : function(target, e, id){
4281
+ this.cancelExpand();
4282
+ return true;
4283
+ },
4284
+
4285
+ // private
4286
+ afterRepair : function(data){
4287
+ if(data && Ext.enableFx){
4288
+ data.node.ui.highlight();
4289
+ }
4290
+ this.hideProxy();
4291
+ }
4292
+ });
4293
+
4294
+ }/**
4295
+ * @class Ext.tree.TreeDragZone
4296
+ * @extends Ext.dd.DragZone
4297
+ * @constructor
4298
+ * @param {String/HTMLElement/Element} tree The {@link Ext.tree.TreePanel} for which to enable dragging
4299
+ * @param {Object} config
4300
+ */
4301
+ if(Ext.dd.DragZone){
4302
+ Ext.tree.TreeDragZone = function(tree, config){
4303
+ Ext.tree.TreeDragZone.superclass.constructor.call(this, tree.innerCt, config);
4304
+ /**
4305
+ * The TreePanel for this drag zone
4306
+ * @type Ext.tree.TreePanel
4307
+ * @property
4308
+ */
4309
+ this.tree = tree;
4310
+ };
4311
+
4312
+ Ext.extend(Ext.tree.TreeDragZone, Ext.dd.DragZone, {
4313
+ /**
4314
+ * @cfg {String} ddGroup
4315
+ * A named drag drop group to which this object belongs. If a group is specified, then this object will only
4316
+ * interact with other drag drop objects in the same group (defaults to 'TreeDD').
4317
+ */
4318
+ ddGroup : "TreeDD",
4319
+
4320
+ // private
4321
+ onBeforeDrag : function(data, e){
4322
+ var n = data.node;
4323
+ return n && n.draggable && !n.disabled;
4324
+ },
4325
+
4326
+ // private
4327
+ onInitDrag : function(e){
4328
+ var data = this.dragData;
4329
+ this.tree.getSelectionModel().select(data.node);
4330
+ this.tree.eventModel.disable();
4331
+ this.proxy.update("");
4332
+ data.node.ui.appendDDGhost(this.proxy.ghost.dom);
4333
+ this.tree.fireEvent("startdrag", this.tree, data.node, e);
4334
+ },
4335
+
4336
+ // private
4337
+ getRepairXY : function(e, data){
4338
+ return data.node.ui.getDDRepairXY();
4339
+ },
4340
+
4341
+ // private
4342
+ onEndDrag : function(data, e){
4343
+ this.tree.eventModel.enable.defer(100, this.tree.eventModel);
4344
+ this.tree.fireEvent("enddrag", this.tree, data.node, e);
4345
+ },
4346
+
4347
+ // private
4348
+ onValidDrop : function(dd, e, id){
4349
+ this.tree.fireEvent("dragdrop", this.tree, this.dragData.node, dd, e);
4350
+ this.hideProxy();
4351
+ },
4352
+
4353
+ // private
4354
+ beforeInvalidDrop : function(e, id){
4355
+ // this scrolls the original position back into view
4356
+ var sm = this.tree.getSelectionModel();
4357
+ sm.clearSelections();
4358
+ sm.select(this.dragData.node);
4359
+ },
4360
+
4361
+ // private
4362
+ afterRepair : function(){
4363
+ if (Ext.enableFx && this.tree.hlDrop) {
4364
+ Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
4365
+ }
4366
+ this.dragging = false;
4367
+ }
4368
+ });
4369
+ }/**
4370
+ * @class Ext.tree.TreeEditor
4371
+ * @extends Ext.Editor
4372
+ * Provides editor functionality for inline tree node editing. Any valid {@link Ext.form.Field} subclass can be used
4373
+ * as the editor field.
4374
+ * @constructor
4375
+ * @param {TreePanel} tree
4376
+ * @param {Object} fieldConfig (optional) Either a prebuilt {@link Ext.form.Field} instance or a Field config object
4377
+ * that will be applied to the default field instance (defaults to a {@link Ext.form.TextField}).
4378
+ * @param {Object} config (optional) A TreeEditor config object
4379
+ */
4380
+ Ext.tree.TreeEditor = function(tree, fc, config){
4381
+ fc = fc || {};
4382
+ var field = fc.events ? fc : new Ext.form.TextField(fc);
4383
+ Ext.tree.TreeEditor.superclass.constructor.call(this, field, config);
4384
+
4385
+ this.tree = tree;
4386
+
4387
+ if(!tree.rendered){
4388
+ tree.on('render', this.initEditor, this);
4389
+ }else{
4390
+ this.initEditor(tree);
4391
+ }
4392
+ };
4393
+
4394
+ Ext.extend(Ext.tree.TreeEditor, Ext.Editor, {
4395
+ /**
4396
+ * @cfg {String} alignment
4397
+ * The position to align to (see {@link Ext.Element#alignTo} for more details, defaults to "l-l").
4398
+ */
4399
+ alignment: "l-l",
4400
+ // inherit
4401
+ autoSize: false,
4402
+ /**
4403
+ * @cfg {Boolean} hideEl
4404
+ * True to hide the bound element while the editor is displayed (defaults to false)
4405
+ */
4406
+ hideEl : false,
4407
+ /**
4408
+ * @cfg {String} cls
4409
+ * CSS class to apply to the editor (defaults to "x-small-editor x-tree-editor")
4410
+ */
4411
+ cls: "x-small-editor x-tree-editor",
4412
+ /**
4413
+ * @cfg {Boolean} shim
4414
+ * True to shim the editor if selects/iframes could be displayed beneath it (defaults to false)
4415
+ */
4416
+ shim:false,
4417
+ // inherit
4418
+ shadow:"frame",
4419
+ /**
4420
+ * @cfg {Number} maxWidth
4421
+ * The maximum width in pixels of the editor field (defaults to 250). Note that if the maxWidth would exceed
4422
+ * the containing tree element's size, it will be automatically limited for you to the container width, taking
4423
+ * scroll and client offsets into account prior to each edit.
4424
+ */
4425
+ maxWidth: 250,
4426
+ /**
4427
+ * @cfg {Number} editDelay The number of milliseconds between clicks to register a double-click that will trigger
4428
+ * editing on the current node (defaults to 350). If two clicks occur on the same node within this time span,
4429
+ * the editor for the node will display, otherwise it will be processed as a regular click.
4430
+ */
4431
+ editDelay : 350,
4432
+
4433
+ initEditor : function(tree){
4434
+ tree.on('beforeclick', this.beforeNodeClick, this);
4435
+ tree.on('dblclick', this.onNodeDblClick, this);
4436
+ this.on('complete', this.updateNode, this);
4437
+ this.on('beforestartedit', this.fitToTree, this);
4438
+ this.on('startedit', this.bindScroll, this, {delay:10});
4439
+ this.on('specialkey', this.onSpecialKey, this);
4440
+ },
4441
+
4442
+ // private
4443
+ fitToTree : function(ed, el){
4444
+ var td = this.tree.getTreeEl().dom, nd = el.dom;
4445
+ if(td.scrollLeft > nd.offsetLeft){ // ensure the node left point is visible
4446
+ td.scrollLeft = nd.offsetLeft;
4447
+ }
4448
+ var w = Math.min(
4449
+ this.maxWidth,
4450
+ (td.clientWidth > 20 ? td.clientWidth : td.offsetWidth) - Math.max(0, nd.offsetLeft-td.scrollLeft) - /*cushion*/5);
4451
+ this.setSize(w, '');
4452
+ },
4453
+
4454
+ /**
4455
+ * Edit the text of the passed {@link Ext.tree.TreeNode TreeNode}.
4456
+ * @param node {Ext.tree.TreeNode} The TreeNode to edit. The TreeNode must be {@link Ext.tree.TreeNode#editable editable}.
4457
+ */
4458
+ triggerEdit : function(node, defer){
4459
+ this.completeEdit();
4460
+ if(node.attributes.editable !== false){
4461
+ /**
4462
+ * The {@link Ext.tree.TreeNode TreeNode} this editor is bound to. Read-only.
4463
+ * @type Ext.tree.TreeNode
4464
+ * @property editNode
4465
+ */
4466
+ this.editNode = node;
4467
+ if(this.tree.autoScroll){
4468
+ Ext.fly(node.ui.getEl()).scrollIntoView(this.tree.body);
4469
+ }
4470
+ var value = node.text || '';
4471
+ if (!Ext.isGecko && Ext.isEmpty(node.text)){
4472
+ node.setText('&#160;');
4473
+ }
4474
+ this.autoEditTimer = this.startEdit.defer(this.editDelay, this, [node.ui.textNode, value]);
4475
+ return false;
4476
+ }
4477
+ },
4478
+
4479
+ // private
4480
+ bindScroll : function(){
4481
+ this.tree.getTreeEl().on('scroll', this.cancelEdit, this);
4482
+ },
4483
+
4484
+ // private
4485
+ beforeNodeClick : function(node, e){
4486
+ clearTimeout(this.autoEditTimer);
4487
+ if(this.tree.getSelectionModel().isSelected(node)){
4488
+ e.stopEvent();
4489
+ return this.triggerEdit(node);
4490
+ }
4491
+ },
4492
+
4493
+ onNodeDblClick : function(node, e){
4494
+ clearTimeout(this.autoEditTimer);
4495
+ },
4496
+
4497
+ // private
4498
+ updateNode : function(ed, value){
4499
+ this.tree.getTreeEl().un('scroll', this.cancelEdit, this);
4500
+ this.editNode.setText(value);
4501
+ },
4502
+
4503
+ // private
4504
+ onHide : function(){
4505
+ Ext.tree.TreeEditor.superclass.onHide.call(this);
4506
+ if(this.editNode){
4507
+ this.editNode.ui.focus.defer(50, this.editNode.ui);
4508
+ }
4509
+ },
4510
+
4511
+ // private
4512
+ onSpecialKey : function(field, e){
4513
+ var k = e.getKey();
4514
+ if(k == e.ESC){
4515
+ e.stopEvent();
4516
+ this.cancelEdit();
4517
+ }else if(k == e.ENTER && !e.hasModifier()){
4518
+ e.stopEvent();
4519
+ this.completeEdit();
4520
+ }
4521
+ }
4522
+ });