lpmp 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ });