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.ComponentMgr=function(){var c=new Ext.util.MixedCollection();var b={};var a={};return{register:function(d){c.add(d)},unregister:function(d){c.remove(d)},get:function(d){return c.get(d)},onAvailable:function(f,e,d){c.on("add",function(g,h){if(h.id==f){e.call(d||h,h);c.un("add",e,d)}})},all:c,isRegistered:function(d){return b[d]!==undefined},registerType:function(e,d){b[e]=d;d.xtype=e},create:function(d,e){return d.render?d:new b[d.xtype||e](d)},registerPlugin:function(e,d){a[e]=d;d.ptype=e},createPlugin:function(d,e){return new a[d.ptype||e](d)}}}();Ext.reg=Ext.ComponentMgr.registerType;Ext.preg=Ext.ComponentMgr.registerPlugin;Ext.create=Ext.ComponentMgr.create;Ext.Component=function(b){b=b||{};if(b.initialConfig){if(b.isAction){this.baseAction=b}b=b.initialConfig}else{if(b.tagName||b.dom||Ext.isString(b)){b={applyTo:b,id:b.id||b}}}this.initialConfig=b;Ext.apply(this,b);this.addEvents("disable","enable","beforeshow","show","beforehide","hide","beforerender","render","afterrender","beforedestroy","destroy","beforestaterestore","staterestore","beforestatesave","statesave");this.getId();Ext.ComponentMgr.register(this);Ext.Component.superclass.constructor.call(this);if(this.baseAction){this.baseAction.addComponent(this)}this.initComponent();if(this.plugins){if(Ext.isArray(this.plugins)){for(var c=0,a=this.plugins.length;c<a;c++){this.plugins[c]=this.initPlugin(this.plugins[c])}}else{this.plugins=this.initPlugin(this.plugins)}}if(this.stateful!==false){this.initState(b)}if(this.applyTo){this.applyToMarkup(this.applyTo);delete this.applyTo}else{if(this.renderTo){this.render(this.renderTo);delete this.renderTo}}};Ext.Component.AUTO_ID=1000;Ext.extend(Ext.Component,Ext.util.Observable,{disabled:false,hidden:false,autoEl:"div",disabledClass:"x-item-disabled",allowDomMove:true,autoShow:false,hideMode:"display",hideParent:false,rendered:false,ctype:"Ext.Component",actionMode:"el",getActionEl:function(){return this[this.actionMode]},initPlugin:function(a){if(a.ptype&&!Ext.isFunction(a.init)){a=Ext.ComponentMgr.createPlugin(a)}else{if(Ext.isString(a)){a=Ext.ComponentMgr.createPlugin({ptype:a})}}a.init(this);return a},initComponent:Ext.emptyFn,render:function(b,a){if(!this.rendered&&this.fireEvent("beforerender",this)!==false){if(!b&&this.el){this.el=Ext.get(this.el);b=this.el.dom.parentNode;this.allowDomMove=false}this.container=Ext.get(b);if(this.ctCls){this.container.addClass(this.ctCls)}this.rendered=true;if(a!==undefined){if(Ext.isNumber(a)){a=this.container.dom.childNodes[a]}else{a=Ext.getDom(a)}}this.onRender(this.container,a||null);if(this.autoShow){this.el.removeClass(["x-hidden","x-hide-"+this.hideMode])}if(this.cls){this.el.addClass(this.cls);delete this.cls}if(this.style){this.el.applyStyles(this.style);delete this.style}if(this.overCls){this.el.addClassOnOver(this.overCls)}this.fireEvent("render",this);this.afterRender(this.container);if(this.hidden){this.doHide()}if(this.disabled){this.disable(true)}if(this.stateful!==false){this.initStateEvents()}this.initRef();this.fireEvent("afterrender",this)}return this},initRef:function(){if(this.ref){var d=this.ref.split("/");var c=d.length,b=0;var a=this;while(b<c){if(a.ownerCt){a=a.ownerCt}b++}a[d[--b]]=this}},initState:function(a){if(Ext.state.Manager){var c=this.getStateId();if(c){var b=Ext.state.Manager.get(c);if(b){if(this.fireEvent("beforestaterestore",this,b)!==false){this.applyState(b);this.fireEvent("staterestore",this,b)}}}}},getStateId:function(){return this.stateId||((this.id.indexOf("ext-comp-")==0||this.id.indexOf("ext-gen")==0)?null:this.id)},initStateEvents:function(){if(this.stateEvents){for(var a=0,b;b=this.stateEvents[a];a++){this.on(b,this.saveState,this,{delay:100})}}},applyState:function(b,a){if(b){Ext.apply(this,b)}},getState:function(){return null},saveState:function(){if(Ext.state.Manager&&this.stateful!==false){var b=this.getStateId();if(b){var a=this.getState();if(this.fireEvent("beforestatesave",this,a)!==false){Ext.state.Manager.set(b,a);this.fireEvent("statesave",this,a)}}}},applyToMarkup:function(a){this.allowDomMove=false;this.el=Ext.get(a);this.render(this.el.dom.parentNode)},addClass:function(a){if(this.el){this.el.addClass(a)}else{this.cls=this.cls?this.cls+" "+a:a}return this},removeClass:function(a){if(this.el){this.el.removeClass(a)}else{if(this.cls){this.cls=this.cls.split(" ").remove(a).join(" ")}}return this},onRender:function(b,a){if(!this.el&&this.autoEl){if(Ext.isString(this.autoEl)){this.el=document.createElement(this.autoEl)}else{var c=document.createElement("div");Ext.DomHelper.overwrite(c,this.autoEl);this.el=c.firstChild}if(!this.el.id){this.el.id=this.getId()}}if(this.el){this.el=Ext.get(this.el);if(this.allowDomMove!==false){b.dom.insertBefore(this.el.dom,a)}}},getAutoCreate:function(){var a=Ext.isObject(this.autoCreate)?this.autoCreate:Ext.apply({},this.defaultAutoCreate);if(this.id&&!a.id){a.id=this.id}return a},afterRender:Ext.emptyFn,destroy:function(){if(this.fireEvent("beforedestroy",this)!==false){this.beforeDestroy();if(this.rendered){this.el.removeAllListeners();this.el.remove();if(this.actionMode=="container"||this.removeMode=="container"){this.container.remove()}}this.onDestroy();Ext.ComponentMgr.unregister(this);this.fireEvent("destroy",this);this.purgeListeners()}},beforeDestroy:Ext.emptyFn,onDestroy:Ext.emptyFn,getEl:function(){return this.el},getId:function(){return this.id||(this.id="ext-comp-"+(++Ext.Component.AUTO_ID))},getItemId:function(){return this.itemId||this.getId()},focus:function(b,a){if(a){this.focus.defer(Ext.isNumber(a)?a:10,this,[b,false]);return}if(this.rendered){this.el.focus();if(b===true){this.el.dom.select()}}return this},blur:function(){if(this.rendered){this.el.blur()}return this},disable:function(a){if(this.rendered){this.onDisable()}this.disabled=true;if(a!==true){this.fireEvent("disable",this)}return this},onDisable:function(){this.getActionEl().addClass(this.disabledClass);this.el.dom.disabled=true},enable:function(){if(this.rendered){this.onEnable()}this.disabled=false;this.fireEvent("enable",this);return this},onEnable:function(){this.getActionEl().removeClass(this.disabledClass);this.el.dom.disabled=false},setDisabled:function(a){return this[a?"disable":"enable"]()},show:function(){if(this.fireEvent("beforeshow",this)!==false){this.hidden=false;if(this.autoRender){this.render(Ext.isBoolean(this.autoRender)?Ext.getBody():this.autoRender)}if(this.rendered){this.onShow()}this.fireEvent("show",this)}return this},onShow:function(){this.getVisibiltyEl().removeClass("x-hide-"+this.hideMode)},hide:function(){if(this.fireEvent("beforehide",this)!==false){this.doHide();this.fireEvent("hide",this)}return this},doHide:function(){this.hidden=true;if(this.rendered){this.onHide()}},onHide:function(){this.getVisibiltyEl().addClass("x-hide-"+this.hideMode)},getVisibiltyEl:function(){return this.hideParent?this.container:this.getActionEl()},setVisible:function(a){return this[a?"show":"hide"]()},isVisible:function(){return this.rendered&&this.getVisibiltyEl().isVisible()},cloneConfig:function(b){b=b||{};var c=b.id||Ext.id();var a=Ext.applyIf(b,this.initialConfig);a.id=c;return new this.constructor(a)},getXType:function(){return this.constructor.xtype},isXType:function(b,a){if(Ext.isFunction(b)){b=b.xtype}else{if(Ext.isObject(b)){b=b.constructor.xtype}}return !a?("/"+this.getXTypes()+"/").indexOf("/"+b+"/")!=-1:this.constructor.xtype==b},getXTypes:function(){var a=this.constructor;if(!a.xtypes){var d=[],b=this;while(b&&b.constructor.xtype){d.unshift(b.constructor.xtype);b=b.constructor.superclass}a.xtypeChain=d;a.xtypes=d.join("/")}return a.xtypes},findParentBy:function(a){for(var b=this.ownerCt;(b!=null)&&!a(b,this);b=b.ownerCt){}return b||null},findParentByType:function(a){return Ext.isFunction(a)?this.findParentBy(function(b){return b.constructor===a}):this.findParentBy(function(b){return b.constructor.xtype===a})},getDomPositionEl:function(){return this.getPositionEl?this.getPositionEl():this.getEl()},purgeListeners:function(){Ext.Component.superclass.purgeListeners.call(this);if(this.mons){this.on("beforedestroy",this.clearMons,this,{single:true})}},clearMons:function(){Ext.each(this.mons,function(a){a.item.un(a.ename,a.fn,a.scope)},this);this.mons=[]},mon:function(f,b,d,c,a){if(!this.mons){this.mons=[];this.on("beforedestroy",this.clearMons,this,{single:true})}if(Ext.isObject(b)){var i=/^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;var h=b;for(var g in h){if(i.test(g)){continue}if(Ext.isFunction(h[g])){this.mons.push({item:f,ename:g,fn:h[g],scope:h.scope});f.on(g,h[g],h.scope,h)}else{this.mons.push({item:f,ename:g,fn:h[g],scope:h.scope});f.on(g,h[g])}}return}this.mons.push({item:f,ename:b,fn:d,scope:c});f.on(b,d,c,a)},mun:function(g,c,f,e){var h,d;for(var b=0,a=this.mons.length;b<a;++b){d=this.mons[b];if(g===d.item&&c==d.ename&&f===d.fn&&e===d.scope){this.mons.splice(b,1);g.un(c,f,e);h=true;break}}return h},nextSibling:function(){if(this.ownerCt){var a=this.ownerCt.items.indexOf(this);if(a!=-1&&a+1<this.ownerCt.items.getCount()){return this.ownerCt.items.itemAt(a+1)}}return null},previousSibling:function(){if(this.ownerCt){var a=this.ownerCt.items.indexOf(this);if(a>0){return this.ownerCt.items.itemAt(a-1)}}return null},getBubbleTarget:function(){return this.ownerCt}});Ext.reg("component",Ext.Component);Ext.Action=function(a){this.initialConfig=a;this.itemId=a.itemId=(a.itemId||a.id||Ext.id());this.items=[]};Ext.Action.prototype={isAction:true,setText:function(a){this.initialConfig.text=a;this.callEach("setText",[a])},getText:function(){return this.initialConfig.text},setIconClass:function(a){this.initialConfig.iconCls=a;this.callEach("setIconClass",[a])},getIconClass:function(){return this.initialConfig.iconCls},setDisabled:function(a){this.initialConfig.disabled=a;this.callEach("setDisabled",[a])},enable:function(){this.setDisabled(false)},disable:function(){this.setDisabled(true)},isDisabled:function(){return this.initialConfig.disabled},setHidden:function(a){this.initialConfig.hidden=a;this.callEach("setVisible",[!a])},show:function(){this.setHidden(false)},hide:function(){this.setHidden(true)},isHidden:function(){return this.initialConfig.hidden},setHandler:function(b,a){this.initialConfig.handler=b;this.initialConfig.scope=a;this.callEach("setHandler",[b,a])},each:function(b,a){Ext.each(this.items,b,a)},callEach:function(e,b){var d=this.items;for(var c=0,a=d.length;c<a;c++){d[c][e].apply(d[c],b)}},addComponent:function(a){this.items.push(a);a.on("destroy",this.removeComponent,this)},removeComponent:function(a){this.items.remove(a)},execute:function(){this.initialConfig.handler.apply(this.initialConfig.scope||window,arguments)}};(function(){Ext.Layer=function(d,c){d=d||{};var e=Ext.DomHelper;var g=d.parentEl,f=g?Ext.getDom(g):document.body;if(c){this.dom=Ext.getDom(c)}if(!this.dom){var h=d.dh||{tag:"div",cls:"x-layer"};this.dom=e.append(f,h)}if(d.cls){this.addClass(d.cls)}this.constrain=d.constrain!==false;this.setVisibilityMode(Ext.Element.VISIBILITY);if(d.id){this.id=this.dom.id=d.id}else{this.id=Ext.id(this.dom)}this.zindex=d.zindex||this.getZIndex();this.position("absolute",this.zindex);if(d.shadow){this.shadowOffset=d.shadowOffset||4;this.shadow=new Ext.Shadow({offset:this.shadowOffset,mode:d.shadow})}else{this.shadowOffset=0}this.useShim=d.shim!==false&&Ext.useShims;this.useDisplay=d.useDisplay;this.hide()};var a=Ext.Element.prototype;var b=[];Ext.extend(Ext.Layer,Ext.Element,{getZIndex:function(){return this.zindex||parseInt((this.getShim()||this).getStyle("z-index"),10)||11000},getShim:function(){if(!this.useShim){return null}if(this.shim){return this.shim}var d=b.shift();if(!d){d=this.createShim();d.enableDisplayMode("block");d.dom.style.display="none";d.dom.style.visibility="visible"}var c=this.dom.parentNode;if(d.dom.parentNode!=c){c.insertBefore(d.dom,this.dom)}d.setStyle("z-index",this.getZIndex()-2);this.shim=d;return d},hideShim:function(){if(this.shim){this.shim.setDisplayed(false);b.push(this.shim);delete this.shim}},disableShadow:function(){if(this.shadow){this.shadowDisabled=true;this.shadow.hide();this.lastShadowOffset=this.shadowOffset;this.shadowOffset=0}},enableShadow:function(c){if(this.shadow){this.shadowDisabled=false;this.shadowOffset=this.lastShadowOffset;delete this.lastShadowOffset;if(c){this.sync(true)}}},sync:function(c){var j=this.shadow;if(!this.updating&&this.isVisible()&&(j||this.useShim)){var f=this.getShim();var i=this.getWidth(),e=this.getHeight();var d=this.getLeft(true),k=this.getTop(true);if(j&&!this.shadowDisabled){if(c&&!j.isVisible()){j.show(this)}else{j.realign(d,k,i,e)}if(f){if(c){f.show()}var g=j.adjusts,m=f.dom.style;m.left=(Math.min(d,d+g.l))+"px";m.top=(Math.min(k,k+g.t))+"px";m.width=(i+g.w)+"px";m.height=(e+g.h)+"px"}}else{if(f){if(c){f.show()}f.setSize(i,e);f.setLeftTop(d,k)}}}},destroy:function(){this.hideShim();if(this.shadow){this.shadow.hide()}this.removeAllListeners();Ext.removeNode(this.dom);Ext.Element.uncache(this.id)},remove:function(){this.destroy()},beginUpdate:function(){this.updating=true},endUpdate:function(){this.updating=false;this.sync(true)},hideUnders:function(c){if(this.shadow){this.shadow.hide()}this.hideShim()},constrainXY:function(){if(this.constrain){var i=Ext.lib.Dom.getViewWidth(),d=Ext.lib.Dom.getViewHeight();var n=Ext.getDoc().getScroll();var m=this.getXY();var j=m[0],g=m[1];var c=this.shadowOffset;var k=this.dom.offsetWidth+c,e=this.dom.offsetHeight+c;var f=false;if((j+k)>i+n.left){j=i-k-c;f=true}if((g+e)>d+n.top){g=d-e-c;f=true}if(j<n.left){j=n.left;f=true}if(g<n.top){g=n.top;f=true}if(f){if(this.avoidY){var l=this.avoidY;if(g<=l&&(g+e)>=l){g=l-e-5}}m=[j,g];this.storeXY(m);a.setXY.call(this,m);this.sync()}}return this},isVisible:function(){return this.visible},showAction:function(){this.visible=true;if(this.useDisplay===true){this.setDisplayed("")}else{if(this.lastXY){a.setXY.call(this,this.lastXY)}else{if(this.lastLT){a.setLeftTop.call(this,this.lastLT[0],this.lastLT[1])}}}},hideAction:function(){this.visible=false;if(this.useDisplay===true){this.setDisplayed(false)}else{this.setLeftTop(-10000,-10000)}},setVisible:function(h,g,j,k,i){if(h){this.showAction()}if(g&&h){var f=function(){this.sync(true);if(k){k()}}.createDelegate(this);a.setVisible.call(this,true,true,j,f,i)}else{if(!h){this.hideUnders(true)}var f=k;if(g){f=function(){this.hideAction();if(k){k()}}.createDelegate(this)}a.setVisible.call(this,h,g,j,f,i);if(h){this.sync(true)}else{if(!g){this.hideAction()}}}return this},storeXY:function(c){delete this.lastLT;this.lastXY=c},storeLeftTop:function(d,c){delete this.lastXY;this.lastLT=[d,c]},beforeFx:function(){this.beforeAction();return Ext.Layer.superclass.beforeFx.apply(this,arguments)},afterFx:function(){Ext.Layer.superclass.afterFx.apply(this,arguments);this.sync(this.isVisible())},beforeAction:function(){if(!this.updating&&this.shadow){this.shadow.hide()}},setLeft:function(c){this.storeLeftTop(c,this.getTop(true));a.setLeft.apply(this,arguments);this.sync();return this},setTop:function(c){this.storeLeftTop(this.getLeft(true),c);a.setTop.apply(this,arguments);this.sync();return this},setLeftTop:function(d,c){this.storeLeftTop(d,c);a.setLeftTop.apply(this,arguments);this.sync();return this},setXY:function(i,g,j,k,h){this.fixDisplay();this.beforeAction();this.storeXY(i);var f=this.createCB(k);a.setXY.call(this,i,g,j,f,h);if(!g){f()}return this},createCB:function(e){var d=this;return function(){d.constrainXY();d.sync(true);if(e){e()}}},setX:function(f,g,i,j,h){this.setXY([f,this.getY()],g,i,j,h);return this},setY:function(j,f,h,i,g){this.setXY([this.getX(),j],f,h,i,g);return this},setSize:function(i,j,g,l,m,k){this.beforeAction();var f=this.createCB(m);a.setSize.call(this,i,j,g,l,f,k);if(!g){f()}return this},setWidth:function(h,g,j,k,i){this.beforeAction();var f=this.createCB(k);a.setWidth.call(this,h,g,j,f,i);if(!g){f()}return this},setHeight:function(i,g,k,l,j){this.beforeAction();var f=this.createCB(l);a.setHeight.call(this,i,g,k,f,j);if(!g){f()}return this},setBounds:function(n,l,o,g,m,j,k,i){this.beforeAction();var f=this.createCB(k);if(!m){this.storeXY([n,l]);a.setXY.call(this,[n,l]);a.setSize.call(this,o,g,m,j,f,i);f()}else{a.setBounds.call(this,n,l,o,g,m,j,f,i)}return this},setZIndex:function(c){this.zindex=c;this.setStyle("z-index",c+2);if(this.shadow){this.shadow.setZIndex(c+1)}if(this.shim){this.shim.setStyle("z-index",c)}return this}})})();Ext.Shadow=function(d){Ext.apply(this,d);if(typeof this.mode!="string"){this.mode=this.defaultMode}var e=this.offset,c={h:0};var b=Math.floor(this.offset/2);switch(this.mode.toLowerCase()){case"drop":c.w=0;c.l=c.t=e;c.t-=1;if(Ext.isIE){c.l-=this.offset+b;c.t-=this.offset+b;c.w-=b;c.h-=b;c.t+=1}break;case"sides":c.w=(e*2);c.l=-e;c.t=e-1;if(Ext.isIE){c.l-=(this.offset-b);c.t-=this.offset+b;c.l+=1;c.w-=(this.offset-b)*2;c.w-=b+1;c.h-=1}break;case"frame":c.w=c.h=(e*2);c.l=c.t=-e;c.t+=1;c.h-=2;if(Ext.isIE){c.l-=(this.offset-b);c.t-=(this.offset-b);c.l+=1;c.w-=(this.offset+b+1);c.h-=(this.offset+b);c.h+=1}break}this.adjusts=c};Ext.Shadow.prototype={offset:4,defaultMode:"drop",show:function(a){a=Ext.get(a);if(!this.el){this.el=Ext.Shadow.Pool.pull();if(this.el.dom.nextSibling!=a.dom){this.el.insertBefore(a)}}this.el.setStyle("z-index",this.zIndex||parseInt(a.getStyle("z-index"),10)-1);if(Ext.isIE){this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")"}this.realign(a.getLeft(true),a.getTop(true),a.getWidth(),a.getHeight());this.el.dom.style.display="block"},isVisible:function(){return this.el?true:false},realign:function(b,q,p,f){if(!this.el){return}var m=this.adjusts,j=this.el.dom,r=j.style;var g=0;r.left=(b+m.l)+"px";r.top=(q+m.t)+"px";var o=(p+m.w),e=(f+m.h),i=o+"px",n=e+"px";if(r.width!=i||r.height!=n){r.width=i;r.height=n;if(!Ext.isIE){var k=j.childNodes;var c=Math.max(0,(o-12))+"px";k[0].childNodes[1].style.width=c;k[1].childNodes[1].style.width=c;k[2].childNodes[1].style.width=c;k[1].style.height=Math.max(0,(e-12))+"px"}}},hide:function(){if(this.el){this.el.dom.style.display="none";Ext.Shadow.Pool.push(this.el);delete this.el}},setZIndex:function(a){this.zIndex=a;if(this.el){this.el.setStyle("z-index",a)}}};Ext.Shadow.Pool=function(){var b=[];var a=Ext.isIE?'<div class="x-ie-shadow"></div>':'<div class="x-shadow"><div class="xst"><div class="xstl"></div><div class="xstc"></div><div class="xstr"></div></div><div class="xsc"><div class="xsml"></div><div class="xsmc"></div><div class="xsmr"></div></div><div class="xsb"><div class="xsbl"></div><div class="xsbc"></div><div class="xsbr"></div></div></div>';return{pull:function(){var c=b.shift();if(!c){c=Ext.get(Ext.DomHelper.insertHtml("beforeBegin",document.body.firstChild,a));c.autoBoxAdjust=false}return c},push:function(c){b.push(c)}}}();Ext.BoxComponent=Ext.extend(Ext.Component,{initComponent:function(){Ext.BoxComponent.superclass.initComponent.call(this);this.addEvents("resize","move")},boxReady:false,deferHeight:false,setSize:function(b,d){if(typeof b=="object"){d=b.height;b=b.width}if(!this.boxReady){this.width=b;this.height=d;return this}if(this.cacheSizes!==false&&this.lastSize&&this.lastSize.width==b&&this.lastSize.height==d){return this}this.lastSize={width:b,height:d};var c=this.adjustSize(b,d);var f=c.width,a=c.height;if(f!==undefined||a!==undefined){var e=this.getResizeEl();if(!this.deferHeight&&f!==undefined&&a!==undefined){e.setSize(f,a)}else{if(!this.deferHeight&&a!==undefined){e.setHeight(a)}else{if(f!==undefined){e.setWidth(f)}}}this.onResize(f,a,b,d);this.fireEvent("resize",this,f,a,b,d)}return this},setWidth:function(a){return this.setSize(a)},setHeight:function(a){return this.setSize(undefined,a)},getSize:function(){return this.getResizeEl().getSize()},getWidth:function(){return this.getResizeEl().getWidth()},getHeight:function(){return this.getResizeEl().getHeight()},getOuterSize:function(){var a=this.getResizeEl();return{width:a.getWidth()+a.getMargins("lr"),height:a.getHeight()+a.getMargins("tb")}},getPosition:function(a){var b=this.getPositionEl();if(a===true){return[b.getLeft(true),b.getTop(true)]}return this.xy||b.getXY()},getBox:function(a){var c=this.getPosition(a);var b=this.getSize();b.x=c[0];b.y=c[1];return b},updateBox:function(a){this.setSize(a.width,a.height);this.setPagePosition(a.x,a.y);return this},getResizeEl:function(){return this.resizeEl||this.el},getPositionEl:function(){return this.positionEl||this.el},setPosition:function(a,f){if(a&&typeof a[1]=="number"){f=a[1];a=a[0]}this.x=a;this.y=f;if(!this.boxReady){return this}var b=this.adjustPosition(a,f);var e=b.x,d=b.y;var c=this.getPositionEl();if(e!==undefined||d!==undefined){if(e!==undefined&&d!==undefined){c.setLeftTop(e,d)}else{if(e!==undefined){c.setLeft(e)}else{if(d!==undefined){c.setTop(d)}}}this.onPosition(e,d);this.fireEvent("move",this,e,d)}return this},setPagePosition:function(a,c){if(a&&typeof a[1]=="number"){c=a[1];a=a[0]}this.pageX=a;this.pageY=c;if(!this.boxReady){return}if(a===undefined||c===undefined){return}var b=this.getPositionEl().translatePoints(a,c);this.setPosition(b.left,b.top);return this},onRender:function(b,a){Ext.BoxComponent.superclass.onRender.call(this,b,a);if(this.resizeEl){this.resizeEl=Ext.get(this.resizeEl)}if(this.positionEl){this.positionEl=Ext.get(this.positionEl)}},afterRender:function(){Ext.BoxComponent.superclass.afterRender.call(this);this.boxReady=true;this.setSize(this.width,this.height);if(this.x||this.y){this.setPosition(this.x,this.y)}else{if(this.pageX||this.pageY){this.setPagePosition(this.pageX,this.pageY)}}},syncSize:function(){delete this.lastSize;this.setSize(this.autoWidth?undefined:this.getResizeEl().getWidth(),this.autoHeight?undefined:this.getResizeEl().getHeight());return this},onResize:function(d,b,a,c){},onPosition:function(a,b){},adjustSize:function(a,b){if(this.autoWidth){a="auto"}if(this.autoHeight){b="auto"}return{width:a,height:b}},adjustPosition:function(a,b){return{x:a,y:b}}});Ext.reg("box",Ext.BoxComponent);Ext.Spacer=Ext.extend(Ext.BoxComponent,{autoEl:"div"});Ext.reg("spacer",Ext.Spacer);Ext.SplitBar=function(c,e,b,d,a){this.el=Ext.get(c,true);this.el.dom.unselectable="on";this.resizingEl=Ext.get(e,true);this.orientation=b||Ext.SplitBar.HORIZONTAL;this.minSize=0;this.maxSize=2000;this.animate=false;this.useShim=false;this.shim=null;if(!a){this.proxy=Ext.SplitBar.createProxy(this.orientation)}else{this.proxy=Ext.get(a).dom}this.dd=new Ext.dd.DDProxy(this.el.dom.id,"XSplitBars",{dragElId:this.proxy.id});this.dd.b4StartDrag=this.onStartProxyDrag.createDelegate(this);this.dd.endDrag=this.onEndProxyDrag.createDelegate(this);this.dragSpecs={};this.adapter=new Ext.SplitBar.BasicLayoutAdapter();this.adapter.init(this);if(this.orientation==Ext.SplitBar.HORIZONTAL){this.placement=d||(this.el.getX()>this.resizingEl.getX()?Ext.SplitBar.LEFT:Ext.SplitBar.RIGHT);this.el.addClass("x-splitbar-h")}else{this.placement=d||(this.el.getY()>this.resizingEl.getY()?Ext.SplitBar.TOP:Ext.SplitBar.BOTTOM);this.el.addClass("x-splitbar-v")}this.addEvents("resize","moved","beforeresize","beforeapply");Ext.SplitBar.superclass.constructor.call(this)};Ext.extend(Ext.SplitBar,Ext.util.Observable,{onStartProxyDrag:function(a,e){this.fireEvent("beforeresize",this);this.overlay=Ext.DomHelper.append(document.body,{cls:"x-drag-overlay",html:"&#160;"},true);this.overlay.unselectable();this.overlay.setSize(Ext.lib.Dom.getViewWidth(true),Ext.lib.Dom.getViewHeight(true));this.overlay.show();Ext.get(this.proxy).setDisplayed("block");var c=this.adapter.getElementSize(this);this.activeMinSize=this.getMinimumSize();this.activeMaxSize=this.getMaximumSize();var d=c-this.activeMinSize;var b=Math.max(this.activeMaxSize-c,0);if(this.orientation==Ext.SplitBar.HORIZONTAL){this.dd.resetConstraints();this.dd.setXConstraint(this.placement==Ext.SplitBar.LEFT?d:b,this.placement==Ext.SplitBar.LEFT?b:d,this.tickSize);this.dd.setYConstraint(0,0)}else{this.dd.resetConstraints();this.dd.setXConstraint(0,0);this.dd.setYConstraint(this.placement==Ext.SplitBar.TOP?d:b,this.placement==Ext.SplitBar.TOP?b:d,this.tickSize)}this.dragSpecs.startSize=c;this.dragSpecs.startPoint=[a,e];Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd,a,e)},onEndProxyDrag:function(c){Ext.get(this.proxy).setDisplayed(false);var b=Ext.lib.Event.getXY(c);if(this.overlay){Ext.destroy(this.overlay);delete this.overlay}var a;if(this.orientation==Ext.SplitBar.HORIZONTAL){a=this.dragSpecs.startSize+(this.placement==Ext.SplitBar.LEFT?b[0]-this.dragSpecs.startPoint[0]:this.dragSpecs.startPoint[0]-b[0])}else{a=this.dragSpecs.startSize+(this.placement==Ext.SplitBar.TOP?b[1]-this.dragSpecs.startPoint[1]:this.dragSpecs.startPoint[1]-b[1])}a=Math.min(Math.max(a,this.activeMinSize),this.activeMaxSize);if(a!=this.dragSpecs.startSize){if(this.fireEvent("beforeapply",this,a)!==false){this.adapter.setElementSize(this,a);this.fireEvent("moved",this,a);this.fireEvent("resize",this,a)}}},getAdapter:function(){return this.adapter},setAdapter:function(a){this.adapter=a;this.adapter.init(this)},getMinimumSize:function(){return this.minSize},setMinimumSize:function(a){this.minSize=a},getMaximumSize:function(){return this.maxSize},setMaximumSize:function(a){this.maxSize=a},setCurrentSize:function(b){var a=this.animate;this.animate=false;this.adapter.setElementSize(this,b);this.animate=a},destroy:function(a){Ext.destroy(this.shim,Ext.get(this.proxy));this.dd.unreg();if(a){this.el.remove()}this.purgeListeners()}});Ext.SplitBar.createProxy=function(b){var c=new Ext.Element(document.createElement("div"));c.unselectable();var a="x-splitbar-proxy";c.addClass(a+" "+(b==Ext.SplitBar.HORIZONTAL?a+"-h":a+"-v"));document.body.appendChild(c.dom);return c.dom};Ext.SplitBar.BasicLayoutAdapter=function(){};Ext.SplitBar.BasicLayoutAdapter.prototype={init:function(a){},getElementSize:function(a){if(a.orientation==Ext.SplitBar.HORIZONTAL){return a.resizingEl.getWidth()}else{return a.resizingEl.getHeight()}},setElementSize:function(b,a,c){if(b.orientation==Ext.SplitBar.HORIZONTAL){if(!b.animate){b.resizingEl.setWidth(a);if(c){c(b,a)}}else{b.resizingEl.setWidth(a,true,0.1,c,"easeOut")}}else{if(!b.animate){b.resizingEl.setHeight(a);if(c){c(b,a)}}else{b.resizingEl.setHeight(a,true,0.1,c,"easeOut")}}}};Ext.SplitBar.AbsoluteLayoutAdapter=function(a){this.basic=new Ext.SplitBar.BasicLayoutAdapter();this.container=Ext.get(a)};Ext.SplitBar.AbsoluteLayoutAdapter.prototype={init:function(a){this.basic.init(a)},getElementSize:function(a){return this.basic.getElementSize(a)},setElementSize:function(b,a,c){this.basic.setElementSize(b,a,this.moveSplitter.createDelegate(this,[b]))},moveSplitter:function(a){var b=Ext.SplitBar;switch(a.placement){case b.LEFT:a.el.setX(a.resizingEl.getRight());break;case b.RIGHT:a.el.setStyle("right",(this.container.getWidth()-a.resizingEl.getLeft())+"px");break;case b.TOP:a.el.setY(a.resizingEl.getBottom());break;case b.BOTTOM:a.el.setY(a.resizingEl.getTop()-a.el.getHeight());break}}};Ext.SplitBar.VERTICAL=1;Ext.SplitBar.HORIZONTAL=2;Ext.SplitBar.LEFT=1;Ext.SplitBar.RIGHT=2;Ext.SplitBar.TOP=3;Ext.SplitBar.BOTTOM=4;Ext.Container=Ext.extend(Ext.BoxComponent,{bufferResize:100,autoDestroy:true,forceLayout:false,defaultType:"panel",initComponent:function(){Ext.Container.superclass.initComponent.call(this);this.addEvents("afterlayout","beforeadd","beforeremove","add","remove");this.enableBubble("add","remove");var a=this.items;if(a){delete this.items;if(Ext.isArray(a)&&a.length>0){this.add.apply(this,a)}else{this.add(a)}}},initItems:function(){if(!this.items){this.items=new Ext.util.MixedCollection(false,this.getComponentId);this.getLayout()}},setLayout:function(a){if(this.layout&&this.layout!=a){this.layout.setContainer(null)}this.initItems();this.layout=a;a.setContainer(this)},render:function(){Ext.Container.superclass.render.apply(this,arguments);if(this.layout){if(Ext.isObject(this.layout)&&!this.layout.layout){this.layoutConfig=this.layout;this.layout=this.layoutConfig.type}if(typeof this.layout=="string"){this.layout=new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig)}this.setLayout(this.layout);if(this.activeItem!==undefined){var a=this.activeItem;delete this.activeItem;this.layout.setActiveItem(a)}}if(!this.ownerCt){this.doLayout(false,true)}if(this.monitorResize===true){Ext.EventManager.onWindowResize(this.doLayout,this,[false])}},getLayoutTarget:function(){return this.el},getComponentId:function(a){return a.getItemId()},add:function(a){this.initItems();var b=arguments.length>1;if(b||Ext.isArray(a)){Ext.each(b?arguments:a,function(f){this.add(f)},this);return}var e=this.lookupComponent(this.applyDefaults(a));var d=this.items.length;if(this.fireEvent("beforeadd",this,e,d)!==false&&this.onBeforeAdd(e)!==false){this.items.add(e);e.ownerCt=this;this.fireEvent("add",this,e,d)}return e},insert:function(f,e){this.initItems();var d=arguments,b=d.length;if(b>2){for(var g=b-1;g>=1;--g){this.insert(f,d[g])}return}var h=this.lookupComponent(this.applyDefaults(e));if(h.ownerCt==this&&this.items.indexOf(h)<f){--f}if(this.fireEvent("beforeadd",this,h,f)!==false&&this.onBeforeAdd(h)!==false){this.items.insert(f,h);h.ownerCt=this;this.fireEvent("add",this,h,f)}return h},applyDefaults:function(a){if(this.defaults){if(typeof a=="string"){a=Ext.ComponentMgr.get(a);Ext.apply(a,this.defaults)}else{if(!a.events){Ext.applyIf(a,this.defaults)}else{Ext.apply(a,this.defaults)}}}return a},onBeforeAdd:function(a){if(a.ownerCt){a.ownerCt.remove(a,false)}if(this.hideBorders===true){a.border=(a.border===true)}},remove:function(a,b){this.initItems();var d=this.getComponent(a);if(d&&this.fireEvent("beforeremove",this,d)!==false){this.items.remove(d);delete d.ownerCt;if(b===true||(b!==false&&this.autoDestroy)){d.destroy()}if(this.layout&&this.layout.activeItem==d){delete this.layout.activeItem}this.fireEvent("remove",this,d)}return d},removeAll:function(c){this.initItems();var e,f=[],b=[];this.items.each(function(g){f.push(g)});for(var d=0,a=f.length;d<a;++d){e=f[d];this.remove(e,c);if(e.ownerCt!==this){b.push(e)}}return b},getComponent:function(a){if(Ext.isObject(a)){return a}return this.items.get(a)},lookupComponent:function(a){if(typeof a=="string"){return Ext.ComponentMgr.get(a)}else{if(!a.events){return this.createComponent(a)}}return a},createComponent:function(a){return Ext.create(a,this.defaultType)},doLayout:function(f,e){var j=this.rendered,h=this.forceLayout;if(!this.isVisible()||this.collapsed){this.deferLayout=this.deferLayout||!f;if(!(e||h)){return}f=f&&!this.deferLayout}else{delete this.deferLayout}if(j&&this.layout){this.layout.layout()}if(f!==true&&this.items){var d=this.items.items;for(var b=0,a=d.length;b<a;b++){var g=d[b];if(g.doLayout){g.forceLayout=h;g.doLayout()}}}if(j){this.onLayout(f,e)}delete this.forceLayout},onLayout:Ext.emptyFn,onShow:function(){Ext.Container.superclass.onShow.call(this);if(this.deferLayout!==undefined){this.doLayout(true)}},getLayout:function(){if(!this.layout){var a=new Ext.layout.ContainerLayout(this.layoutConfig);this.setLayout(a)}return this.layout},beforeDestroy:function(){if(this.items){Ext.destroy.apply(Ext,this.items.items)}if(this.monitorResize){Ext.EventManager.removeResizeListener(this.doLayout,this)}Ext.destroy(this.layout);Ext.Container.superclass.beforeDestroy.call(this)},bubble:function(c,b,a){var d=this;while(d){if(c.apply(b||d,a||[d])===false){break}d=d.ownerCt}return this},cascade:function(f,e,b){if(f.apply(e||this,b||[this])!==false){if(this.items){var d=this.items.items;for(var c=0,a=d.length;c<a;c++){if(d[c].cascade){d[c].cascade(f,e,b)}else{f.apply(e||d[c],b||[d[c]])}}}}return this},findById:function(c){var a,b=this;this.cascade(function(d){if(b!=d&&d.id===c){a=d;return false}});return a||null},findByType:function(b,a){return this.findBy(function(d){return d.isXType(b,a)})},find:function(b,a){return this.findBy(function(d){return d[b]===a})},findBy:function(d,c){var a=[],b=this;this.cascade(function(e){if(b!=e&&d.call(c||e,e,b)===true){a.push(e)}});return a},get:function(a){return this.items.get(a)}});Ext.Container.LAYOUTS={};Ext.reg("container",Ext.Container);Ext.layout.ContainerLayout=function(a){Ext.apply(this,a)};Ext.layout.ContainerLayout.prototype={monitorResize:false,activeItem:null,layout:function(){var a=this.container.getLayoutTarget();this.onLayout(this.container,a);this.container.fireEvent("afterlayout",this.container,this)},onLayout:function(a,b){this.renderAll(a,b)},isValidParent:function(b,a){return a&&b.getDomPositionEl().dom.parentNode==(a.dom||a)},renderAll:function(e,f){var b=e.items.items;for(var d=0,a=b.length;d<a;d++){var g=b[d];if(g&&(!g.rendered||!this.isValidParent(g,f))){this.renderItem(g,d,f)}}},renderItem:function(d,a,b){if(d&&!d.rendered){d.render(b,a);this.configureItem(d,a)}else{if(d&&!this.isValidParent(d,b)){if(typeof a=="number"){a=b.dom.childNodes[a]}b.dom.insertBefore(d.getDomPositionEl().dom,a||null);d.container=b;this.configureItem(d,a)}}},configureItem:function(d,a){if(this.extraCls){var b=d.getPositionEl?d.getPositionEl():d;b.addClass(this.extraCls)}if(this.renderHidden&&d!=this.activeItem){d.hide()}if(d.doLayout){d.doLayout(false,this.forceLayout)}},onResize:function(){if(this.container.collapsed){return}var a=this.container.bufferResize;if(a){if(!this.resizeTask){this.resizeTask=new Ext.util.DelayedTask(this.runLayout,this);this.resizeBuffer=typeof a=="number"?a:100}this.resizeTask.delay(this.resizeBuffer)}else{this.runLayout()}},runLayout:function(){this.layout();this.container.onLayout()},setContainer:function(a){if(this.monitorResize&&a!=this.container){if(this.container){this.container.un("resize",this.onResize,this);this.container.un("bodyresize",this.onResize,this)}if(a){a.on({scope:this,resize:this.onResize,bodyresize:this.onResize})}}this.container=a},parseMargins:function(b){if(typeof b=="number"){b=b.toString()}var c=b.split(" ");var a=c.length;if(a==1){c[1]=c[0];c[2]=c[0];c[3]=c[0]}if(a==2){c[2]=c[0];c[3]=c[1]}if(a==3){c[3]=c[1]}return{top:parseInt(c[0],10)||0,right:parseInt(c[1],10)||0,bottom:parseInt(c[2],10)||0,left:parseInt(c[3],10)||0}},fieldTpl:(function(){var a=new Ext.Template('<div class="x-form-item {itemCls}" tabIndex="-1">','<label for="{id}" style="{labelStyle}" class="x-form-item-label">{label}{labelSeparator}</label>','<div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">','</div><div class="{clearCls}"></div>',"</div>");a.disableFormats=true;return a.compile()})(),destroy:Ext.emptyFn};Ext.Container.LAYOUTS.auto=Ext.layout.ContainerLayout;Ext.layout.FitLayout=Ext.extend(Ext.layout.ContainerLayout,{monitorResize:true,onLayout:function(a,c){Ext.layout.FitLayout.superclass.onLayout.call(this,a,c);if(!this.container.collapsed){var b=(Ext.isIE6&&Ext.isStrict&&c.dom==document.body)?c.getViewSize():c.getStyleSize();this.setItemSize(this.activeItem||a.items.itemAt(0),b)}},setItemSize:function(b,a){if(b&&a.height>0){b.setSize(a)}}});Ext.Container.LAYOUTS.fit=Ext.layout.FitLayout;Ext.layout.CardLayout=Ext.extend(Ext.layout.FitLayout,{deferredRender:false,layoutOnCardChange:false,renderHidden:true,constructor:function(a){Ext.layout.CardLayout.superclass.constructor.call(this,a);this.forceLayout=(this.deferredRender===false)},setActiveItem:function(a){a=this.container.getComponent(a);if(this.activeItem!=a){if(this.activeItem){this.activeItem.hide()}this.activeItem=a;a.show();this.container.doLayout();if(this.layoutOnCardChange&&a.doLayout){a.doLayout()}}},renderAll:function(a,b){if(this.deferredRender){this.renderItem(this.activeItem,undefined,b)}else{Ext.layout.CardLayout.superclass.renderAll.call(this,a,b)}}});Ext.Container.LAYOUTS.card=Ext.layout.CardLayout;Ext.layout.AnchorLayout=Ext.extend(Ext.layout.ContainerLayout,{monitorResize:true,getAnchorViewSize:function(a,b){return b.dom==document.body?b.getViewSize():b.getStyleSize()},onLayout:function(j,m){Ext.layout.AnchorLayout.superclass.onLayout.call(this,j,m);var s=this.getAnchorViewSize(j,m);var q=s.width,g=s.height;if(q<20&&g<20){return}var d,o;if(j.anchorSize){if(typeof j.anchorSize=="number"){d=j.anchorSize}else{d=j.anchorSize.width;o=j.anchorSize.height}}else{d=j.initialConfig.width;o=j.initialConfig.height}var l=j.items.items,k=l.length,f,n,p,e,b;for(f=0;f<k;f++){n=l[f];if(n.anchor){p=n.anchorSpec;if(!p){var r=n.anchor.split(" ");n.anchorSpec=p={right:this.parseAnchor(r[0],n.initialConfig.width,d),bottom:this.parseAnchor(r[1],n.initialConfig.height,o)}}e=p.right?this.adjustWidthAnchor(p.right(q),n):undefined;b=p.bottom?this.adjustHeightAnchor(p.bottom(g),n):undefined;if(e||b){n.setSize(e||undefined,b||undefined)}}}},parseAnchor:function(c,g,b){if(c&&c!="none"){var e;if(/^(r|right|b|bottom)$/i.test(c)){var f=b-g;return function(a){if(a!==e){e=a;return a-f}}}else{if(c.indexOf("%")!=-1){var d=parseFloat(c.replace("%",""))*0.01;return function(a){if(a!==e){e=a;return Math.floor(a*d)}}}else{c=parseInt(c,10);if(!isNaN(c)){return function(a){if(a!==e){e=a;return a+c}}}}}}return false},adjustWidthAnchor:function(b,a){return b},adjustHeightAnchor:function(b,a){return b}});Ext.Container.LAYOUTS.anchor=Ext.layout.AnchorLayout;Ext.layout.ColumnLayout=Ext.extend(Ext.layout.ContainerLayout,{monitorResize:true,extraCls:"x-column",scrollOffset:0,isValidParent:function(b,a){return(b.getPositionEl?b.getPositionEl():b.getEl()).dom.parentNode==this.innerCt.dom},onLayout:function(d,g){var e=d.items.items,f=e.length,j,a;if(!this.innerCt){g.addClass("x-column-layout-ct");this.innerCt=g.createChild({cls:"x-column-inner"});this.innerCt.createChild({cls:"x-clear"})}this.renderAll(d,this.innerCt);var m=Ext.isIE&&g.dom!=Ext.getBody().dom?g.getStyleSize():g.getViewSize();if(m.width<1&&m.height<1){return}var k=m.width-g.getPadding("lr")-this.scrollOffset,b=m.height-g.getPadding("tb"),l=k;this.innerCt.setWidth(k);for(a=0;a<f;a++){j=e[a];if(!j.columnWidth){l-=(j.getSize().width+j.getEl().getMargins("lr"))}}l=l<0?0:l;for(a=0;a<f;a++){j=e[a];if(j.columnWidth){j.setSize(Math.floor(j.columnWidth*l)-j.getEl().getMargins("lr"))}}}});Ext.Container.LAYOUTS.column=Ext.layout.ColumnLayout;Ext.layout.BorderLayout=Ext.extend(Ext.layout.ContainerLayout,{monitorResize:true,rendered:false,onLayout:function(d,G){var f;if(!this.rendered){G.addClass("x-border-layout-ct");var u=d.items.items;f=[];for(var z=0,A=u.length;z<A;z++){var D=u[z];var k=D.region;if(D.collapsed){f.push(D)}D.collapsed=false;if(!D.rendered){D.cls=D.cls?D.cls+" x-border-panel":"x-border-panel";D.render(G,z)}this[k]=k!="center"&&D.split?new Ext.layout.BorderLayout.SplitRegion(this,D.initialConfig,k):new Ext.layout.BorderLayout.Region(this,D.initialConfig,k);this[k].render(G,D)}this.rendered=true}var t=G.getViewSize();if(t.width<20||t.height<20){if(f){this.restoreCollapsed=f}return}else{if(this.restoreCollapsed){f=this.restoreCollapsed;delete this.restoreCollapsed}}var q=t.width,B=t.height;var p=q,y=B,l=0,o=0;var v=this.north,r=this.south,j=this.west,C=this.east,D=this.center;if(!D&&Ext.layout.BorderLayout.WARN!==false){throw"No center region defined in BorderLayout "+d.id}if(v&&v.isVisible()){var F=v.getSize();var x=v.getMargins();F.width=q-(x.left+x.right);F.x=x.left;F.y=x.top;l=F.height+F.y+x.bottom;y-=l;v.applyLayout(F)}if(r&&r.isVisible()){var F=r.getSize();var x=r.getMargins();F.width=q-(x.left+x.right);F.x=x.left;var E=(F.height+x.top+x.bottom);F.y=B-E+x.top;y-=E;r.applyLayout(F)}if(j&&j.isVisible()){var F=j.getSize();var x=j.getMargins();F.height=y-(x.top+x.bottom);F.x=x.left;F.y=l+x.top;var a=(F.width+x.left+x.right);o+=a;p-=a;j.applyLayout(F)}if(C&&C.isVisible()){var F=C.getSize();var x=C.getMargins();F.height=y-(x.top+x.bottom);var a=(F.width+x.left+x.right);F.x=q-a+x.left;F.y=l+x.top;p-=a;C.applyLayout(F)}if(D){var x=D.getMargins();var g={x:o+x.left,y:l+x.top,width:p-(x.left+x.right),height:y-(x.top+x.bottom)};D.applyLayout(g)}if(f){for(var z=0,A=f.length;z<A;z++){f[z].collapse(false)}}if(Ext.isIE&&Ext.isStrict){G.repaint()}},destroy:function(){var b=["north","south","east","west"];for(var a=0;a<b.length;a++){var c=this[b[a]];if(c){if(c.destroy){c.destroy()}else{if(c.split){c.split.destroy(true)}}}}Ext.layout.BorderLayout.superclass.destroy.call(this)}});Ext.layout.BorderLayout.Region=function(b,a,c){Ext.apply(this,a);this.layout=b;this.position=c;this.state={};if(typeof this.margins=="string"){this.margins=this.layout.parseMargins(this.margins)}this.margins=Ext.applyIf(this.margins||{},this.defaultMargins);if(this.collapsible){if(typeof this.cmargins=="string"){this.cmargins=this.layout.parseMargins(this.cmargins)}if(this.collapseMode=="mini"&&!this.cmargins){this.cmargins={left:0,top:0,right:0,bottom:0}}else{this.cmargins=Ext.applyIf(this.cmargins||{},c=="north"||c=="south"?this.defaultNSCMargins:this.defaultEWCMargins)}}};Ext.layout.BorderLayout.Region.prototype={collapsible:false,split:false,floatable:true,minWidth:50,minHeight:50,defaultMargins:{left:0,top:0,right:0,bottom:0},defaultNSCMargins:{left:5,top:5,right:5,bottom:5},defaultEWCMargins:{left:5,top:0,right:5,bottom:0},floatingZIndex:100,isCollapsed:false,render:function(b,c){this.panel=c;c.el.enableDisplayMode();this.targetEl=b;this.el=c.el;var a=c.getState,d=this.position;c.getState=function(){return Ext.apply(a.call(c)||{},this.state)}.createDelegate(this);if(d!="center"){c.allowQueuedExpand=false;c.on({beforecollapse:this.beforeCollapse,collapse:this.onCollapse,beforeexpand:this.beforeExpand,expand:this.onExpand,hide:this.onHide,show:this.onShow,scope:this});if(this.collapsible||this.floatable){c.collapseEl="el";c.slideAnchor=this.getSlideAnchor()}if(c.tools&&c.tools.toggle){c.tools.toggle.addClass("x-tool-collapse-"+d);c.tools.toggle.addClassOnOver("x-tool-collapse-"+d+"-over")}}},getCollapsedEl:function(){if(!this.collapsedEl){if(!this.toolTemplate){var b=new Ext.Template('<div class="x-tool x-tool-{id}">&#160;</div>');b.disableFormats=true;b.compile();Ext.layout.BorderLayout.Region.prototype.toolTemplate=b}this.collapsedEl=this.targetEl.createChild({cls:"x-layout-collapsed x-layout-collapsed-"+this.position,id:this.panel.id+"-xcollapsed"});this.collapsedEl.enableDisplayMode("block");if(this.collapseMode=="mini"){this.collapsedEl.addClass("x-layout-cmini-"+this.position);this.miniCollapsedEl=this.collapsedEl.createChild({cls:"x-layout-mini x-layout-mini-"+this.position,html:"&#160;"});this.miniCollapsedEl.addClassOnOver("x-layout-mini-over");this.collapsedEl.addClassOnOver("x-layout-collapsed-over");this.collapsedEl.on("click",this.onExpandClick,this,{stopEvent:true})}else{if(this.collapsible!==false&&!this.hideCollapseTool){var a=this.toolTemplate.append(this.collapsedEl.dom,{id:"expand-"+this.position},true);a.addClassOnOver("x-tool-expand-"+this.position+"-over");a.on("click",this.onExpandClick,this,{stopEvent:true})}if(this.floatable!==false||this.titleCollapse){this.collapsedEl.addClassOnOver("x-layout-collapsed-over");this.collapsedEl.on("click",this[this.floatable?"collapseClick":"onExpandClick"],this)}}}return this.collapsedEl},onExpandClick:function(a){if(this.isSlid){this.afterSlideIn();this.panel.expand(false)}else{this.panel.expand()}},onCollapseClick:function(a){this.panel.collapse()},beforeCollapse:function(b,a){this.lastAnim=a;if(this.splitEl){this.splitEl.hide()}this.getCollapsedEl().show();this.panel.el.setStyle("z-index",100);this.isCollapsed=true;this.layout.layout()},onCollapse:function(a){this.panel.el.setStyle("z-index",1);if(this.lastAnim===false||this.panel.animCollapse===false){this.getCollapsedEl().dom.style.visibility="visible"}else{this.getCollapsedEl().slideIn(this.panel.slideAnchor,{duration:0.2})}this.state.collapsed=true;this.panel.saveState()},beforeExpand:function(a){var b=this.getCollapsedEl();this.el.show();if(this.position=="east"||this.position=="west"){this.panel.setSize(undefined,b.getHeight())}else{this.panel.setSize(b.getWidth(),undefined)}b.hide();b.dom.style.visibility="hidden";this.panel.el.setStyle("z-index",this.floatingZIndex)},onExpand:function(){this.isCollapsed=false;if(this.splitEl){this.splitEl.show()}this.layout.layout();this.panel.el.setStyle("z-index",1);this.state.collapsed=false;this.panel.saveState()},collapseClick:function(a){if(this.isSlid){a.stopPropagation();this.slideIn()}else{a.stopPropagation();this.slideOut()}},onHide:function(){if(this.isCollapsed){this.getCollapsedEl().hide()}else{if(this.splitEl){this.splitEl.hide()}}},onShow:function(){if(this.isCollapsed){this.getCollapsedEl().show()}else{if(this.splitEl){this.splitEl.show()}}},isVisible:function(){return !this.panel.hidden},getMargins:function(){return this.isCollapsed&&this.cmargins?this.cmargins:this.margins},getSize:function(){return this.isCollapsed?this.getCollapsedEl().getSize():this.panel.getSize()},setPanel:function(a){this.panel=a},getMinWidth:function(){return this.minWidth},getMinHeight:function(){return this.minHeight},applyLayoutCollapsed:function(a){var b=this.getCollapsedEl();b.setLeftTop(a.x,a.y);b.setSize(a.width,a.height)},applyLayout:function(a){if(this.isCollapsed){this.applyLayoutCollapsed(a)}else{this.panel.setPosition(a.x,a.y);this.panel.setSize(a.width,a.height)}},beforeSlide:function(){this.panel.beforeEffect()},afterSlide:function(){this.panel.afterEffect()},initAutoHide:function(){if(this.autoHide!==false){if(!this.autoHideHd){var a=new Ext.util.DelayedTask(this.slideIn,this);this.autoHideHd={mouseout:function(b){if(!b.within(this.el,true)){a.delay(500)}},mouseover:function(b){a.cancel()},scope:this}}this.el.on(this.autoHideHd)}},clearAutoHide:function(){if(this.autoHide!==false){this.el.un("mouseout",this.autoHideHd.mouseout);this.el.un("mouseover",this.autoHideHd.mouseover)}},clearMonitor:function(){Ext.getDoc().un("click",this.slideInIf,this)},slideOut:function(){if(this.isSlid||this.el.hasActiveFx()){return}this.isSlid=true;var a=this.panel.tools;if(a&&a.toggle){a.toggle.hide()}this.el.show();if(this.position=="east"||this.position=="west"){this.panel.setSize(undefined,this.collapsedEl.getHeight())}else{this.panel.setSize(this.collapsedEl.getWidth(),undefined)}this.restoreLT=[this.el.dom.style.left,this.el.dom.style.top];this.el.alignTo(this.collapsedEl,this.getCollapseAnchor());this.el.setStyle("z-index",this.floatingZIndex+2);this.panel.el.replaceClass("x-panel-collapsed","x-panel-floating");if(this.animFloat!==false){this.beforeSlide();this.el.slideIn(this.getSlideAnchor(),{callback:function(){this.afterSlide();this.initAutoHide();Ext.getDoc().on("click",this.slideInIf,this)},scope:this,block:true})}else{this.initAutoHide();Ext.getDoc().on("click",this.slideInIf,this)}},afterSlideIn:function(){this.clearAutoHide();this.isSlid=false;this.clearMonitor();this.el.setStyle("z-index","");this.panel.el.replaceClass("x-panel-floating","x-panel-collapsed");this.el.dom.style.left=this.restoreLT[0];this.el.dom.style.top=this.restoreLT[1];var a=this.panel.tools;if(a&&a.toggle){a.toggle.show()}},slideIn:function(a){if(!this.isSlid||this.el.hasActiveFx()){Ext.callback(a);return}this.isSlid=false;if(this.animFloat!==false){this.beforeSlide();this.el.slideOut(this.getSlideAnchor(),{callback:function(){this.el.hide();this.afterSlide();this.afterSlideIn();Ext.callback(a)},scope:this,block:true})}else{this.el.hide();this.afterSlideIn()}},slideInIf:function(a){if(!a.within(this.el)){this.slideIn()}},anchors:{west:"left",east:"right",north:"top",south:"bottom"},sanchors:{west:"l",east:"r",north:"t",south:"b"},canchors:{west:"tl-tr",east:"tr-tl",north:"tl-bl",south:"bl-tl"},getAnchor:function(){return this.anchors[this.position]},getCollapseAnchor:function(){return this.canchors[this.position]},getSlideAnchor:function(){return this.sanchors[this.position]},getAlignAdj:function(){var a=this.cmargins;switch(this.position){case"west":return[0,0];break;case"east":return[0,0];break;case"north":return[0,0];break;case"south":return[0,0];break}},getExpandAdj:function(){var b=this.collapsedEl,a=this.cmargins;switch(this.position){case"west":return[-(a.right+b.getWidth()+a.left),0];break;case"east":return[a.right+b.getWidth()+a.left,0];break;case"north":return[0,-(a.top+a.bottom+b.getHeight())];break;case"south":return[0,a.top+a.bottom+b.getHeight()];break}}};Ext.layout.BorderLayout.SplitRegion=function(b,a,c){Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this,b,a,c);this.applyLayout=this.applyFns[c]};Ext.extend(Ext.layout.BorderLayout.SplitRegion,Ext.layout.BorderLayout.Region,{splitTip:"Drag to resize.",collapsibleSplitTip:"Drag to resize. Double click to hide.",useSplitTips:false,splitSettings:{north:{orientation:Ext.SplitBar.VERTICAL,placement:Ext.SplitBar.TOP,maxFn:"getVMaxSize",minProp:"minHeight",maxProp:"maxHeight"},south:{orientation:Ext.SplitBar.VERTICAL,placement:Ext.SplitBar.BOTTOM,maxFn:"getVMaxSize",minProp:"minHeight",maxProp:"maxHeight"},east:{orientation:Ext.SplitBar.HORIZONTAL,placement:Ext.SplitBar.RIGHT,maxFn:"getHMaxSize",minProp:"minWidth",maxProp:"maxWidth"},west:{orientation:Ext.SplitBar.HORIZONTAL,placement:Ext.SplitBar.LEFT,maxFn:"getHMaxSize",minProp:"minWidth",maxProp:"maxWidth"}},applyFns:{west:function(c){if(this.isCollapsed){return this.applyLayoutCollapsed(c)}var d=this.splitEl.dom,b=d.style;this.panel.setPosition(c.x,c.y);var a=d.offsetWidth;b.left=(c.x+c.width-a)+"px";b.top=(c.y)+"px";b.height=Math.max(0,c.height)+"px";this.panel.setSize(c.width-a,c.height)},east:function(c){if(this.isCollapsed){return this.applyLayoutCollapsed(c)}var d=this.splitEl.dom,b=d.style;var a=d.offsetWidth;this.panel.setPosition(c.x+a,c.y);b.left=(c.x)+"px";b.top=(c.y)+"px";b.height=Math.max(0,c.height)+"px";this.panel.setSize(c.width-a,c.height)},north:function(c){if(this.isCollapsed){return this.applyLayoutCollapsed(c)}var d=this.splitEl.dom,b=d.style;var a=d.offsetHeight;this.panel.setPosition(c.x,c.y);b.left=(c.x)+"px";b.top=(c.y+c.height-a)+"px";b.width=Math.max(0,c.width)+"px";this.panel.setSize(c.width,c.height-a)},south:function(c){if(this.isCollapsed){return this.applyLayoutCollapsed(c)}var d=this.splitEl.dom,b=d.style;var a=d.offsetHeight;this.panel.setPosition(c.x,c.y+a);b.left=(c.x)+"px";b.top=(c.y)+"px";b.width=Math.max(0,c.width)+"px";this.panel.setSize(c.width,c.height-a)}},render:function(a,c){Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this,a,c);var d=this.position;this.splitEl=a.createChild({cls:"x-layout-split x-layout-split-"+d,html:"&#160;",id:this.panel.id+"-xsplit"});if(this.collapseMode=="mini"){this.miniSplitEl=this.splitEl.createChild({cls:"x-layout-mini x-layout-mini-"+d,html:"&#160;"});this.miniSplitEl.addClassOnOver("x-layout-mini-over");this.miniSplitEl.on("click",this.onCollapseClick,this,{stopEvent:true})}var b=this.splitSettings[d];this.split=new Ext.SplitBar(this.splitEl.dom,c.el,b.orientation);this.split.tickSize=this.tickSize;this.split.placement=b.placement;this.split.getMaximumSize=this[b.maxFn].createDelegate(this);this.split.minSize=this.minSize||this[b.minProp];this.split.on("beforeapply",this.onSplitMove,this);this.split.useShim=this.useShim===true;this.maxSize=this.maxSize||this[b.maxProp];if(c.hidden){this.splitEl.hide()}if(this.useSplitTips){this.splitEl.dom.title=this.collapsible?this.collapsibleSplitTip:this.splitTip}if(this.collapsible){this.splitEl.on("dblclick",this.onCollapseClick,this)}},getSize:function(){if(this.isCollapsed){return this.collapsedEl.getSize()}var a=this.panel.getSize();if(this.position=="north"||this.position=="south"){a.height+=this.splitEl.dom.offsetHeight}else{a.width+=this.splitEl.dom.offsetWidth}return a},getHMaxSize:function(){var b=this.maxSize||10000;var a=this.layout.center;return Math.min(b,(this.el.getWidth()+a.el.getWidth())-a.getMinWidth())},getVMaxSize:function(){var b=this.maxSize||10000;var a=this.layout.center;return Math.min(b,(this.el.getHeight()+a.el.getHeight())-a.getMinHeight())},onSplitMove:function(b,a){var c=this.panel.getSize();this.lastSplitSize=a;if(this.position=="north"||this.position=="south"){this.panel.setSize(c.width,a);this.state.height=a}else{this.panel.setSize(a,c.height);this.state.width=a}this.layout.layout();this.panel.saveState();return false},getSplitBar:function(){return this.split},destroy:function(){Ext.destroy(this.miniSplitEl,this.split,this.splitEl)}});Ext.Container.LAYOUTS.border=Ext.layout.BorderLayout;Ext.layout.FormLayout=Ext.extend(Ext.layout.AnchorLayout,{labelSeparator:":",setContainer:function(a){Ext.layout.FormLayout.superclass.setContainer.call(this,a);if(a.labelAlign){a.addClass("x-form-label-"+a.labelAlign)}if(a.hideLabels){this.labelStyle="display:none";this.elementStyle="padding-left:0;";this.labelAdjust=0}else{this.labelSeparator=a.labelSeparator||this.labelSeparator;a.labelWidth=a.labelWidth||100;if(typeof a.labelWidth=="number"){var b=(typeof a.labelPad=="number"?a.labelPad:5);this.labelAdjust=a.labelWidth+b;this.labelStyle="width:"+a.labelWidth+"px;";this.elementStyle="padding-left:"+(a.labelWidth+b)+"px"}if(a.labelAlign=="top"){this.labelStyle="width:auto;";this.labelAdjust=0;this.elementStyle="padding-left:0;"}}},getLabelStyle:function(e){var b="",c=[this.labelStyle,e];for(var d=0,a=c.length;d<a;++d){if(c[d]){b+=c[d];if(b.substr(-1,1)!=";"){b+=";"}}}return b},renderItem:function(e,a,d){if(e&&!e.rendered&&(e.isFormField||e.fieldLabel)&&e.inputType!="hidden"){var b=this.getTemplateArgs(e);if(typeof a=="number"){a=d.dom.childNodes[a]||null}if(a){this.fieldTpl.insertBefore(a,b)}else{this.fieldTpl.append(d,b)}e.render("x-form-el-"+e.id)}else{Ext.layout.FormLayout.superclass.renderItem.apply(this,arguments)}},getTemplateArgs:function(b){var a=!b.fieldLabel||b.hideLabel;return{id:b.id,label:b.fieldLabel,labelStyle:b.labelStyle||this.labelStyle||"",elementStyle:this.elementStyle||"",labelSeparator:a?"":(typeof b.labelSeparator=="undefined"?this.labelSeparator:b.labelSeparator),itemCls:(b.itemCls||this.container.itemCls||"")+(b.hideLabel?" x-hide-label":""),clearCls:b.clearCls||"x-form-clear-left"}},adjustWidthAnchor:function(b,a){return b-(a.isFormField||a.fieldLabel?(a.hideLabel?0:this.labelAdjust):0)},isValidParent:function(b,a){return true}});Ext.Container.LAYOUTS.form=Ext.layout.FormLayout;Ext.layout.AccordionLayout=Ext.extend(Ext.layout.FitLayout,{fill:true,autoWidth:true,titleCollapse:true,hideCollapseTool:false,collapseFirst:false,animate:false,sequence:false,activeOnTop:false,renderItem:function(a){if(this.animate===false){a.animCollapse=false}a.collapsible=true;if(this.autoWidth){a.autoWidth=true}if(this.titleCollapse){a.titleCollapse=true}if(this.hideCollapseTool){a.hideCollapseTool=true}if(this.collapseFirst!==undefined){a.collapseFirst=this.collapseFirst}if(!this.activeItem&&!a.collapsed){this.activeItem=a}else{if(this.activeItem&&this.activeItem!=a){a.collapsed=true}}Ext.layout.AccordionLayout.superclass.renderItem.apply(this,arguments);a.header.addClass("x-accordion-hd");a.on("beforeexpand",this.beforeExpand,this)},beforeExpand:function(c,b){var a=this.activeItem;if(a){if(this.sequence){delete this.activeItem;if(!a.collapsed){a.collapse({callback:function(){c.expand(b||true)},scope:this});return false}}else{a.collapse(this.animate)}}this.activeItem=c;if(this.activeOnTop){c.el.dom.parentNode.insertBefore(c.el.dom,c.el.dom.parentNode.firstChild)}this.layout()},setItemSize:function(c,b){if(this.fill&&c){var a=0;this.container.items.each(function(d){if(d!=c){a+=d.header.getHeight()}});b.height-=a;c.setSize(b)}},setActiveItem:function(a){a=this.container.getComponent(a);if(this.activeItem!=a){if(a.rendered&&a.collapsed){a.expand()}else{this.activeItem=a}}}});Ext.Container.LAYOUTS.accordion=Ext.layout.AccordionLayout;Ext.layout.Accordion=Ext.layout.AccordionLayout;Ext.layout.TableLayout=Ext.extend(Ext.layout.ContainerLayout,{monitorResize:false,tableAttrs:null,setContainer:function(a){Ext.layout.TableLayout.superclass.setContainer.call(this,a);this.currentRow=0;this.currentColumn=0;this.cells=[]},onLayout:function(d,f){var e=d.items.items,a=e.length,g,b;if(!this.table){f.addClass("x-table-layout-ct");this.table=f.createChild(Ext.apply({tag:"table",cls:"x-table-layout",cellspacing:0,cn:{tag:"tbody"}},this.tableAttrs),null,true)}this.renderAll(d,f)},getRow:function(a){var b=this.table.tBodies[0].childNodes[a];if(!b){b=document.createElement("tr");this.table.tBodies[0].appendChild(b)}return b},getNextCell:function(i){var a=this.getNextNonSpan(this.currentColumn,this.currentRow);var f=this.currentColumn=a[0],e=this.currentRow=a[1];for(var h=e;h<e+(i.rowspan||1);h++){if(!this.cells[h]){this.cells[h]=[]}for(var d=f;d<f+(i.colspan||1);d++){this.cells[h][d]=true}}var g=document.createElement("td");if(i.cellId){g.id=i.cellId}var b="x-table-layout-cell";if(i.cellCls){b+=" "+i.cellCls}g.className=b;if(i.colspan){g.colSpan=i.colspan}if(i.rowspan){g.rowSpan=i.rowspan}this.getRow(e).appendChild(g);return g},getNextNonSpan:function(a,c){var b=this.columns;while((b&&a>=b)||(this.cells[c]&&this.cells[c][a])){if(b&&a>=b){c++;a=0}else{a++}}return[a,c]},renderItem:function(e,a,d){if(e&&!e.rendered){e.render(this.getNextCell(e));if(this.extraCls){var b=e.getPositionEl?e.getPositionEl():e;b.addClass(this.extraCls)}}},isValidParent:function(b,a){return true}});Ext.Container.LAYOUTS.table=Ext.layout.TableLayout;Ext.layout.AbsoluteLayout=Ext.extend(Ext.layout.AnchorLayout,{extraCls:"x-abs-layout-item",onLayout:function(a,b){b.position();this.paddingLeft=b.getPadding("l");this.paddingTop=b.getPadding("t");Ext.layout.AbsoluteLayout.superclass.onLayout.call(this,a,b)},adjustWidthAnchor:function(b,a){return b?b-a.getPosition(true)[0]+this.paddingLeft:b},adjustHeightAnchor:function(b,a){return b?b-a.getPosition(true)[1]+this.paddingTop:b}});Ext.Container.LAYOUTS.absolute=Ext.layout.AbsoluteLayout;Ext.layout.BoxLayout=Ext.extend(Ext.layout.ContainerLayout,{defaultMargins:{left:0,top:0,right:0,bottom:0},padding:"0",pack:"start",monitorResize:true,scrollOffset:0,extraCls:"x-box-item",ctCls:"x-box-layout-ct",innerCls:"x-box-inner",isValidParent:function(b,a){return b.getEl().dom.parentNode==this.innerCt.dom},onLayout:function(e,h){var f=e.items.items,b=f.length,j,d,g=b-1,a;if(!this.innerCt){h.addClass(this.ctCls);this.innerCt=h.createChild({cls:this.innerCls});this.padding=this.parseMargins(this.padding)}this.renderAll(e,this.innerCt)},renderItem:function(a){if(typeof a.margins=="string"){a.margins=this.parseMargins(a.margins)}else{if(!a.margins){a.margins=this.defaultMargins}}Ext.layout.BoxLayout.superclass.renderItem.apply(this,arguments)},getTargetSize:function(a){return(Ext.isIE6&&Ext.isStrict&&a.dom==document.body)?a.getStyleSize():a.getViewSize()},getItems:function(b){var a=[];b.items.each(function(d){if(d.isVisible()){a.push(d)}});return a}});Ext.layout.VBoxLayout=Ext.extend(Ext.layout.BoxLayout,{align:"left",onLayout:function(e,D){Ext.layout.VBoxLayout.superclass.onLayout.call(this,e,D);var f=this.getItems(e),i,k,p,q=this.getTargetSize(D),j=q.width-D.getPadding("lr")-this.scrollOffset,x=q.height-D.getPadding("tb"),r=this.padding.left,m=this.padding.top,g=this.pack=="start",u=["stretch","stretchmax"].indexOf(this.align)==-1,A=j-(this.padding.left+this.padding.right),n=0,z=0,s=0,B=0,d=0;Ext.each(f,function(h){i=h.margins;s+=h.flex||0;k=h.getHeight();p=i.top+i.bottom;n+=k+p;B+=p+(h.flex?0:k);z=Math.max(z,h.getWidth()+i.left+i.right)});n=x-n-this.padding.top-this.padding.bottom;var a=z+this.padding.left+this.padding.right;switch(this.align){case"stretch":this.innerCt.setSize(j,x);break;case"stretchmax":case"left":this.innerCt.setSize(a,x);break;case"center":this.innerCt.setSize(j=Math.max(j,a),x);break}var c=Math.max(0,x-this.padding.top-this.padding.bottom-B),C=c,y=[],v=[],o=0,b=Math.max(0,j-this.padding.left-this.padding.right);Ext.each(f,function(h){if(g&&h.flex){k=Math.floor(c*(h.flex/s));C-=k;y.push(k)}});if(this.pack=="center"){m+=n?n/2:0}else{if(this.pack=="end"){m+=n}}Ext.each(f,function(h){i=h.margins;m+=i.top;h.setPosition(r+i.left,m);if(g&&h.flex){k=Math.max(0,y[o++]+(C-->0?1:0));if(u){v.push(h.getWidth())}h.setSize(b,k)}else{k=h.getHeight()}m+=k+i.bottom});o=0;Ext.each(f,function(l){i=l.margins;if(this.align=="stretch"){l.setWidth((A-(i.left+i.right)).constrain(l.minWidth||0,l.maxWidth||1000000))}else{if(this.align=="stretchmax"){l.setWidth((z-(i.left+i.right)).constrain(l.minWidth||0,l.maxWidth||1000000))}else{if(this.align=="center"){var h=b-(l.getWidth()+i.left+i.right);if(h>0){l.setPosition(r+i.left+(h/2),l.y)}}if(g&&l.flex){l.setWidth(v[o++])}}}},this)}});Ext.Container.LAYOUTS.vbox=Ext.layout.VBoxLayout;Ext.layout.HBoxLayout=Ext.extend(Ext.layout.BoxLayout,{align:"top",onLayout:function(d,D){Ext.layout.HBoxLayout.superclass.onLayout.call(this,d,D);var e=this.getItems(d),i,c,p,q=this.getTargetSize(D),k=q.width-D.getPadding("lr")-this.scrollOffset,A=q.height-D.getPadding("tb"),s=this.padding.left,n=this.padding.top,g=this.pack=="start",y=["stretch","stretchmax"].indexOf(this.align)==-1,m=A-(this.padding.top+this.padding.bottom),B=0,r=0,u=0,b=0,f=0;Ext.each(e,function(h){i=h.margins;u+=h.flex||0;c=h.getWidth();p=i.left+i.right;B+=c+p;b+=p+(h.flex?0:c);r=Math.max(r,h.getHeight()+i.top+i.bottom)});B=k-B-this.padding.left-this.padding.right;var x=r+this.padding.top+this.padding.bottom;switch(this.align){case"stretch":this.innerCt.setSize(k,A);break;case"stretchmax":case"top":this.innerCt.setSize(k,x);break;case"middle":this.innerCt.setSize(k,A=Math.max(A,x));break}var v=Math.max(0,k-this.padding.left-this.padding.right-b),C=v,j=[],z=[],o=0,a=Math.max(0,A-this.padding.top-this.padding.bottom);Ext.each(e,function(h){if(g&&h.flex){c=Math.floor(v*(h.flex/u));C-=c;j.push(c)}});if(this.pack=="center"){s+=B?B/2:0}else{if(this.pack=="end"){s+=B}}Ext.each(e,function(h){i=h.margins;s+=i.left;h.setPosition(s,n+i.top);if(g&&h.flex){c=Math.max(0,j[o++]+(C-->0?1:0));if(y){z.push(h.getHeight())}h.setSize(c,a)}else{c=h.getWidth()}s+=c+i.right});o=0;Ext.each(e,function(t){var h=t.margins;if(this.align=="stretch"){t.setHeight((m-(h.top+h.bottom)).constrain(t.minHeight||0,t.maxHeight||1000000))}else{if(this.align=="stretchmax"){t.setHeight((r-(h.top+h.bottom)).constrain(t.minHeight||0,t.maxHeight||1000000))}else{if(this.align=="middle"){var l=a-(t.getHeight()+h.top+h.bottom);if(l>0){t.setPosition(t.x,n+h.top+(l/2))}}if(g&&t.flex){t.setHeight(z[o++])}}}},this)}});Ext.Container.LAYOUTS.hbox=Ext.layout.HBoxLayout;Ext.Viewport=Ext.extend(Ext.Container,{initComponent:function(){Ext.Viewport.superclass.initComponent.call(this);document.getElementsByTagName("html")[0].className+=" x-viewport";this.el=Ext.getBody();this.el.setHeight=Ext.emptyFn;this.el.setWidth=Ext.emptyFn;this.el.setSize=Ext.emptyFn;this.el.dom.scroll="no";this.allowDomMove=false;this.autoWidth=true;this.autoHeight=true;Ext.EventManager.onWindowResize(this.fireResize,this);this.renderTo=this.el},fireResize:function(a,b){this.fireEvent("resize",this,a,b,a,b)}});Ext.reg("viewport",Ext.Viewport);Ext.Panel=Ext.extend(Ext.Container,{baseCls:"x-panel",collapsedCls:"x-panel-collapsed",maskDisabled:true,animCollapse:Ext.enableFx,headerAsText:true,buttonAlign:"right",collapsed:false,collapseFirst:true,minButtonWidth:75,elements:"body",preventBodyReset:false,toolTarget:"header",collapseEl:"bwrap",slideAnchor:"t",disabledClass:"",deferHeight:true,expandDefaults:{duration:0.25},collapseDefaults:{duration:0.25},initComponent:function(){Ext.Panel.superclass.initComponent.call(this);this.addEvents("bodyresize","titlechange","iconchange","collapse","expand","beforecollapse","beforeexpand","beforeclose","close","activate","deactivate");if(this.unstyled){this.baseCls="x-plain"}if(this.tbar){this.elements+=",tbar";if(Ext.isObject(this.tbar)){this.topToolbar=this.tbar}delete this.tbar}if(this.bbar){this.elements+=",bbar";if(Ext.isObject(this.bbar)){this.bottomToolbar=this.bbar}delete this.bbar}if(this.header===true){this.elements+=",header";delete this.header}else{if(this.headerCfg||(this.title&&this.header!==false)){this.elements+=",header"}}if(this.footerCfg||this.footer===true){this.elements+=",footer";delete this.footer}if(this.buttons){this.elements+=",footer";var c=this.buttons;this.buttons=[];for(var b=0,a=c.length;b<a;b++){if(c[b].render){this.buttons.push(c[b])}else{if(c[b].xtype){this.buttons.push(Ext.create(c[b],"button"))}else{this.addButton(c[b])}}}}if(this.fbar){this.elements+=",footer"}if(this.autoLoad){this.on("render",this.doAutoLoad,this,{delay:10})}},createElement:function(a,c){if(this[a]){c.appendChild(this[a].dom);return}if(a==="bwrap"||this.elements.indexOf(a)!=-1){if(this[a+"Cfg"]){this[a]=Ext.fly(c).createChild(this[a+"Cfg"])}else{var b=document.createElement("div");b.className=this[a+"Cls"];this[a]=Ext.get(c.appendChild(b))}if(this[a+"CssClass"]){this[a].addClass(this[a+"CssClass"])}if(this[a+"Style"]){this[a].applyStyles(this[a+"Style"])}}},onRender:function(f,e){Ext.Panel.superclass.onRender.call(this,f,e);this.createClasses();var a=this.el,h=a.dom,j;a.addClass(this.baseCls);if(h.firstChild){this.header=a.down("."+this.headerCls);this.bwrap=a.down("."+this.bwrapCls);var i=this.bwrap?this.bwrap:a;this.tbar=i.down("."+this.tbarCls);this.body=i.down("."+this.bodyCls);this.bbar=i.down("."+this.bbarCls);this.footer=i.down("."+this.footerCls);this.fromMarkup=true}if(this.preventBodyReset===true){a.addClass("x-panel-reset")}if(this.cls){a.addClass(this.cls)}if(this.buttons){this.elements+=",footer"}if(this.frame){a.insertHtml("afterBegin",String.format(Ext.Element.boxMarkup,this.baseCls));this.createElement("header",h.firstChild.firstChild.firstChild);this.createElement("bwrap",h);j=this.bwrap.dom;var c=h.childNodes[1],b=h.childNodes[2];j.appendChild(c);j.appendChild(b);var k=j.firstChild.firstChild.firstChild;this.createElement("tbar",k);this.createElement("body",k);this.createElement("bbar",k);this.createElement("footer",j.lastChild.firstChild.firstChild);if(!this.footer){this.bwrap.dom.lastChild.className+=" x-panel-nofooter"}}else{this.createElement("header",h);this.createElement("bwrap",h);j=this.bwrap.dom;this.createElement("tbar",j);this.createElement("body",j);this.createElement("bbar",j);this.createElement("footer",j);if(!this.header){this.body.addClass(this.bodyCls+"-noheader");if(this.tbar){this.tbar.addClass(this.tbarCls+"-noheader")}}}if(this.padding!==undefined){this.body.setStyle("padding",this.body.addUnits(this.padding))}if(this.border===false){this.el.addClass(this.baseCls+"-noborder");this.body.addClass(this.bodyCls+"-noborder");if(this.header){this.header.addClass(this.headerCls+"-noborder")}if(this.footer){this.footer.addClass(this.footerCls+"-noborder")}if(this.tbar){this.tbar.addClass(this.tbarCls+"-noborder")}if(this.bbar){this.bbar.addClass(this.bbarCls+"-noborder")}}if(this.bodyBorder===false){this.body.addClass(this.bodyCls+"-noborder")}this.bwrap.enableDisplayMode("block");if(this.header){this.header.unselectable();if(this.headerAsText){this.header.dom.innerHTML='<span class="'+this.headerTextCls+'">'+this.header.dom.innerHTML+"</span>";if(this.iconCls){this.setIconClass(this.iconCls)}}}if(this.floating){this.makeFloating(this.floating)}if(this.collapsible){this.tools=this.tools?this.tools.slice(0):[];if(!this.hideCollapseTool){this.tools[this.collapseFirst?"unshift":"push"]({id:"toggle",handler:this.toggleCollapse,scope:this})}if(this.titleCollapse&&this.header){this.mon(this.header,"click",this.toggleCollapse,this);this.header.setStyle("cursor","pointer")}}if(this.tools){var g=this.tools;this.tools={};this.addTool.apply(this,g)}else{this.tools={}}if(this.buttons&&this.buttons.length>0){this.fbar=new Ext.Toolbar({items:this.buttons,toolbarCls:"x-panel-fbar"})}this.toolbars=[];if(this.fbar){this.fbar=Ext.create(this.fbar,"toolbar");this.fbar.enableOverflow=false;if(this.fbar.items){this.fbar.items.each(function(d){d.minWidth=d.minWidth||this.minButtonWidth},this)}this.fbar.toolbarCls="x-panel-fbar";var l=this.footer.createChild({cls:"x-panel-btns x-panel-btns-"+this.buttonAlign});this.fbar.ownerCt=this;this.fbar.render(l);l.createChild({cls:"x-clear"});this.toolbars.push(this.fbar)}if(this.tbar&&this.topToolbar){if(Ext.isArray(this.topToolbar)){this.topToolbar=new Ext.Toolbar(this.topToolbar)}else{if(!this.topToolbar.events){this.topToolbar=Ext.create(this.topToolbar,"toolbar")}}this.topToolbar.ownerCt=this;this.topToolbar.render(this.tbar);this.toolbars.push(this.topToolbar)}if(this.bbar&&this.bottomToolbar){if(Ext.isArray(this.bottomToolbar)){this.bottomToolbar=new Ext.Toolbar(this.bottomToolbar)}else{if(!this.bottomToolbar.events){this.bottomToolbar=Ext.create(this.bottomToolbar,"toolbar")}}this.bottomToolbar.ownerCt=this;this.bottomToolbar.render(this.bbar);this.toolbars.push(this.bottomToolbar)}Ext.each(this.toolbars,function(d){d.on({scope:this,afterlayout:this.syncHeight,remove:this.syncHeight})},this)},setIconClass:function(b){var a=this.iconCls;this.iconCls=b;if(this.rendered&&this.header){if(this.frame){this.header.addClass("x-panel-icon");this.header.replaceClass(a,this.iconCls)}else{var d=this.header.dom;var c=d.firstChild&&String(d.firstChild.tagName).toLowerCase()=="img"?d.firstChild:null;if(c){Ext.fly(c).replaceClass(a,this.iconCls)}else{Ext.DomHelper.insertBefore(d.firstChild,{tag:"img",src:Ext.BLANK_IMAGE_URL,cls:"x-panel-inline-icon "+this.iconCls})}}}this.fireEvent("iconchange",this,b,a)},makeFloating:function(a){this.floating=true;this.el=new Ext.Layer(Ext.isObject(a)?a:{shadow:this.shadow!==undefined?this.shadow:"sides",shadowOffset:this.shadowOffset,constrain:false,shim:this.shim===false?false:undefined},this.el)},getTopToolbar:function(){return this.topToolbar},getBottomToolbar:function(){return this.bottomToolbar},addButton:function(a,d,c){var e={handler:d,scope:c,minWidth:this.minButtonWidth,hideParent:true};if(typeof a=="string"){e.text=a}else{Ext.apply(e,a)}var b=new Ext.Button(e);if(!this.buttons){this.buttons=[]}this.buttons.push(b);return b},addTool:function(){if(!this[this.toolTarget]){return}if(!this.toolTemplate){var g=new Ext.Template('<div class="x-tool x-tool-{id}">&#160;</div>');g.disableFormats=true;g.compile();Ext.Panel.prototype.toolTemplate=g}for(var f=0,d=arguments,c=d.length;f<c;f++){var b=d[f];if(!this.tools[b.id]){var h="x-tool-"+b.id+"-over";var e=this.toolTemplate.insertFirst((b.align!=="left")?this[this.toolTarget]:this[this.toolTarget].child("span"),b,true);this.tools[b.id]=e;e.enableDisplayMode("block");this.mon(e,"click",this.createToolHandler(e,b,h,this));if(b.on){this.mon(e,b.on)}if(b.hidden){e.hide()}if(b.qtip){if(Ext.isObject(b.qtip)){Ext.QuickTips.register(Ext.apply({target:e.id},b.qtip))}else{e.dom.qtip=b.qtip}}e.addClassOnOver(h)}}},onLayout:function(){if(this.toolbars.length>0){this.duringLayout=true;Ext.each(this.toolbars,function(a){a.doLayout()});delete this.duringLayout;this.syncHeight()}},syncHeight:function(){if(!(this.autoHeight||this.duringLayout)){var d=this.lastSize;if(d&&!Ext.isEmpty(d.height)){var b=d.height,c=this.el.getHeight();if(b!="auto"&&b!=c){var e=this.body,a=e.getHeight();c=Math.max(a+b-c,0);if(a>0&&a!=c){e.setHeight(c);if(Ext.isIE&&c<=0){return}var f=e.getSize();this.fireEvent("bodyresize",f.width,f.height)}}}}},onShow:function(){if(this.floating){return this.el.show()}Ext.Panel.superclass.onShow.call(this)},onHide:function(){if(this.floating){return this.el.hide()}Ext.Panel.superclass.onHide.call(this)},createToolHandler:function(c,a,d,b){return function(f){c.removeClass(d);if(a.stopEvent!==false){f.stopEvent()}if(a.handler){a.handler.call(a.scope||c,f,c,b,a)}}},afterRender:function(){if(this.floating&&!this.hidden){this.el.show()}if(this.title){this.setTitle(this.title)}this.setAutoScroll();if(this.html){this.body.update(Ext.isObject(this.html)?Ext.DomHelper.markup(this.html):this.html);delete this.html}if(this.contentEl){var a=Ext.getDom(this.contentEl);Ext.fly(a).removeClass(["x-hidden","x-hide-display"]);this.body.dom.appendChild(a)}if(this.collapsed){this.collapsed=false;this.collapse(false)}Ext.Panel.superclass.afterRender.call(this);this.initEvents()},setAutoScroll:function(){if(this.rendered&&this.autoScroll){var a=this.body||this.el;if(a){a.setOverflow("auto")}}},getKeyMap:function(){if(!this.keyMap){this.keyMap=new Ext.KeyMap(this.el,this.keys)}return this.keyMap},initEvents:function(){if(this.keys){this.getKeyMap()}if(this.draggable){this.initDraggable()}},initDraggable:function(){this.dd=new Ext.Panel.DD(this,typeof this.draggable=="boolean"?null:this.draggable)},beforeEffect:function(){if(this.floating){this.el.beforeAction()}this.el.addClass("x-panel-animated")},afterEffect:function(){this.syncShadow();this.el.removeClass("x-panel-animated")},createEffect:function(c,b,d){var e={scope:d,block:true};if(c===true){e.callback=b;return e}else{if(!c.callback){e.callback=b}else{e.callback=function(){b.call(d);Ext.callback(c.callback,c.scope)}}}return Ext.applyIf(e,c)},collapse:function(b){if(this.collapsed||this.el.hasFxBlock()||this.fireEvent("beforecollapse",this,b)===false){return}var a=b===true||(b!==false&&this.animCollapse);this.beforeEffect();this.onCollapse(a,b);return this},onCollapse:function(a,b){if(a){this[this.collapseEl].slideOut(this.slideAnchor,Ext.apply(this.createEffect(b||true,this.afterCollapse,this),this.collapseDefaults))}else{this[this.collapseEl].hide();this.afterCollapse()}},afterCollapse:function(){this.collapsed=true;this.el.addClass(this.collapsedCls);this.afterEffect();this.fireEvent("collapse",this)},expand:function(b){if(!this.collapsed||this.el.hasFxBlock()||this.fireEvent("beforeexpand",this,b)===false){return}var a=b===true||(b!==false&&this.animCollapse);this.el.removeClass(this.collapsedCls);this.beforeEffect();this.onExpand(a,b);return this},onExpand:function(a,b){if(a){this[this.collapseEl].slideIn(this.slideAnchor,Ext.apply(this.createEffect(b||true,this.afterExpand,this),this.expandDefaults))}else{this[this.collapseEl].show();this.afterExpand()}},afterExpand:function(){this.collapsed=false;this.afterEffect();if(this.deferLayout!==undefined){this.doLayout(true)}this.fireEvent("expand",this)},toggleCollapse:function(a){this[this.collapsed?"expand":"collapse"](a);return this},onDisable:function(){if(this.rendered&&this.maskDisabled){this.el.mask()}Ext.Panel.superclass.onDisable.call(this)},onEnable:function(){if(this.rendered&&this.maskDisabled){this.el.unmask()}Ext.Panel.superclass.onEnable.call(this)},onResize:function(b,c){if(b!==undefined||c!==undefined){if(!this.collapsed){if(typeof b=="number"){b=this.adjustBodyWidth(b-this.getFrameWidth());if(this.tbar){this.tbar.setWidth(b);if(this.topToolbar){this.topToolbar.setSize(b)}}if(this.bbar){this.bbar.setWidth(b);if(this.bottomToolbar){this.bottomToolbar.setSize(b)}}if(this.fbar){var d=this.fbar,e=1,a=Ext.isStrict;if(this.buttonAlign=="left"){e=b-d.container.getFrameWidth("lr")}else{if(Ext.isIE||Ext.isWebKit){if(!(this.buttonAlign=="center"&&Ext.isWebKit)&&(!a||(!Ext.isIE8&&a))){(function(){d.setWidth(d.getEl().child(".x-toolbar-ct").getWidth())}).defer(1)}else{e="auto"}}else{e="auto"}}d.setWidth(e)}this.body.setWidth(b)}else{if(b=="auto"){this.body.setWidth(b)}}if(typeof c=="number"){c=Math.max(0,this.adjustBodyHeight(c-this.getFrameHeight()));this.body.setHeight(c)}else{if(c=="auto"){this.body.setHeight(c)}}if(this.disabled&&this.el._mask){this.el._mask.setSize(this.el.dom.clientWidth,this.el.getHeight())}}else{this.queuedBodySize={width:b,height:c};if(!this.queuedExpand&&this.allowQueuedExpand!==false){this.queuedExpand=true;this.on("expand",function(){delete this.queuedExpand;this.onResize(this.queuedBodySize.width,this.queuedBodySize.height);this.doLayout()},this,{single:true})}}this.fireEvent("bodyresize",this,b,c)}this.syncShadow()},adjustBodyHeight:function(a){return a},adjustBodyWidth:function(a){return a},onPosition:function(){this.syncShadow()},getFrameWidth:function(){var b=this.el.getFrameWidth("lr")+this.bwrap.getFrameWidth("lr");if(this.frame){var a=this.bwrap.dom.firstChild;b+=(Ext.fly(a).getFrameWidth("l")+Ext.fly(a.firstChild).getFrameWidth("r"));var c=this.bwrap.dom.firstChild.firstChild.firstChild;b+=Ext.fly(c).getFrameWidth("lr")}return b},getFrameHeight:function(){var a=this.el.getFrameWidth("tb")+this.bwrap.getFrameWidth("tb");a+=(this.tbar?this.tbar.getHeight():0)+(this.bbar?this.bbar.getHeight():0);if(this.frame){var c=this.el.dom.firstChild;var d=this.bwrap.dom.lastChild;a+=(c.offsetHeight+d.offsetHeight);var b=this.bwrap.dom.firstChild.firstChild.firstChild;a+=Ext.fly(b).getFrameWidth("tb")}else{a+=(this.header?this.header.getHeight():0)+(this.footer?this.footer.getHeight():0)}return a},getInnerWidth:function(){return this.getSize().width-this.getFrameWidth()},getInnerHeight:function(){return this.getSize().height-this.getFrameHeight()},syncShadow:function(){if(this.floating){this.el.sync(true)}},getLayoutTarget:function(){return this.body},setTitle:function(b,a){this.title=b;if(this.header&&this.headerAsText){this.header.child("span").update(b)}if(a){this.setIconClass(a)}this.fireEvent("titlechange",this,b);return this},getUpdater:function(){return this.body.getUpdater()},load:function(){var a=this.body.getUpdater();a.update.apply(a,arguments);return this},beforeDestroy:function(){if(this.header){this.header.removeAllListeners();if(this.headerAsText){Ext.Element.uncache(this.header.child("span"))}}Ext.Element.uncache(this.header,this.tbar,this.bbar,this.footer,this.body,this.bwrap);if(this.tools){for(var c in this.tools){Ext.destroy(this.tools[c])}}if(this.buttons){for(var a in this.buttons){Ext.destroy(this.buttons[a])}}Ext.destroy(this.toolbars);Ext.Panel.superclass.beforeDestroy.call(this)},createClasses:function(){this.headerCls=this.baseCls+"-header";this.headerTextCls=this.baseCls+"-header-text";this.bwrapCls=this.baseCls+"-bwrap";this.tbarCls=this.baseCls+"-tbar";this.bodyCls=this.baseCls+"-body";this.bbarCls=this.baseCls+"-bbar";this.footerCls=this.baseCls+"-footer"},createGhost:function(a,e,b){var d=document.createElement("div");d.className="x-panel-ghost "+(a?a:"");if(this.header){d.appendChild(this.el.dom.firstChild.cloneNode(true))}Ext.fly(d.appendChild(document.createElement("ul"))).setHeight(this.bwrap.getHeight());d.style.width=this.el.dom.offsetWidth+"px";if(!b){this.container.dom.appendChild(d)}else{Ext.getDom(b).appendChild(d)}if(e!==false&&this.el.useShim!==false){var c=new Ext.Layer({shadow:false,useDisplay:true,constrain:false},d);c.show();return c}else{return new Ext.Element(d)}},doAutoLoad:function(){var a=this.body.getUpdater();if(this.renderer){a.setRenderer(this.renderer)}a.update(Ext.isObject(this.autoLoad)?this.autoLoad:{url:this.autoLoad})},getTool:function(a){return this.tools[a]}});Ext.reg("panel",Ext.Panel);Ext.Editor=function(b,a){if(b.field){this.field=Ext.create(b.field,"textfield");a=Ext.apply({},b);delete a.field}else{this.field=b}Ext.Editor.superclass.constructor.call(this,a)};Ext.extend(Ext.Editor,Ext.Component,{value:"",alignment:"c-c?",shadow:"frame",constrain:false,swallowKeys:true,completeOnEnter:false,cancelOnEsc:false,updateEl:false,initComponent:function(){Ext.Editor.superclass.initComponent.call(this);this.addEvents("beforestartedit","startedit","beforecomplete","complete","canceledit","specialkey")},onRender:function(b,a){this.el=new Ext.Layer({shadow:this.shadow,cls:"x-editor",parentEl:b,shim:this.shim,shadowOffset:this.shadowOffset||4,id:this.id,constrain:this.constrain});if(this.zIndex){this.el.setZIndex(this.zIndex)}this.el.setStyle("overflow",Ext.isGecko?"auto":"hidden");if(this.field.msgTarget!="title"){this.field.msgTarget="qtip"}this.field.inEditor=true;this.field.render(this.el);if(Ext.isGecko){this.field.el.dom.setAttribute("autocomplete","off")}this.mon(this.field,"specialkey",this.onSpecialKey,this);if(this.swallowKeys){this.field.el.swallowEvent(["keydown","keypress"])}this.field.show();this.mon(this.field,"blur",this.onBlur,this);if(this.field.grow){this.mon(this.field,"autosize",this.el.sync,this.el,{delay:1})}},onSpecialKey:function(c,b){var a=b.getKey();if(this.completeOnEnter&&a==b.ENTER){b.stopEvent();this.completeEdit()}else{if(this.cancelOnEsc&&a==b.ESC){this.cancelEdit()}else{this.fireEvent("specialkey",c,b)}}if(this.field.triggerBlur&&(a==b.ENTER||a==b.ESC||a==b.TAB)){this.field.triggerBlur()}},startEdit:function(b,c){if(this.editing){this.completeEdit()}this.boundEl=Ext.get(b);var a=c!==undefined?c:this.boundEl.dom.innerHTML;if(!this.rendered){this.render(this.parentEl||document.body)}if(this.fireEvent("beforestartedit",this,this.boundEl,a)===false){return}this.startValue=a;this.field.setValue(a);this.doAutoSize();this.el.alignTo(this.boundEl,this.alignment);this.editing=true;this.show()},doAutoSize:function(){if(this.autoSize){var a=this.boundEl.getSize();switch(this.autoSize){case"width":this.setSize(a.width,"");break;case"height":this.setSize("",a.height);break;default:this.setSize(a.width,a.height)}}},setSize:function(a,b){delete this.field.lastSize;this.field.setSize(a,b);if(this.el){if(Ext.isGecko2||Ext.isOpera){this.el.setSize(a,b)}this.el.sync()}},realign:function(){this.el.alignTo(this.boundEl,this.alignment)},completeEdit:function(a){if(!this.editing){return}var b=this.getValue();if(!this.field.isValid()){if(this.revertInvalid!==false){this.cancelEdit(a)}return}if(String(b)===String(this.startValue)&&this.ignoreNoChange){this.hideEdit(a);return}if(this.fireEvent("beforecomplete",this,b,this.startValue)!==false){b=this.getValue();if(this.updateEl&&this.boundEl){this.boundEl.update(b)}this.hideEdit(a);this.fireEvent("complete",this,b,this.startValue)}},onShow:function(){this.el.show();if(this.hideEl!==false){this.boundEl.hide()}this.field.show();if(Ext.isIE&&!this.fixIEFocus){this.fixIEFocus=true;this.deferredFocus.defer(50,this)}else{this.field.focus()}this.fireEvent("startedit",this.boundEl,this.startValue)},deferredFocus:function(){if(this.editing){this.field.focus()}},cancelEdit:function(a){if(this.editing){var b=this.getValue();this.setValue(this.startValue);this.hideEdit(a);this.fireEvent("canceledit",this,b,this.startValue)}},hideEdit:function(a){if(a!==true){this.editing=false;this.hide()}},onBlur:function(){if(this.allowBlur!==true&&this.editing){this.completeEdit()}},onHide:function(){if(this.editing){this.completeEdit();return}this.field.blur();if(this.field.collapse){this.field.collapse()}this.el.hide();if(this.hideEl!==false){this.boundEl.show()}},setValue:function(a){this.field.setValue(a)},getValue:function(){return this.field.getValue()},beforeDestroy:function(){Ext.destroy(this.field);this.field=null}});Ext.reg("editor",Ext.Editor);Ext.ColorPalette=function(a){Ext.ColorPalette.superclass.constructor.call(this,a);this.addEvents("select");if(this.handler){this.on("select",this.handler,this.scope,true)}};Ext.extend(Ext.ColorPalette,Ext.Component,{itemCls:"x-color-palette",value:null,clickEvent:"click",ctype:"Ext.ColorPalette",allowReselect:false,colors:["000000","993300","333300","003300","003366","000080","333399","333333","800000","FF6600","808000","008000","008080","0000FF","666699","808080","FF0000","FF9900","99CC00","339966","33CCCC","3366FF","800080","969696","FF00FF","FFCC00","FFFF00","00FF00","00FFFF","00CCFF","993366","C0C0C0","FF99CC","FFCC99","FFFF99","CCFFCC","CCFFFF","99CCFF","CC99FF","FFFFFF"],onRender:function(b,a){var c=this.tpl||new Ext.XTemplate('<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>');var d=document.createElement("div");d.id=this.getId();d.className=this.itemCls;c.overwrite(d,this.colors);b.dom.insertBefore(d,a);this.el=Ext.get(d);this.mon(this.el,this.clickEvent,this.handleClick,this,{delegate:"a"});if(this.clickEvent!="click"){this.mon(this.el,"click",Ext.emptyFn,this,{delegate:"a",preventDefault:true})}},afterRender:function(){Ext.ColorPalette.superclass.afterRender.call(this);if(this.value){var a=this.value;this.value=null;this.select(a)}},handleClick:function(b,a){b.preventDefault();if(!this.disabled){var d=a.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];this.select(d.toUpperCase())}},select:function(a){a=a.replace("#","");if(a!=this.value||this.allowReselect){var b=this.el;if(this.value){b.child("a.color-"+this.value).removeClass("x-color-palette-sel")}b.child("a.color-"+a).addClass("x-color-palette-sel");this.value=a;this.fireEvent("select",this,a)}}});Ext.reg("colorpalette",Ext.ColorPalette);Ext.DatePicker=Ext.extend(Ext.BoxComponent,{todayText:"Today",okText:"&#160;OK&#160;",cancelText:"Cancel",todayTip:"{0} (Spacebar)",minText:"This date is before the minimum date",maxText:"This date is after the maximum date",format:"m/d/y",disabledDaysText:"Disabled",disabledDatesText:"Disabled",monthNames:Date.monthNames,dayNames:Date.dayNames,nextText:"Next Month (Control+Right)",prevText:"Previous Month (Control+Left)",monthYearText:"Choose a month (Control+Up/Down to move years)",startDay:0,showToday:true,initComponent:function(){Ext.DatePicker.superclass.initComponent.call(this);this.value=this.value?this.value.clearTime():new Date().clearTime();this.addEvents("select");if(this.handler){this.on("select",this.handler,this.scope||this)}this.initDisabledDays()},initDisabledDays:function(){if(!this.disabledDatesRE&&this.disabledDates){var b=this.disabledDates,a=b.length-1,c="(?:";Ext.each(b,function(f,e){c+=Ext.isDate(f)?"^"+Ext.escapeRe(f.dateFormat(this.format))+"$":b[e];if(e!=a){c+="|"}},this);this.disabledDatesRE=new RegExp(c+")")}},setDisabledDates:function(a){if(Ext.isArray(a)){this.disabledDates=a;this.disabledDatesRE=null}else{this.disabledDatesRE=a}this.initDisabledDays();this.update(this.value,true)},setDisabledDays:function(a){this.disabledDays=a;this.update(this.value,true)},setMinDate:function(a){this.minDate=a;this.update(this.value,true)},setMaxDate:function(a){this.maxDate=a;this.update(this.value,true)},setValue:function(b){var a=this.value;this.value=b.clearTime(true);if(this.el){this.update(this.value)}},getValue:function(){return this.value},focus:function(){if(this.el){this.update(this.activeDate)}},onEnable:function(a){Ext.DatePicker.superclass.onEnable.call(this);this.doDisabled(false);this.update(a?this.value:this.activeDate);if(Ext.isIE){this.el.repaint()}},onDisable:function(){Ext.DatePicker.superclass.onDisable.call(this);this.doDisabled(true);if(Ext.isIE&&!Ext.isIE8){Ext.each([].concat(this.textNodes,this.el.query("th span")),function(a){Ext.fly(a).repaint()})}},doDisabled:function(a){this.keyNav.setDisabled(a);this.prevRepeater.setDisabled(a);this.nextRepeater.setDisabled(a);if(this.showToday){this.todayKeyListener.setDisabled(a);this.todayBtn.setDisabled(a)}},onRender:function(e,b){var a=['<table cellspacing="0">','<tr><td class="x-date-left"><a href="#" title="',this.prevText,'">&#160;</a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="',this.nextText,'">&#160;</a></td></tr>','<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],c=this.dayNames,g;for(g=0;g<7;g++){var j=this.startDay+g;if(j>6){j=j-7}a.push("<th><span>",c[j].substr(0,1),"</span></th>")}a[a.length]="</tr></thead><tbody><tr>";for(g=0;g<42;g++){if(g%7===0&&g!==0){a[a.length]="</tr><tr>"}a[a.length]='<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>'}a.push("</tr></tbody></table></td></tr>",this.showToday?'<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>':"",'</table><div class="x-date-mp"></div>');var h=document.createElement("div");h.className="x-date-picker";h.innerHTML=a.join("");e.dom.insertBefore(h,b);this.el=Ext.get(h);this.eventEl=Ext.get(h.firstChild);this.prevRepeater=new Ext.util.ClickRepeater(this.el.child("td.x-date-left a"),{handler:this.showPrevMonth,scope:this,preventDefault:true,stopDefault:true});this.nextRepeater=new Ext.util.ClickRepeater(this.el.child("td.x-date-right a"),{handler:this.showNextMonth,scope:this,preventDefault:true,stopDefault:true});this.monthPicker=this.el.down("div.x-date-mp");this.monthPicker.enableDisplayMode("block");this.keyNav=new Ext.KeyNav(this.eventEl,{left:function(d){if(d.ctrlKey){this.showPrevMonth()}else{this.update(this.activeDate.add("d",-1))}},right:function(d){if(d.ctrlKey){this.showNextMonth()}else{this.update(this.activeDate.add("d",1))}},up:function(d){if(d.ctrlKey){this.showNextYear()}else{this.update(this.activeDate.add("d",-7))}},down:function(d){if(d.ctrlKey){this.showPrevYear()}else{this.update(this.activeDate.add("d",7))}},pageUp:function(d){this.showNextMonth()},pageDown:function(d){this.showPrevMonth()},enter:function(d){d.stopPropagation();return true},scope:this});this.el.unselectable();this.cells=this.el.select("table.x-date-inner tbody td");this.textNodes=this.el.query("table.x-date-inner tbody span");this.mbtn=new Ext.Button({text:"&#160;",tooltip:this.monthYearText,renderTo:this.el.child("td.x-date-middle",true)});this.mbtn.el.child("em").addClass("x-btn-arrow");if(this.showToday){this.todayKeyListener=this.eventEl.addKeyListener(Ext.EventObject.SPACE,this.selectToday,this);var f=(new Date()).dateFormat(this.format);this.todayBtn=new Ext.Button({renderTo:this.el.child("td.x-date-bottom",true),text:String.format(this.todayText,f),tooltip:String.format(this.todayTip,f),handler:this.selectToday,scope:this})}this.mon(this.eventEl,"mousewheel",this.handleMouseWheel,this);this.mon(this.eventEl,"click",this.handleDateClick,this,{delegate:"a.x-date-date"});this.mon(this.mbtn,"click",this.showMonthPicker,this);this.onEnable(true)},createMonthPicker:function(){if(!this.monthPicker.dom.firstChild){var a=['<table border="0" cellspacing="0">'];for(var b=0;b<6;b++){a.push('<tr><td class="x-date-mp-month"><a href="#">',Date.getShortMonthName(b),"</a></td>",'<td class="x-date-mp-month x-date-mp-sep"><a href="#">',Date.getShortMonthName(b+6),"</a></td>",b===0?'<td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-prev"></a></td><td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-next"></a></td></tr>':'<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>')}a.push('<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',this.okText,'</button><button type="button" class="x-date-mp-cancel">',this.cancelText,"</button></td></tr>","</table>");this.monthPicker.update(a.join(""));this.mon(this.monthPicker,"click",this.onMonthClick,this);this.mon(this.monthPicker,"dblclick",this.onMonthDblClick,this);this.mpMonths=this.monthPicker.select("td.x-date-mp-month");this.mpYears=this.monthPicker.select("td.x-date-mp-year");this.mpMonths.each(function(c,d,e){e+=1;if((e%2)===0){c.dom.xmonth=5+Math.round(e*0.5)}else{c.dom.xmonth=Math.round((e-1)*0.5)}})}},showMonthPicker:function(){if(!this.disabled){this.createMonthPicker();var a=this.el.getSize();this.monthPicker.setSize(a);this.monthPicker.child("table").setSize(a);this.mpSelMonth=(this.activeDate||this.value).getMonth();this.updateMPMonth(this.mpSelMonth);this.mpSelYear=(this.activeDate||this.value).getFullYear();this.updateMPYear(this.mpSelYear);this.monthPicker.slideIn("t",{duration:0.2})}},updateMPYear:function(e){this.mpyear=e;var c=this.mpYears.elements;for(var b=1;b<=10;b++){var d=c[b-1],a;if((b%2)===0){a=e+Math.round(b*0.5);d.firstChild.innerHTML=a;d.xyear=a}else{a=e-(5-Math.round(b*0.5));d.firstChild.innerHTML=a;d.xyear=a}this.mpYears.item(b-1)[a==this.mpSelYear?"addClass":"removeClass"]("x-date-mp-sel")}},updateMPMonth:function(a){this.mpMonths.each(function(b,c,d){b[b.dom.xmonth==a?"addClass":"removeClass"]("x-date-mp-sel")})},selectMPMonth:function(a){},onMonthClick:function(f,b){f.stopEvent();var c=new Ext.Element(b),a;if(c.is("button.x-date-mp-cancel")){this.hideMonthPicker()}else{if(c.is("button.x-date-mp-ok")){var g=new Date(this.mpSelYear,this.mpSelMonth,(this.activeDate||this.value).getDate());if(g.getMonth()!=this.mpSelMonth){g=new Date(this.mpSelYear,this.mpSelMonth,1).getLastDateOfMonth()}this.update(g);this.hideMonthPicker()}else{if((a=c.up("td.x-date-mp-month",2))){this.mpMonths.removeClass("x-date-mp-sel");a.addClass("x-date-mp-sel");this.mpSelMonth=a.dom.xmonth}else{if((a=c.up("td.x-date-mp-year",2))){this.mpYears.removeClass("x-date-mp-sel");a.addClass("x-date-mp-sel");this.mpSelYear=a.dom.xyear}else{if(c.is("a.x-date-mp-prev")){this.updateMPYear(this.mpyear-10)}else{if(c.is("a.x-date-mp-next")){this.updateMPYear(this.mpyear+10)}}}}}}},onMonthDblClick:function(d,b){d.stopEvent();var c=new Ext.Element(b),a;if((a=c.up("td.x-date-mp-month",2))){this.update(new Date(this.mpSelYear,a.dom.xmonth,(this.activeDate||this.value).getDate()));this.hideMonthPicker()}else{if((a=c.up("td.x-date-mp-year",2))){this.update(new Date(a.dom.xyear,this.mpSelMonth,(this.activeDate||this.value).getDate()));this.hideMonthPicker()}}},hideMonthPicker:function(a){if(this.monthPicker){if(a===true){this.monthPicker.hide()}else{this.monthPicker.slideOut("t",{duration:0.2})}}},showPrevMonth:function(a){this.update(this.activeDate.add("mo",-1))},showNextMonth:function(a){this.update(this.activeDate.add("mo",1))},showPrevYear:function(){this.update(this.activeDate.add("y",-1))},showNextYear:function(){this.update(this.activeDate.add("y",1))},handleMouseWheel:function(a){a.stopEvent();if(!this.disabled){var b=a.getWheelDelta();if(b>0){this.showPrevMonth()}else{if(b<0){this.showNextMonth()}}}},handleDateClick:function(b,a){b.stopEvent();if(!this.disabled&&a.dateValue&&!Ext.fly(a.parentNode).hasClass("x-date-disabled")){this.setValue(new Date(a.dateValue));this.fireEvent("select",this,this.value)}},selectToday:function(){if(this.todayBtn&&!this.todayBtn.disabled){this.setValue(new Date().clearTime());this.fireEvent("select",this,this.value)}},update:function(G,A){var a=this.activeDate,o=this.isVisible();this.activeDate=G;if(!A&&a&&this.el){var n=G.getTime();if(a.getMonth()==G.getMonth()&&a.getFullYear()==G.getFullYear()){this.cells.removeClass("x-date-selected");this.cells.each(function(d){if(d.dom.firstChild.dateValue==n){d.addClass("x-date-selected");if(o){Ext.fly(d.dom.firstChild).focus(50)}return false}});return}}var j=G.getDaysInMonth();var p=G.getFirstDateOfMonth();var f=p.getDay()-this.startDay;if(f<=this.startDay){f+=7}var B=G.add("mo",-1);var g=B.getDaysInMonth()-f;var e=this.cells.elements;var q=this.textNodes;j+=f;var y=86400000;var D=(new Date(B.getFullYear(),B.getMonth(),g)).clearTime();var C=new Date().clearTime().getTime();var u=G.clearTime().getTime();var s=this.minDate?this.minDate.clearTime():Number.NEGATIVE_INFINITY;var x=this.maxDate?this.maxDate.clearTime():Number.POSITIVE_INFINITY;var F=this.disabledDatesRE;var r=this.disabledDatesText;var I=this.disabledDays?this.disabledDays.join(""):false;var E=this.disabledDaysText;var z=this.format;if(this.showToday){var l=new Date().clearTime();var c=(l<s||l>x||(F&&z&&F.test(l.dateFormat(z)))||(I&&I.indexOf(l.getDay())!=-1));if(!this.disabled){this.todayBtn.setDisabled(c);this.todayKeyListener[c?"disable":"enable"]()}}var k=function(J,d){d.title="";var i=D.getTime();d.firstChild.dateValue=i;if(i==C){d.className+=" x-date-today";d.title=J.todayText}if(i==u){d.className+=" x-date-selected";if(o){Ext.fly(d.firstChild).focus(50)}}if(i<s){d.className=" x-date-disabled";d.title=J.minText;return}if(i>x){d.className=" x-date-disabled";d.title=J.maxText;return}if(I){if(I.indexOf(D.getDay())!=-1){d.title=E;d.className=" x-date-disabled"}}if(F&&z){var w=D.dateFormat(z);if(F.test(w)){d.title=r.replace("%0",w);d.className=" x-date-disabled"}}};var v=0;for(;v<f;v++){q[v].innerHTML=(++g);D.setDate(D.getDate()+1);e[v].className="x-date-prevday";k(this,e[v])}for(;v<j;v++){var b=v-f+1;q[v].innerHTML=(b);D.setDate(D.getDate()+1);e[v].className="x-date-active";k(this,e[v])}var H=0;for(;v<42;v++){q[v].innerHTML=(++H);D.setDate(D.getDate()+1);e[v].className="x-date-nextday";k(this,e[v])}this.mbtn.setText(this.monthNames[G.getMonth()]+" "+G.getFullYear());if(!this.internalRender){var h=this.el.dom.firstChild;var m=h.offsetWidth;this.el.setWidth(m+this.el.getBorderWidth("lr"));Ext.fly(h).setWidth(m);this.internalRender=true;if(Ext.isOpera&&!this.secondPass){h.rows[0].cells[1].style.width=(m-(h.rows[0].cells[0].offsetWidth+h.rows[0].cells[2].offsetWidth))+"px";this.secondPass=true;this.update.defer(10,this,[G])}}},beforeDestroy:function(){if(this.rendered){this.keyNav.disable();this.keyNav=null;Ext.destroy(this.leftClickRpt,this.rightClickRpt,this.monthPicker,this.eventEl,this.mbtn,this.todayBtn)}}});Ext.reg("datepicker",Ext.DatePicker);Ext.LoadMask=function(c,b){this.el=Ext.get(c);Ext.apply(this,b);if(this.store){this.store.on("beforeload",this.onBeforeLoad,this);this.store.on("load",this.onLoad,this);this.store.on("exception",this.onLoad,this);this.removeMask=Ext.value(this.removeMask,false)}else{var a=this.el.getUpdater();a.showLoadIndicator=false;a.on("beforeupdate",this.onBeforeLoad,this);a.on("update",this.onLoad,this);a.on("failure",this.onLoad,this);this.removeMask=Ext.value(this.removeMask,true)}};Ext.LoadMask.prototype={msg:"Loading...",msgCls:"x-mask-loading",disabled:false,disable:function(){this.disabled=true},enable:function(){this.disabled=false},onLoad:function(){this.el.unmask(this.removeMask)},onBeforeLoad:function(){if(!this.disabled){this.el.mask(this.msg,this.msgCls)}},show:function(){this.onBeforeLoad()},hide:function(){this.onLoad()},destroy:function(){if(this.store){this.store.un("beforeload",this.onBeforeLoad,this);this.store.un("load",this.onLoad,this);this.store.un("exception",this.onLoad,this)}else{var a=this.el.getUpdater();a.un("beforeupdate",this.onBeforeLoad,this);a.un("update",this.onLoad,this);a.un("failure",this.onLoad,this)}}};Ext.Slider=Ext.extend(Ext.BoxComponent,{vertical:false,minValue:0,maxValue:100,decimalPrecision:0,keyIncrement:1,increment:0,clickRange:[5,15],clickToChange:true,animate:true,dragging:false,initComponent:function(){if(!Ext.isDefined(this.value)){this.value=this.minValue}Ext.Slider.superclass.initComponent.call(this);this.keyIncrement=Math.max(this.increment,this.keyIncrement);this.addEvents("beforechange","change","changecomplete","dragstart","drag","dragend");if(this.vertical){Ext.apply(this,Ext.Slider.Vertical)}},onRender:function(){this.autoEl={cls:"x-slider "+(this.vertical?"x-slider-vert":"x-slider-horz"),cn:{cls:"x-slider-end",cn:{cls:"x-slider-inner",cn:[{cls:"x-slider-thumb"},{tag:"a",cls:"x-slider-focus",href:"#",tabIndex:"-1",hidefocus:"on"}]}}};Ext.Slider.superclass.onRender.apply(this,arguments);this.endEl=this.el.first();this.innerEl=this.endEl.first();this.thumb=this.innerEl.first();this.halfThumb=(this.vertical?this.thumb.getHeight():this.thumb.getWidth())/2;this.focusEl=this.thumb.next();this.initEvents()},initEvents:function(){this.thumb.addClassOnOver("x-slider-thumb-over");this.mon(this.el,{scope:this,mousedown:this.onMouseDown,keydown:this.onKeyDown});this.focusEl.swallowEvent("click",true);this.tracker=new Ext.dd.DragTracker({onBeforeStart:this.onBeforeDragStart.createDelegate(this),onStart:this.onDragStart.createDelegate(this),onDrag:this.onDrag.createDelegate(this),onEnd:this.onDragEnd.createDelegate(this),tolerance:3,autoStart:300});this.tracker.initEl(this.thumb);this.on("beforedestroy",this.tracker.destroy,this.tracker)},onMouseDown:function(b){if(this.disabled){return}if(this.clickToChange&&b.target!=this.thumb.dom){var a=this.innerEl.translatePoints(b.getXY());this.onClickChange(a)}this.focus()},onClickChange:function(a){if(a.top>this.clickRange[0]&&a.top<this.clickRange[1]){this.setValue(Ext.util.Format.round(this.reverseValue(a.left),this.decimalPrecision),undefined,true)}},onKeyDown:function(b){if(this.disabled){b.preventDefault();return}var a=b.getKey();switch(a){case b.UP:case b.RIGHT:b.stopEvent();if(b.ctrlKey){this.setValue(this.maxValue,undefined,true)}else{this.setValue(this.value+this.keyIncrement,undefined,true)}break;case b.DOWN:case b.LEFT:b.stopEvent();if(b.ctrlKey){this.setValue(this.minValue,undefined,true)}else{this.setValue(this.value-this.keyIncrement,undefined,true)}break;default:b.preventDefault()}},doSnap:function(b){if(!this.increment||this.increment==1||!b){return b}var d=b,c=this.increment;var a=b%c;if(a!=0){d-=a;if(a*2>c){d+=c}else{if(a*2<-c){d-=c}}}return d.constrain(this.minValue,this.maxValue)},afterRender:function(){Ext.Slider.superclass.afterRender.apply(this,arguments);if(this.value!==undefined){var a=this.normalizeValue(this.value);if(a!==this.value){delete this.value;this.setValue(a,false)}else{this.moveThumb(this.translateValue(a),false)}}},getRatio:function(){var a=this.innerEl.getWidth();var b=this.maxValue-this.minValue;return b==0?a:(a/b)},normalizeValue:function(a){a=this.doSnap(a);a=Ext.util.Format.round(a,this.decimalPrecision);a=a.constrain(this.minValue,this.maxValue);return a},setValue:function(b,a,c){b=this.normalizeValue(b);if(b!==this.value&&this.fireEvent("beforechange",this,b,this.value)!==false){this.value=b;this.moveThumb(this.translateValue(b),a!==false);this.fireEvent("change",this,b);if(c){this.fireEvent("changecomplete",this,b)}}},translateValue:function(a){var b=this.getRatio();return(a*b)-(this.minValue*b)-this.halfThumb},reverseValue:function(b){var a=this.getRatio();return(b+this.halfThumb+(this.minValue*a))/a},moveThumb:function(b,a){if(!a||this.animate===false){this.thumb.setLeft(b)}else{this.thumb.shift({left:b,stopFx:true,duration:0.35})}},focus:function(){this.focusEl.focus(10)},onBeforeDragStart:function(a){return !this.disabled},onDragStart:function(a){this.thumb.addClass("x-slider-thumb-drag");this.dragging=true;this.dragStartValue=this.value;this.fireEvent("dragstart",this,a)},onDrag:function(a){var b=this.innerEl.translatePoints(this.tracker.getXY());this.setValue(Ext.util.Format.round(this.reverseValue(b.left),this.decimalPrecision),false);this.fireEvent("drag",this,a)},onDragEnd:function(a){this.thumb.removeClass("x-slider-thumb-drag");this.dragging=false;this.fireEvent("dragend",this,a);if(this.dragStartValue!=this.value){this.fireEvent("changecomplete",this,this.value)}},onResize:function(a,b){this.innerEl.setWidth(a-(this.el.getPadding("l")+this.endEl.getPadding("r")));this.syncThumb()},onDisable:function(){Ext.Slider.superclass.onDisable.call(this);this.thumb.addClass(this.disabledClass);if(Ext.isIE){var a=this.thumb.getXY();this.thumb.hide();this.innerEl.addClass(this.disabledClass).dom.disabled=true;if(!this.thumbHolder){this.thumbHolder=this.endEl.createChild({cls:"x-slider-thumb "+this.disabledClass})}this.thumbHolder.show().setXY(a)}},onEnable:function(){Ext.Slider.superclass.onEnable.call(this);this.thumb.removeClass(this.disabledClass);if(Ext.isIE){this.innerEl.removeClass(this.disabledClass).dom.disabled=false;if(this.thumbHolder){this.thumbHolder.hide()}this.thumb.show();this.syncThumb()}},syncThumb:function(){if(this.rendered){this.moveThumb(this.translateValue(this.value))}},getValue:function(){return this.value}});Ext.reg("slider",Ext.Slider);Ext.Slider.Vertical={onResize:function(a,b){this.innerEl.setHeight(b-(this.el.getPadding("t")+this.endEl.getPadding("b")));this.syncThumb()},getRatio:function(){var b=this.innerEl.getHeight();var a=this.maxValue-this.minValue;return b/a},moveThumb:function(b,a){if(!a||this.animate===false){this.thumb.setBottom(b)}else{this.thumb.shift({bottom:b,stopFx:true,duration:0.35})}},onDrag:function(b){var c=this.innerEl.translatePoints(this.tracker.getXY());var a=this.innerEl.getHeight()-c.top;this.setValue(this.minValue+Ext.util.Format.round(a/this.getRatio(),this.decimalPrecision),false);this.fireEvent("drag",this,b)},onClickChange:function(b){if(b.left>this.clickRange[0]&&b.left<this.clickRange[1]){var a=this.innerEl.getHeight()-b.top;this.setValue(this.minValue+Ext.util.Format.round(a/this.getRatio(),this.decimalPrecision),undefined,true)}}};Ext.ProgressBar=Ext.extend(Ext.BoxComponent,{baseCls:"x-progress",animate:false,waitTimer:null,initComponent:function(){Ext.ProgressBar.superclass.initComponent.call(this);this.addEvents("update")},onRender:function(d,a){var c=new Ext.Template('<div class="{cls}-wrap">','<div class="{cls}-inner">','<div class="{cls}-bar">','<div class="{cls}-text">',"<div>&#160;</div>","</div>","</div>",'<div class="{cls}-text {cls}-text-back">',"<div>&#160;</div>","</div>","</div>","</div>");this.el=a?c.insertBefore(a,{cls:this.baseCls},true):c.append(d,{cls:this.baseCls},true);if(this.id){this.el.dom.id=this.id}var b=this.el.dom.firstChild;this.progressBar=Ext.get(b.firstChild);if(this.textEl){this.textEl=Ext.get(this.textEl);delete this.textTopEl}else{this.textTopEl=Ext.get(this.progressBar.dom.firstChild);var e=Ext.get(b.childNodes[1]);this.textTopEl.setStyle("z-index",99).addClass("x-hidden");this.textEl=new Ext.CompositeElement([this.textTopEl.dom.firstChild,e.dom.firstChild]);this.textEl.setWidth(b.offsetWidth)}this.progressBar.setHeight(b.offsetHeight)},afterRender:function(){Ext.ProgressBar.superclass.afterRender.call(this);if(this.value){this.updateProgress(this.value,this.text)}else{this.updateText(this.text)}},updateProgress:function(c,d,b){this.value=c||0;if(d){this.updateText(d)}if(this.rendered){var a=Math.floor(c*this.el.dom.firstChild.offsetWidth);this.progressBar.setWidth(a,b===true||(b!==false&&this.animate));if(this.textTopEl){this.textTopEl.removeClass("x-hidden").setWidth(a)}}this.fireEvent("update",this,c,d);return this},wait:function(b){if(!this.waitTimer){var a=this;b=b||{};this.updateText(b.text);this.waitTimer=Ext.TaskMgr.start({run:function(c){var d=b.increment||10;this.updateProgress(((((c+d)%d)+1)*(100/d))*0.01,null,b.animate)},interval:b.interval||1000,duration:b.duration,onStop:function(){if(b.fn){b.fn.apply(b.scope||this)}this.reset()},scope:a})}return this},isWaiting:function(){return this.waitTimer!==null},updateText:function(a){this.text=a||"&#160;";if(this.rendered){this.textEl.update(this.text)}return this},syncProgressBar:function(){if(this.value){this.updateProgress(this.value,this.text)}return this},setSize:function(a,c){Ext.ProgressBar.superclass.setSize.call(this,a,c);if(this.textTopEl){var b=this.el.dom.firstChild;this.textEl.setSize(b.offsetWidth,b.offsetHeight)}this.syncProgressBar();return this},reset:function(a){this.updateProgress(0);if(this.textTopEl){this.textTopEl.addClass("x-hidden")}if(this.waitTimer){this.waitTimer.onStop=null;Ext.TaskMgr.stop(this.waitTimer);this.waitTimer=null}if(a===true){this.hide()}return this}});Ext.reg("progress",Ext.ProgressBar);
@@ -0,0 +1,3853 @@
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.data.Api
9
+ * @extends Object
10
+ * Ext.data.Api is a singleton designed to manage the data API including methods
11
+ * for validating a developer's DataProxy API. Defines variables for CRUD actions
12
+ * create, read, update and destroy in addition to a mapping of RESTful HTTP methods
13
+ * GET, POST, PUT and DELETE to CRUD actions.
14
+ * @singleton
15
+ */
16
+ Ext.data.Api = (function() {
17
+
18
+ // private validActions. validActions is essentially an inverted hash of Ext.data.Api.actions, where value becomes the key.
19
+ // Some methods in this singleton (e.g.: getActions, getVerb) will loop through actions with the code <code>for (var verb in this.actions)</code>
20
+ // For efficiency, some methods will first check this hash for a match. Those methods which do acces validActions will cache their result here.
21
+ // We cannot pre-define this hash since the developer may over-ride the actions at runtime.
22
+ var validActions = {};
23
+
24
+ return {
25
+ /**
26
+ * Defined actions corresponding to remote actions:
27
+ * <pre><code>
28
+ actions: {
29
+ create : 'create', // Text representing the remote-action to create records on server.
30
+ read : 'read', // Text representing the remote-action to read/load data from server.
31
+ update : 'update', // Text representing the remote-action to update records on server.
32
+ destroy : 'destroy' // Text representing the remote-action to destroy records on server.
33
+ }
34
+ * </code></pre>
35
+ * @property actions
36
+ * @type Object
37
+ */
38
+ actions : {
39
+ create : 'create',
40
+ read : 'read',
41
+ update : 'update',
42
+ destroy : 'destroy'
43
+ },
44
+
45
+ /**
46
+ * Defined {CRUD action}:{HTTP method} pairs to associate HTTP methods with the
47
+ * corresponding actions for {@link Ext.data.DataProxy#restful RESTful proxies}.
48
+ * Defaults to:
49
+ * <pre><code>
50
+ restActions : {
51
+ create : 'POST',
52
+ read : 'GET',
53
+ update : 'PUT',
54
+ destroy : 'DELETE'
55
+ },
56
+ * </code></pre>
57
+ */
58
+ restActions : {
59
+ create : 'POST',
60
+ read : 'GET',
61
+ update : 'PUT',
62
+ destroy : 'DELETE'
63
+ },
64
+
65
+ /**
66
+ * Returns true if supplied action-name is a valid API action defined in <code>{@link #actions}</code> constants
67
+ * @param {String} action
68
+ * @param {String[]}(Optional) List of available CRUD actions. Pass in list when executing multiple times for efficiency.
69
+ * @return {Boolean}
70
+ */
71
+ isAction : function(action) {
72
+ return (Ext.data.Api.actions[action]) ? true : false;
73
+ },
74
+
75
+ /**
76
+ * Returns the actual CRUD action KEY "create", "read", "update" or "destroy" from the supplied action-name. This method is used internally and shouldn't generally
77
+ * need to be used directly. The key/value pair of Ext.data.Api.actions will often be identical but this is not necessarily true. A developer can override this naming
78
+ * convention if desired. However, the framework internally calls methods based upon the KEY so a way of retreiving the the words "create", "read", "update" and "destroy" is
79
+ * required. This method will cache discovered KEYS into the private validActions hash.
80
+ * @param {String} name The runtime name of the action.
81
+ * @return {String||null} returns the action-key, or verb of the user-action or null if invalid.
82
+ * @nodoc
83
+ */
84
+ getVerb : function(name) {
85
+ if (validActions[name]) {
86
+ return validActions[name]; // <-- found in cache. return immediately.
87
+ }
88
+ for (var verb in this.actions) {
89
+ if (this.actions[verb] === name) {
90
+ validActions[name] = verb;
91
+ break;
92
+ }
93
+ }
94
+ return (validActions[name] !== undefined) ? validActions[name] : null;
95
+ },
96
+
97
+ /**
98
+ * Returns true if the supplied API is valid; that is, check that all keys match defined actions
99
+ * otherwise returns an array of mistakes.
100
+ * @return {String[]||true}
101
+ */
102
+ isValid : function(api){
103
+ var invalid = [];
104
+ var crud = this.actions; // <-- cache a copy of the actions.
105
+ for (var action in api) {
106
+ if (!(action in crud)) {
107
+ invalid.push(action);
108
+ }
109
+ }
110
+ return (!invalid.length) ? true : invalid;
111
+ },
112
+
113
+ /**
114
+ * Returns true if the supplied verb upon the supplied proxy points to a unique url in that none of the other api-actions
115
+ * point to the same url. The question is important for deciding whether to insert the "xaction" HTTP parameter within an
116
+ * Ajax request. This method is used internally and shouldn't generally need to be called directly.
117
+ * @param {Ext.data.DataProxy} proxy
118
+ * @param {String} verb
119
+ * @return {Boolean}
120
+ */
121
+ hasUniqueUrl : function(proxy, verb) {
122
+ var url = (proxy.api[verb]) ? proxy.api[verb].url : null;
123
+ var unique = true;
124
+ for (var action in proxy.api) {
125
+ if ((unique = (action === verb) ? true : (proxy.api[action].url != url) ? true : false) === false) {
126
+ break;
127
+ }
128
+ }
129
+ return unique;
130
+ },
131
+
132
+ /**
133
+ * This method is used internally by <tt>{@link Ext.data.DataProxy DataProxy}</tt> and should not generally need to be used directly.
134
+ * Each action of a DataProxy api can be initially defined as either a String or an Object. When specified as an object,
135
+ * one can explicitly define the HTTP method (GET|POST) to use for each CRUD action. This method will prepare the supplied API, setting
136
+ * each action to the Object form. If your API-actions do not explicitly define the HTTP method, the "method" configuration-parameter will
137
+ * be used. If the method configuration parameter is not specified, POST will be used.
138
+ <pre><code>
139
+ new Ext.data.HttpProxy({
140
+ method: "POST", // <-- default HTTP method when not specified.
141
+ api: {
142
+ create: 'create.php',
143
+ load: 'read.php',
144
+ save: 'save.php',
145
+ destroy: 'destroy.php'
146
+ }
147
+ });
148
+
149
+ // Alternatively, one can use the object-form to specify the API
150
+ new Ext.data.HttpProxy({
151
+ api: {
152
+ load: {url: 'read.php', method: 'GET'},
153
+ create: 'create.php',
154
+ destroy: 'destroy.php',
155
+ save: 'update.php'
156
+ }
157
+ });
158
+ </code></pre>
159
+ *
160
+ * @param {Ext.data.DataProxy} proxy
161
+ */
162
+ prepare : function(proxy) {
163
+ if (!proxy.api) {
164
+ proxy.api = {}; // <-- No api? create a blank one.
165
+ }
166
+ for (var verb in this.actions) {
167
+ var action = this.actions[verb];
168
+ proxy.api[action] = proxy.api[action] || proxy.url || proxy.directFn;
169
+ if (typeof(proxy.api[action]) == 'string') {
170
+ proxy.api[action] = {
171
+ url: proxy.api[action]
172
+ };
173
+ }
174
+ }
175
+ },
176
+
177
+ /**
178
+ * Prepares a supplied Proxy to be RESTful. Sets the HTTP method for each api-action to be one of
179
+ * GET, POST, PUT, DELETE according to the defined {@link #restActions}.
180
+ * @param {Ext.data.DataProxy} proxy
181
+ */
182
+ restify : function(proxy) {
183
+ proxy.restful = true;
184
+ for (var verb in this.restActions) {
185
+ proxy.api[this.actions[verb]].method = this.restActions[verb];
186
+ }
187
+ }
188
+ };
189
+ })();
190
+
191
+ /**
192
+ * @class Ext.data.Api.Error
193
+ * @extends Ext.Error
194
+ * Error class for Ext.data.Api errors
195
+ */
196
+ Ext.data.Api.Error = Ext.extend(Ext.Error, {
197
+ constructor : function(message, arg) {
198
+ this.arg = arg;
199
+ Ext.Error.call(this, message);
200
+ },
201
+ name: 'Ext.data.Api'
202
+ });
203
+ Ext.apply(Ext.data.Api.Error.prototype, {
204
+ lang: {
205
+ 'action-url-undefined': 'No fallback url defined for this action. When defining a DataProxy api, please be sure to define an url for each CRUD action in Ext.data.Api.actions or define a default url in addition to your api-configuration.',
206
+ 'invalid': 'received an invalid API-configuration. Please ensure your proxy API-configuration contains only the actions defined in Ext.data.Api.actions',
207
+ 'invalid-url': 'Invalid url. Please review your proxy configuration.',
208
+ 'execute': 'Attempted to execute an unknown action. Valid API actions are defined in Ext.data.Api.actions"'
209
+ }
210
+ });
211
+
212
+ /**
213
+ * @class Ext.data.SortTypes
214
+ * @singleton
215
+ * Defines the default sorting (casting?) comparison functions used when sorting data.
216
+ */
217
+ Ext.data.SortTypes = {
218
+ /**
219
+ * Default sort that does nothing
220
+ * @param {Mixed} s The value being converted
221
+ * @return {Mixed} The comparison value
222
+ */
223
+ none : function(s){
224
+ return s;
225
+ },
226
+
227
+ /**
228
+ * The regular expression used to strip tags
229
+ * @type {RegExp}
230
+ * @property
231
+ */
232
+ stripTagsRE : /<\/?[^>]+>/gi,
233
+
234
+ /**
235
+ * Strips all HTML tags to sort on text only
236
+ * @param {Mixed} s The value being converted
237
+ * @return {String} The comparison value
238
+ */
239
+ asText : function(s){
240
+ return String(s).replace(this.stripTagsRE, "");
241
+ },
242
+
243
+ /**
244
+ * Strips all HTML tags to sort on text only - Case insensitive
245
+ * @param {Mixed} s The value being converted
246
+ * @return {String} The comparison value
247
+ */
248
+ asUCText : function(s){
249
+ return String(s).toUpperCase().replace(this.stripTagsRE, "");
250
+ },
251
+
252
+ /**
253
+ * Case insensitive string
254
+ * @param {Mixed} s The value being converted
255
+ * @return {String} The comparison value
256
+ */
257
+ asUCString : function(s) {
258
+ return String(s).toUpperCase();
259
+ },
260
+
261
+ /**
262
+ * Date sorting
263
+ * @param {Mixed} s The value being converted
264
+ * @return {Number} The comparison value
265
+ */
266
+ asDate : function(s) {
267
+ if(!s){
268
+ return 0;
269
+ }
270
+ if(Ext.isDate(s)){
271
+ return s.getTime();
272
+ }
273
+ return Date.parse(String(s));
274
+ },
275
+
276
+ /**
277
+ * Float sorting
278
+ * @param {Mixed} s The value being converted
279
+ * @return {Float} The comparison value
280
+ */
281
+ asFloat : function(s) {
282
+ var val = parseFloat(String(s).replace(/,/g, ""));
283
+ return isNaN(val) ? 0 : val;
284
+ },
285
+
286
+ /**
287
+ * Integer sorting
288
+ * @param {Mixed} s The value being converted
289
+ * @return {Number} The comparison value
290
+ */
291
+ asInt : function(s) {
292
+ var val = parseInt(String(s).replace(/,/g, ""), 10);
293
+ return isNaN(val) ? 0 : val;
294
+ }
295
+ };/**
296
+ * @class Ext.data.Record
297
+ * <p>Instances of this class encapsulate both Record <em>definition</em> information, and Record
298
+ * <em>value</em> information for use in {@link Ext.data.Store} objects, or any code which needs
299
+ * to access Records cached in an {@link Ext.data.Store} object.</p>
300
+ * <p>Constructors for this class are generated by passing an Array of field definition objects to {@link #create}.
301
+ * Instances are usually only created by {@link Ext.data.Reader} implementations when processing unformatted data
302
+ * objects.</p>
303
+ * <p>Note that an instance of a Record class may only belong to one {@link Ext.data.Store Store} at a time.
304
+ * In order to copy data from one Store to another, use the {@link #copy} method to create an exact
305
+ * copy of the Record, and insert the new instance into the other Store.</p>
306
+ * <p>When serializing a Record for submission to the server, be aware that it contains many private
307
+ * properties, and also a reference to its owning Store which in turn holds references to its Records.
308
+ * This means that a whole Record may not be encoded using {@link Ext.util.JSON.encode}. Instead, use the
309
+ * <code>{@link #data}</code> and <code>{@link #id}</code> properties.</p>
310
+ * <p>Record objects generated by this constructor inherit all the methods of Ext.data.Record listed below.</p>
311
+ * @constructor
312
+ * This constructor should not be used to create Record objects. Instead, use {@link #create} to
313
+ * generate a subclass of Ext.data.Record configured with information about its constituent fields.
314
+ * @param {Object} data (Optional) An object, the properties of which provide values for the new Record's
315
+ * fields. If not specified the <code>{@link Ext.data.Field#defaultValue defaultValue}</code>
316
+ * for each field will be assigned.
317
+ * @param {Object} id (Optional) The id of the Record. This id should be unique, and is used by the
318
+ * {@link Ext.data.Store} object which owns the Record to index its collection of Records. If
319
+ * an <code>id</code> is not specified a <b><code>{@link #phantom}</code></b> Record will be created
320
+ * with an {@link #Record.id automatically generated id}.
321
+ */
322
+ Ext.data.Record = function(data, id){
323
+ // if no id, call the auto id method
324
+ this.id = (id || id === 0) ? id : Ext.data.Record.id(this);
325
+ this.data = data || {};
326
+ };
327
+
328
+ /**
329
+ * Generate a constructor for a specific Record layout.
330
+ * @param {Array} o An Array of <b>{@link Ext.data.Field Field}</b> definition objects.
331
+ * The constructor generated by this method may be used to create new Record instances. The data
332
+ * object must contain properties named after the {@link Ext.data.Field field}
333
+ * <b><tt>{@link Ext.data.Field#name}s</tt></b>. Example usage:<pre><code>
334
+ // create a Record constructor from a description of the fields
335
+ var TopicRecord = Ext.data.Record.create([ // creates a subclass of Ext.data.Record
336
+ {{@link Ext.data.Field#name name}: 'title', {@link Ext.data.Field#mapping mapping}: 'topic_title'},
337
+ {name: 'author', mapping: 'username', allowBlank: false},
338
+ {name: 'totalPosts', mapping: 'topic_replies', type: 'int'},
339
+ {name: 'lastPost', mapping: 'post_time', type: 'date'},
340
+ {name: 'lastPoster', mapping: 'user2'},
341
+ {name: 'excerpt', mapping: 'post_text', allowBlank: false},
342
+ // In the simplest case, if no properties other than <tt>name</tt> are required,
343
+ // a field definition may consist of just a String for the field name.
344
+ 'signature'
345
+ ]);
346
+
347
+ // create Record instance
348
+ var myNewRecord = new TopicRecord(
349
+ {
350
+ title: 'Do my job please',
351
+ author: 'noobie',
352
+ totalPosts: 1,
353
+ lastPost: new Date(),
354
+ lastPoster: 'Animal',
355
+ excerpt: 'No way dude!',
356
+ signature: ''
357
+ },
358
+ id // optionally specify the id of the record otherwise {@link #Record.id one is auto-assigned}
359
+ );
360
+ myStore.{@link Ext.data.Store#add add}(myNewRecord);
361
+ </code></pre>
362
+ * @method create
363
+ * @return {function} A constructor which is used to create new Records according
364
+ * to the definition. The constructor has the same signature as {@link #Ext.data.Record}.
365
+ * @static
366
+ */
367
+ Ext.data.Record.create = function(o){
368
+ var f = Ext.extend(Ext.data.Record, {});
369
+ var p = f.prototype;
370
+ p.fields = new Ext.util.MixedCollection(false, function(field){
371
+ return field.name;
372
+ });
373
+ for(var i = 0, len = o.length; i < len; i++){
374
+ p.fields.add(new Ext.data.Field(o[i]));
375
+ }
376
+ f.getField = function(name){
377
+ return p.fields.get(name);
378
+ };
379
+ return f;
380
+ };
381
+
382
+ Ext.data.Record.PREFIX = 'ext-record';
383
+ Ext.data.Record.AUTO_ID = 1;
384
+ Ext.data.Record.EDIT = 'edit';
385
+ Ext.data.Record.REJECT = 'reject';
386
+ Ext.data.Record.COMMIT = 'commit';
387
+
388
+
389
+ /**
390
+ * Generates a sequential id. This method is typically called when a record is {@link #create}d
391
+ * and {@link #Record no id has been specified}. The returned id takes the form:
392
+ * <tt>&#123;PREFIX}-&#123;AUTO_ID}</tt>.<div class="mdetail-params"><ul>
393
+ * <li><b><tt>PREFIX</tt></b> : String<p class="sub-desc"><tt>Ext.data.Record.PREFIX</tt>
394
+ * (defaults to <tt>'ext-record'</tt>)</p></li>
395
+ * <li><b><tt>AUTO_ID</tt></b> : String<p class="sub-desc"><tt>Ext.data.Record.AUTO_ID</tt>
396
+ * (defaults to <tt>1</tt> initially)</p></li>
397
+ * </ul></div>
398
+ * @param {Record} rec The record being created. The record does not exist, it's a {@link #phantom}.
399
+ * @return {String} auto-generated string id, <tt>"ext-record-i++'</tt>;
400
+ */
401
+ Ext.data.Record.id = function(rec) {
402
+ rec.phantom = true;
403
+ return [Ext.data.Record.PREFIX, '-', Ext.data.Record.AUTO_ID++].join('');
404
+ };
405
+
406
+ Ext.data.Record.prototype = {
407
+ /**
408
+ * <p><b>This property is stored in the Record definition's <u>prototype</u></b></p>
409
+ * A MixedCollection containing the defined {@link Ext.data.Field Field}s for this Record. Read-only.
410
+ * @property fields
411
+ * @type Ext.util.MixedCollection
412
+ */
413
+ /**
414
+ * An object hash representing the data for this Record. Every field name in the Record definition
415
+ * is represented by a property of that name in this object. Note that unless you specified a field
416
+ * with {@link Ext.data.Field#name name} "id" in the Record definition, this will <b>not</b> contain
417
+ * an <tt>id</tt> property.
418
+ * @property data
419
+ * @type {Object}
420
+ */
421
+ /**
422
+ * The unique ID of the Record {@link #Record as specified at construction time}.
423
+ * @property id
424
+ * @type {Object}
425
+ */
426
+ /**
427
+ * Readonly flag - true if this Record has been modified.
428
+ * @type Boolean
429
+ */
430
+ dirty : false,
431
+ editing : false,
432
+ error: null,
433
+ /**
434
+ * This object contains a key and value storing the original values of all modified
435
+ * fields or is null if no fields have been modified.
436
+ * @property modified
437
+ * @type {Object}
438
+ */
439
+ modified: null,
440
+ /**
441
+ * <tt>false</tt> when the record does not yet exist in a server-side database (see
442
+ * {@link #markDirty}). Any record which has a real database pk set as its id property
443
+ * is NOT a phantom -- it's real.
444
+ * @property phantom
445
+ * @type {Boolean}
446
+ */
447
+ phantom : false,
448
+
449
+ // private
450
+ join : function(store){
451
+ /**
452
+ * The {@link Ext.data.Store} to which this Record belongs.
453
+ * @property store
454
+ * @type {Ext.data.Store}
455
+ */
456
+ this.store = store;
457
+ },
458
+
459
+ /**
460
+ * Set the {@link Ext.data.Field#name named field} to the specified value. For example:
461
+ * <pre><code>
462
+ // record has a field named 'firstname'
463
+ var Employee = Ext.data.Record.{@link #create}([
464
+ {name: 'firstname'},
465
+ ...
466
+ ]);
467
+
468
+ // update the 2nd record in the store:
469
+ var rec = myStore.{@link Ext.data.Store#getAt getAt}(1);
470
+
471
+ // set the value (shows dirty flag):
472
+ rec.set('firstname', 'Betty');
473
+
474
+ // commit the change (removes dirty flag):
475
+ rec.{@link #commit}();
476
+
477
+ // update the record in the store, bypass setting dirty flag,
478
+ // and do not store the change in the {@link Ext.data.Store#getModifiedRecords modified records}
479
+ rec.{@link #data}['firstname'] = 'Wilma'); // updates record, but not the view
480
+ rec.{@link #commit}(); // updates the view
481
+ * </code></pre>
482
+ * <b>Notes</b>:<div class="mdetail-params"><ul>
483
+ * <li>If the store has a writer and <code>autoSave=true</code>, each set()
484
+ * will execute an XHR to the server.</li>
485
+ * <li>Use <code>{@link #beginEdit}</code> to prevent the store's <code>update</code>
486
+ * event firing while using set().</li>
487
+ * <li>Use <code>{@link #endEdit}</code> to have the store's <code>update</code>
488
+ * event fire.</li>
489
+ * </ul></div>
490
+ * @param {String} name The {@link Ext.data.Field#name name of the field} to set.
491
+ * @param {Object} value The value to set the field to.
492
+ */
493
+ set : function(name, value){
494
+ var isObj = (typeof value === 'object');
495
+ if(!isObj && String(this.data[name]) === String(value)){
496
+ return;
497
+ } else if (isObj && Ext.encode(this.data[name]) === Ext.encode(value)) {
498
+ return;
499
+ }
500
+ this.dirty = true;
501
+ if(!this.modified){
502
+ this.modified = {};
503
+ }
504
+ if(typeof this.modified[name] == 'undefined'){
505
+ this.modified[name] = this.data[name];
506
+ }
507
+ this.data[name] = value;
508
+ if(!this.editing){
509
+ this.afterEdit();
510
+ }
511
+ },
512
+
513
+ // private
514
+ afterEdit: function(){
515
+ if(this.store){
516
+ this.store.afterEdit(this);
517
+ }
518
+ },
519
+
520
+ // private
521
+ afterReject: function(){
522
+ if(this.store){
523
+ this.store.afterReject(this);
524
+ }
525
+ },
526
+
527
+ // private
528
+ afterCommit: function(){
529
+ if(this.store){
530
+ this.store.afterCommit(this);
531
+ }
532
+ },
533
+
534
+ /**
535
+ * Get the value of the {@link Ext.data.Field#name named field}.
536
+ * @param {String} name The {@link Ext.data.Field#name name of the field} to get the value of.
537
+ * @return {Object} The value of the field.
538
+ */
539
+ get : function(name){
540
+ return this.data[name];
541
+ },
542
+
543
+ /**
544
+ * Begin an edit. While in edit mode, no events (e.g.. the <code>update</code> event)
545
+ * are relayed to the containing store.
546
+ * See also: <code>{@link #endEdit}</code> and <code>{@link #cancelEdit}</code>.
547
+ */
548
+ beginEdit : function(){
549
+ this.editing = true;
550
+ this.modified = this.modified || {};
551
+ },
552
+
553
+ /**
554
+ * Cancels all changes made in the current edit operation.
555
+ */
556
+ cancelEdit : function(){
557
+ this.editing = false;
558
+ delete this.modified;
559
+ },
560
+
561
+ /**
562
+ * End an edit. If any data was modified, the containing store is notified
563
+ * (ie, the store's <code>update</code> event will fire).
564
+ */
565
+ endEdit : function(){
566
+ this.editing = false;
567
+ if(this.dirty){
568
+ this.afterEdit();
569
+ }
570
+ },
571
+
572
+ /**
573
+ * Usually called by the {@link Ext.data.Store} which owns the Record.
574
+ * Rejects all changes made to the Record since either creation, or the last commit operation.
575
+ * Modified fields are reverted to their original values.
576
+ * <p>Developers should subscribe to the {@link Ext.data.Store#update} event
577
+ * to have their code notified of reject operations.</p>
578
+ * @param {Boolean} silent (optional) True to skip notification of the owning
579
+ * store of the change (defaults to false)
580
+ */
581
+ reject : function(silent){
582
+ var m = this.modified;
583
+ for(var n in m){
584
+ if(typeof m[n] != "function"){
585
+ this.data[n] = m[n];
586
+ }
587
+ }
588
+ this.dirty = false;
589
+ delete this.modified;
590
+ this.editing = false;
591
+ if(silent !== true){
592
+ this.afterReject();
593
+ }
594
+ },
595
+
596
+ /**
597
+ * Usually called by the {@link Ext.data.Store} which owns the Record.
598
+ * Commits all changes made to the Record since either creation, or the last commit operation.
599
+ * <p>Developers should subscribe to the {@link Ext.data.Store#update} event
600
+ * to have their code notified of commit operations.</p>
601
+ * @param {Boolean} silent (optional) True to skip notification of the owning
602
+ * store of the change (defaults to false)
603
+ */
604
+ commit : function(silent){
605
+ this.dirty = false;
606
+ delete this.modified;
607
+ this.editing = false;
608
+ if(silent !== true){
609
+ this.afterCommit();
610
+ }
611
+ },
612
+
613
+ /**
614
+ * Gets a hash of only the fields that have been modified since this Record was created or commited.
615
+ * @return Object
616
+ */
617
+ getChanges : function(){
618
+ var m = this.modified, cs = {};
619
+ for(var n in m){
620
+ if(m.hasOwnProperty(n)){
621
+ cs[n] = this.data[n];
622
+ }
623
+ }
624
+ return cs;
625
+ },
626
+
627
+ // private
628
+ hasError : function(){
629
+ return this.error !== null;
630
+ },
631
+
632
+ // private
633
+ clearError : function(){
634
+ this.error = null;
635
+ },
636
+
637
+ /**
638
+ * Creates a copy of this Record.
639
+ * @param {String} id (optional) A new Record id, defaults to {@link #Record.id autogenerating an id}.
640
+ * Note: if an <code>id</code> is not specified the copy created will be a
641
+ * <code>{@link #phantom}</code> Record.
642
+ * @return {Record}
643
+ */
644
+ copy : function(newId) {
645
+ return new this.constructor(Ext.apply({}, this.data), newId || this.id);
646
+ },
647
+
648
+ /**
649
+ * Returns <tt>true</tt> if the passed field name has been <code>{@link #modified}</code>
650
+ * since the load or last commit.
651
+ * @param {String} fieldName {@link Ext.data.Field.{@link Ext.data.Field#name}
652
+ * @return {Boolean}
653
+ */
654
+ isModified : function(fieldName){
655
+ return !!(this.modified && this.modified.hasOwnProperty(fieldName));
656
+ },
657
+
658
+ /**
659
+ * By default returns <tt>false</tt> if any {@link Ext.data.Field field} within the
660
+ * record configured with <tt>{@link Ext.data.Field#allowBlank} = false</tt> returns
661
+ * <tt>true</tt> from an {@link Ext}.{@link Ext#isEmpty isempty} test.
662
+ * @return {Boolean}
663
+ */
664
+ isValid : function() {
665
+ return this.fields.find(function(f) {
666
+ return (f.allowBlank === false && Ext.isEmpty(this.data[f.name])) ? true : false;
667
+ },this) ? false : true;
668
+ },
669
+
670
+ /**
671
+ * <p>Marks this <b>Record</b> as <code>{@link #dirty}</code>. This method
672
+ * is used interally when adding <code>{@link #phantom}</code> records to a
673
+ * {@link Ext.data.Store#writer writer enabled store}.</p>
674
+ * <br><p>Marking a record <code>{@link #dirty}</code> causes the phantom to
675
+ * be returned by {@link Ext.data.Store#getModifiedRecords} where it will
676
+ * have a create action composed for it during {@link Ext.data.Store#save store save}
677
+ * operations.</p>
678
+ */
679
+ markDirty : function(){
680
+ this.dirty = true;
681
+ if(!this.modified){
682
+ this.modified = {};
683
+ }
684
+ this.fields.each(function(f) {
685
+ this.modified[f.name] = this.data[f.name];
686
+ },this);
687
+ }
688
+ };/**
689
+ * @class Ext.StoreMgr
690
+ * @extends Ext.util.MixedCollection
691
+ * The default global group of stores.
692
+ * @singleton
693
+ */
694
+ Ext.StoreMgr = Ext.apply(new Ext.util.MixedCollection(), {
695
+ /**
696
+ * @cfg {Object} listeners @hide
697
+ */
698
+
699
+ /**
700
+ * Registers one or more Stores with the StoreMgr. You do not normally need to register stores
701
+ * manually. Any store initialized with a {@link Ext.data.Store#storeId} will be auto-registered.
702
+ * @param {Ext.data.Store} store1 A Store instance
703
+ * @param {Ext.data.Store} store2 (optional)
704
+ * @param {Ext.data.Store} etc... (optional)
705
+ */
706
+ register : function(){
707
+ for(var i = 0, s; (s = arguments[i]); i++){
708
+ this.add(s);
709
+ }
710
+ },
711
+
712
+ /**
713
+ * Unregisters one or more Stores with the StoreMgr
714
+ * @param {String/Object} id1 The id of the Store, or a Store instance
715
+ * @param {String/Object} id2 (optional)
716
+ * @param {String/Object} etc... (optional)
717
+ */
718
+ unregister : function(){
719
+ for(var i = 0, s; (s = arguments[i]); i++){
720
+ this.remove(this.lookup(s));
721
+ }
722
+ },
723
+
724
+ /**
725
+ * Gets a registered Store by id
726
+ * @param {String/Object} id The id of the Store, or a Store instance
727
+ * @return {Ext.data.Store}
728
+ */
729
+ lookup : function(id){
730
+ if(Ext.isArray(id)){
731
+ var fields = ['field1'], expand = !Ext.isArray(id[0]);
732
+ if(!expand){
733
+ for(var i = 2, len = id[0].length; i <= len; ++i){
734
+ fields.push('field' + i);
735
+ }
736
+ }
737
+ return new Ext.data.ArrayStore({
738
+ fields: fields,
739
+ data: id,
740
+ expandData: expand,
741
+ autoDestroy: true,
742
+ autoCreated: true
743
+
744
+ });
745
+ }
746
+ return Ext.isObject(id) ? (id.events ? id : Ext.create(id, 'store')) : this.get(id);
747
+ },
748
+
749
+ // getKey implementation for MixedCollection
750
+ getKey : function(o){
751
+ return o.storeId;
752
+ }
753
+ });/**
754
+ * @class Ext.data.Store
755
+ * @extends Ext.util.Observable
756
+ * <p>The Store class encapsulates a client side cache of {@link Ext.data.Record Record}
757
+ * objects which provide input data for Components such as the {@link Ext.grid.GridPanel GridPanel},
758
+ * the {@link Ext.form.ComboBox ComboBox}, or the {@link Ext.DataView DataView}.</p>
759
+ * <p><u>Retrieving Data</u></p>
760
+ * <p>A Store object may access a data object using:<div class="mdetail-params"><ul>
761
+ * <li>{@link #proxy configured implementation} of {@link Ext.data.DataProxy DataProxy}</li>
762
+ * <li>{@link #data} to automatically pass in data</li>
763
+ * <li>{@link #loadData} to manually pass in data</li>
764
+ * </ul></div></p>
765
+ * <p><u>Reading Data</u></p>
766
+ * <p>A Store object has no inherent knowledge of the format of the data object (it could be
767
+ * an Array, XML, or JSON). A Store object uses an appropriate {@link #reader configured implementation}
768
+ * of a {@link Ext.data.DataReader DataReader} to create {@link Ext.data.Record Record} instances from the data
769
+ * object.</p>
770
+ * <p><u>Store Types</u></p>
771
+ * <p>There are several implementations of Store available which are customized for use with
772
+ * a specific DataReader implementation. Here is an example using an ArrayStore which implicitly
773
+ * creates a reader commensurate to an Array data object.</p>
774
+ * <pre><code>
775
+ var myStore = new Ext.data.ArrayStore({
776
+ fields: ['fullname', 'first'],
777
+ idIndex: 0 // id for each record will be the first element
778
+ });
779
+ * </code></pre>
780
+ * <p>For custom implementations create a basic {@link Ext.data.Store} configured as needed:</p>
781
+ * <pre><code>
782
+ // create a {@link Ext.data.Record Record} constructor:
783
+ var rt = Ext.data.Record.create([
784
+ {name: 'fullname'},
785
+ {name: 'first'}
786
+ ]);
787
+ var myStore = new Ext.data.Store({
788
+ // explicitly create reader
789
+ reader: new Ext.data.ArrayReader(
790
+ {
791
+ idIndex: 0 // id for each record will be the first element
792
+ },
793
+ rt // recordType
794
+ )
795
+ });
796
+ * </code></pre>
797
+ * <p>Load some data into store (note the data object is an array which corresponds to the reader):</p>
798
+ * <pre><code>
799
+ var myData = [
800
+ [1, 'Fred Flintstone', 'Fred'], // note that id for the record is the first element
801
+ [2, 'Barney Rubble', 'Barney']
802
+ ];
803
+ myStore.loadData(myData);
804
+ * </code></pre>
805
+ * <p>Records are cached and made available through accessor functions. An example of adding
806
+ * a record to the store:</p>
807
+ * <pre><code>
808
+ var defaultData = {
809
+ fullname: 'Full Name',
810
+ first: 'First Name'
811
+ };
812
+ var recId = 100; // provide unique id for the record
813
+ var r = new myStore.recordType(defaultData, ++recId); // create new record
814
+ myStore.{@link #insert}(0, r); // insert a new record into the store (also see {@link #add})
815
+ * </code></pre>
816
+ * @constructor
817
+ * Creates a new Store.
818
+ * @param {Object} config A config object containing the objects needed for the Store to access data,
819
+ * and read the data into Records.
820
+ * @xtype store
821
+ */
822
+ Ext.data.Store = function(config){
823
+ this.data = new Ext.util.MixedCollection(false);
824
+ this.data.getKey = function(o){
825
+ return o.id;
826
+ };
827
+ /**
828
+ * See the <code>{@link #baseParams corresponding configuration option}</code>
829
+ * for a description of this property.
830
+ * To modify this property see <code>{@link #setBaseParam}</code>.
831
+ * @property
832
+ */
833
+ this.baseParams = {};
834
+
835
+ // temporary removed-records cache
836
+ this.removed = [];
837
+
838
+ if(config && config.data){
839
+ this.inlineData = config.data;
840
+ delete config.data;
841
+ }
842
+
843
+ Ext.apply(this, config);
844
+
845
+ this.paramNames = Ext.applyIf(this.paramNames || {}, this.defaultParamNames);
846
+
847
+ if(this.url && !this.proxy){
848
+ this.proxy = new Ext.data.HttpProxy({url: this.url});
849
+ }
850
+ // If Store is RESTful, so too is the DataProxy
851
+ if (this.restful === true && this.proxy) {
852
+ // When operating RESTfully, a unique transaction is generated for each record.
853
+ this.batch = false;
854
+ Ext.data.Api.restify(this.proxy);
855
+ }
856
+
857
+ if(this.reader){ // reader passed
858
+ if(!this.recordType){
859
+ this.recordType = this.reader.recordType;
860
+ }
861
+ if(this.reader.onMetaChange){
862
+ this.reader.onMetaChange = this.onMetaChange.createDelegate(this);
863
+ }
864
+ if (this.writer) { // writer passed
865
+ this.writer.meta = this.reader.meta;
866
+ this.pruneModifiedRecords = true;
867
+ }
868
+ }
869
+
870
+ /**
871
+ * The {@link Ext.data.Record Record} constructor as supplied to (or created by) the
872
+ * {@link Ext.data.DataReader Reader}. Read-only.
873
+ * <p>If the Reader was constructed by passing in an Array of {@link Ext.data.Field} definition objects,
874
+ * instead of a Record constructor, it will implicitly create a Record constructor from that Array (see
875
+ * {@link Ext.data.Record}.{@link Ext.data.Record#create create} for additional details).</p>
876
+ * <p>This property may be used to create new Records of the type held in this Store, for example:</p><pre><code>
877
+ // create the data store
878
+ var store = new Ext.data.ArrayStore({
879
+ autoDestroy: true,
880
+ fields: [
881
+ {name: 'company'},
882
+ {name: 'price', type: 'float'},
883
+ {name: 'change', type: 'float'},
884
+ {name: 'pctChange', type: 'float'},
885
+ {name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}
886
+ ]
887
+ });
888
+ store.loadData(myData);
889
+
890
+ // create the Grid
891
+ var grid = new Ext.grid.EditorGridPanel({
892
+ store: store,
893
+ colModel: new Ext.grid.ColumnModel({
894
+ columns: [
895
+ {id:'company', header: 'Company', width: 160, dataIndex: 'company'},
896
+ {header: 'Price', renderer: 'usMoney', dataIndex: 'price'},
897
+ {header: 'Change', renderer: change, dataIndex: 'change'},
898
+ {header: '% Change', renderer: pctChange, dataIndex: 'pctChange'},
899
+ {header: 'Last Updated', width: 85,
900
+ renderer: Ext.util.Format.dateRenderer('m/d/Y'),
901
+ dataIndex: 'lastChange'}
902
+ ],
903
+ defaults: {
904
+ sortable: true,
905
+ width: 75
906
+ }
907
+ }),
908
+ autoExpandColumn: 'company', // match the id specified in the column model
909
+ height:350,
910
+ width:600,
911
+ title:'Array Grid',
912
+ tbar: [{
913
+ text: 'Add Record',
914
+ handler : function(){
915
+ var defaultData = {
916
+ change: 0,
917
+ company: 'New Company',
918
+ lastChange: (new Date()).clearTime(),
919
+ pctChange: 0,
920
+ price: 10
921
+ };
922
+ var recId = 3; // provide unique id
923
+ var p = new store.recordType(defaultData, recId); // create new record
924
+ grid.stopEditing();
925
+ store.{@link #insert}(0, p); // insert a new record into the store (also see {@link #add})
926
+ grid.startEditing(0, 0);
927
+ }
928
+ }]
929
+ });
930
+ * </code></pre>
931
+ * @property recordType
932
+ * @type Function
933
+ */
934
+
935
+ if(this.recordType){
936
+ /**
937
+ * A {@link Ext.util.MixedCollection MixedCollection} containing the defined {@link Ext.data.Field Field}s
938
+ * for the {@link Ext.data.Record Records} stored in this Store. Read-only.
939
+ * @property fields
940
+ * @type Ext.util.MixedCollection
941
+ */
942
+ this.fields = this.recordType.prototype.fields;
943
+ }
944
+ this.modified = [];
945
+
946
+ this.addEvents(
947
+ /**
948
+ * @event datachanged
949
+ * Fires when the data cache has changed in a bulk manner (e.g., it has been sorted, filtered, etc.) and a
950
+ * widget that is using this Store as a Record cache should refresh its view.
951
+ * @param {Store} this
952
+ */
953
+ 'datachanged',
954
+ /**
955
+ * @event metachange
956
+ * Fires when this store's reader provides new metadata (fields). This is currently only supported for JsonReaders.
957
+ * @param {Store} this
958
+ * @param {Object} meta The JSON metadata
959
+ */
960
+ 'metachange',
961
+ /**
962
+ * @event add
963
+ * Fires when Records have been {@link #add}ed to the Store
964
+ * @param {Store} this
965
+ * @param {Ext.data.Record[]} records The array of Records added
966
+ * @param {Number} index The index at which the record(s) were added
967
+ */
968
+ 'add',
969
+ /**
970
+ * @event remove
971
+ * Fires when a Record has been {@link #remove}d from the Store
972
+ * @param {Store} this
973
+ * @param {Ext.data.Record} record The Record that was removed
974
+ * @param {Number} index The index at which the record was removed
975
+ */
976
+ 'remove',
977
+ /**
978
+ * @event update
979
+ * Fires when a Record has been updated
980
+ * @param {Store} this
981
+ * @param {Ext.data.Record} record The Record that was updated
982
+ * @param {String} operation The update operation being performed. Value may be one of:
983
+ * <pre><code>
984
+ Ext.data.Record.EDIT
985
+ Ext.data.Record.REJECT
986
+ Ext.data.Record.COMMIT
987
+ * </code></pre>
988
+ */
989
+ 'update',
990
+ /**
991
+ * @event clear
992
+ * Fires when the data cache has been cleared.
993
+ * @param {Store} this
994
+ */
995
+ 'clear',
996
+ /**
997
+ * @event exception
998
+ * <p>Fires if an exception occurs in the Proxy during a remote request.
999
+ * This event is relayed through the corresponding {@link Ext.data.DataProxy}.
1000
+ * See {@link Ext.data.DataProxy}.{@link Ext.data.DataProxy#exception exception}
1001
+ * for additional details.
1002
+ * @param {misc} misc See {@link Ext.data.DataProxy}.{@link Ext.data.DataProxy#exception exception}
1003
+ * for description.
1004
+ */
1005
+ 'exception',
1006
+ /**
1007
+ * @event beforeload
1008
+ * Fires before a request is made for a new data object. If the beforeload handler returns
1009
+ * <tt>false</tt> the {@link #load} action will be canceled.
1010
+ * @param {Store} this
1011
+ * @param {Object} options The loading options that were specified (see {@link #load} for details)
1012
+ */
1013
+ 'beforeload',
1014
+ /**
1015
+ * @event load
1016
+ * Fires after a new set of Records has been loaded.
1017
+ * @param {Store} this
1018
+ * @param {Ext.data.Record[]} records The Records that were loaded
1019
+ * @param {Object} options The loading options that were specified (see {@link #load} for details)
1020
+ */
1021
+ 'load',
1022
+ /**
1023
+ * @event loadexception
1024
+ * <p>This event is <b>deprecated</b> in favor of the catch-all <b><code>{@link #exception}</code></b>
1025
+ * event instead.</p>
1026
+ * <p>This event is relayed through the corresponding {@link Ext.data.DataProxy}.
1027
+ * See {@link Ext.data.DataProxy}.{@link Ext.data.DataProxy#loadexception loadexception}
1028
+ * for additional details.
1029
+ * @param {misc} misc See {@link Ext.data.DataProxy}.{@link Ext.data.DataProxy#loadexception loadexception}
1030
+ * for description.
1031
+ */
1032
+ 'loadexception',
1033
+ /**
1034
+ * @event beforewrite
1035
+ * @param {DataProxy} this
1036
+ * @param {String} action [Ext.data.Api.actions.create|update|destroy]
1037
+ * @param {Record/Array[Record]} rs
1038
+ * @param {Object} options The loading options that were specified. Edit <code>options.params</code> to add Http parameters to the request. (see {@link #save} for details)
1039
+ * @param {Object} arg The callback's arg object passed to the {@link #request} function
1040
+ */
1041
+ 'beforewrite',
1042
+ /**
1043
+ * @event write
1044
+ * Fires if the server returns 200 after an Ext.data.Api.actions CRUD action.
1045
+ * Success or failure of the action is available in the <code>result['successProperty']</code> property.
1046
+ * The server-code might set the <code>successProperty</code> to <tt>false</tt> if a database validation
1047
+ * failed, for example.
1048
+ * @param {Ext.data.Store} store
1049
+ * @param {String} action [Ext.data.Api.actions.create|update|destroy]
1050
+ * @param {Object} result The 'data' picked-out out of the response for convenience.
1051
+ * @param {Ext.Direct.Transaction} res
1052
+ * @param {Record/Record[]} rs Store's records, the subject(s) of the write-action
1053
+ */
1054
+ 'write'
1055
+ );
1056
+
1057
+ if(this.proxy){
1058
+ this.relayEvents(this.proxy, ['loadexception', 'exception']);
1059
+ }
1060
+ // With a writer set for the Store, we want to listen to add/remove events to remotely create/destroy records.
1061
+ if (this.writer) {
1062
+ this.on({
1063
+ scope: this,
1064
+ add: this.createRecords,
1065
+ remove: this.destroyRecord,
1066
+ update: this.updateRecord
1067
+ });
1068
+ }
1069
+
1070
+ this.sortToggle = {};
1071
+ if(this.sortField){
1072
+ this.setDefaultSort(this.sortField, this.sortDir);
1073
+ }else if(this.sortInfo){
1074
+ this.setDefaultSort(this.sortInfo.field, this.sortInfo.direction);
1075
+ }
1076
+
1077
+ Ext.data.Store.superclass.constructor.call(this);
1078
+
1079
+ if(this.id){
1080
+ this.storeId = this.id;
1081
+ delete this.id;
1082
+ }
1083
+ if(this.storeId){
1084
+ Ext.StoreMgr.register(this);
1085
+ }
1086
+ if(this.inlineData){
1087
+ this.loadData(this.inlineData);
1088
+ delete this.inlineData;
1089
+ }else if(this.autoLoad){
1090
+ this.load.defer(10, this, [
1091
+ typeof this.autoLoad == 'object' ?
1092
+ this.autoLoad : undefined]);
1093
+ }
1094
+ };
1095
+ Ext.extend(Ext.data.Store, Ext.util.Observable, {
1096
+ /**
1097
+ * @cfg {String} storeId If passed, the id to use to register with the <b>{@link Ext.StoreMgr StoreMgr}</b>.
1098
+ * <p><b>Note</b>: if a (deprecated) <tt>{@link #id}</tt> is specified it will supersede the <tt>storeId</tt>
1099
+ * assignment.</p>
1100
+ */
1101
+ /**
1102
+ * @cfg {String} url If a <tt>{@link #proxy}</tt> is not specified the <tt>url</tt> will be used to
1103
+ * implicitly configure a {@link Ext.data.HttpProxy HttpProxy} if an <tt>url</tt> is specified.
1104
+ * Typically this option, or the <code>{@link #data}</code> option will be specified.
1105
+ */
1106
+ /**
1107
+ * @cfg {Boolean/Object} autoLoad If <tt>{@link #data}</tt> is not specified, and if <tt>autoLoad</tt>
1108
+ * is <tt>true</tt> or an <tt>Object</tt>, this store's {@link #load} method is automatically called
1109
+ * after creation. If the value of <tt>autoLoad</tt> is an <tt>Object</tt>, this <tt>Object</tt> will
1110
+ * be passed to the store's {@link #load} method.
1111
+ */
1112
+ /**
1113
+ * @cfg {Ext.data.DataProxy} proxy The {@link Ext.data.DataProxy DataProxy} object which provides
1114
+ * access to a data object. See <code>{@link #url}</code>.
1115
+ */
1116
+ /**
1117
+ * @cfg {Array} data An inline data object readable by the <code>{@link #reader}</code>.
1118
+ * Typically this option, or the <code>{@link #url}</code> option will be specified.
1119
+ */
1120
+ /**
1121
+ * @cfg {Ext.data.DataReader} reader The {@link Ext.data.DataReader Reader} object which processes the
1122
+ * data object and returns an Array of {@link Ext.data.Record} objects which are cached keyed by their
1123
+ * <b><tt>{@link Ext.data.Record#id id}</tt></b> property.
1124
+ */
1125
+ /**
1126
+ * @cfg {Ext.data.DataWriter} writer
1127
+ * <p>The {@link Ext.data.DataWriter Writer} object which processes a record object for being written
1128
+ * to the server-side database.</p>
1129
+ * <br><p>When a writer is installed into a Store the {@link #add}, {@link #remove}, and {@link #update}
1130
+ * events on the store are monitored in order to remotely {@link #createRecords create records},
1131
+ * {@link #destroyRecord destroy records}, or {@link #updateRecord update records}.</p>
1132
+ * <br><p>The proxy for this store will relay any {@link #writexception} events to this store.</p>
1133
+ * <br><p>Sample implementation:
1134
+ * <pre><code>
1135
+ var writer = new {@link Ext.data.JsonWriter}({
1136
+ encode: true,
1137
+ writeAllFields: true // write all fields, not just those that changed
1138
+ });
1139
+
1140
+ // Typical Store collecting the Proxy, Reader and Writer together.
1141
+ var store = new Ext.data.Store({
1142
+ storeId: 'user',
1143
+ root: 'records',
1144
+ proxy: proxy,
1145
+ reader: reader,
1146
+ writer: writer, // <-- plug a DataWriter into the store just as you would a Reader
1147
+ paramsAsHash: true,
1148
+ autoSave: false // <-- false to delay executing create, update, destroy requests
1149
+ // until specifically told to do so.
1150
+ });
1151
+ * </code></pre></p>
1152
+ */
1153
+ writer : undefined,
1154
+ /**
1155
+ * @cfg {Object} baseParams
1156
+ * <p>An object containing properties which are to be sent as parameters
1157
+ * for <i>every</i> HTTP request.</p>
1158
+ * <p>Parameters are encoded as standard HTTP parameters using {@link Ext#urlEncode}.</p>
1159
+ * <p><b>Note</b>: <code>baseParams</code> may be superseded by any <code>params</code>
1160
+ * specified in a <code>{@link #load}</code> request, see <code>{@link #load}</code>
1161
+ * for more details.</p>
1162
+ * This property may be modified after creation using the <code>{@link #setBaseParam}</code>
1163
+ * method.
1164
+ * @property
1165
+ */
1166
+ /**
1167
+ * @cfg {Object} sortInfo A config object to specify the sort order in the request of a Store's
1168
+ * {@link #load} operation. Note that for local sorting, the <tt>direction</tt> property is
1169
+ * case-sensitive. See also {@link #remoteSort} and {@link #paramNames}.
1170
+ * For example:<pre><code>
1171
+ sortInfo: {
1172
+ field: 'fieldName',
1173
+ direction: 'ASC' // or 'DESC' (case sensitive for local sorting)
1174
+ }
1175
+ </code></pre>
1176
+ */
1177
+ /**
1178
+ * @cfg {boolean} remoteSort <tt>true</tt> if sorting is to be handled by requesting the <tt>{@link #proxy Proxy}</tt>
1179
+ * to provide a refreshed version of the data object in sorted order, as opposed to sorting the Record cache
1180
+ * in place (defaults to <tt>false</tt>).
1181
+ * <p>If <tt>remoteSort</tt> is <tt>true</tt>, then clicking on a {@link Ext.grid.Column Grid Column}'s
1182
+ * {@link Ext.grid.Column#header header} causes the current page to be requested from the server appending
1183
+ * the following two parameters to the <b><tt>{@link #load params}</tt></b>:<div class="mdetail-params"><ul>
1184
+ * <li><b><tt>sort</tt></b> : String<p class="sub-desc">The <tt>name</tt> (as specified in the Record's
1185
+ * {@link Ext.data.Field Field definition}) of the field to sort on.</p></li>
1186
+ * <li><b><tt>dir</tt></b> : String<p class="sub-desc">The direction of the sort, 'ASC' or 'DESC' (case-sensitive).</p></li>
1187
+ * </ul></div></p>
1188
+ */
1189
+ remoteSort : false,
1190
+
1191
+ /**
1192
+ * @cfg {Boolean} autoDestroy <tt>true</tt> to destroy the store when the component the store is bound
1193
+ * to is destroyed (defaults to <tt>false</tt>).
1194
+ * <p><b>Note</b>: this should be set to true when using stores that are bound to only 1 component.</p>
1195
+ */
1196
+ autoDestroy : false,
1197
+
1198
+ /**
1199
+ * @cfg {Boolean} pruneModifiedRecords <tt>true</tt> to clear all modified record information each time
1200
+ * the store is loaded or when a record is removed (defaults to <tt>false</tt>). See {@link #getModifiedRecords}
1201
+ * for the accessor method to retrieve the modified records.
1202
+ */
1203
+ pruneModifiedRecords : false,
1204
+
1205
+ /**
1206
+ * Contains the last options object used as the parameter to the {@link #load} method. See {@link #load}
1207
+ * for the details of what this may contain. This may be useful for accessing any params which were used
1208
+ * to load the current Record cache.
1209
+ * @property
1210
+ */
1211
+ lastOptions : null,
1212
+
1213
+ /**
1214
+ * @cfg {Boolean} autoSave
1215
+ * <p>Defaults to <tt>true</tt> causing the store to automatically {@link #save} records to
1216
+ * the server when a record is modified (ie: becomes 'dirty'). Specify <tt>false</tt> to manually call {@link #save}
1217
+ * to send all modifiedRecords to the server.</p>
1218
+ * <br><p><b>Note</b>: each CRUD action will be sent as a separate request.</p>
1219
+ */
1220
+ autoSave : true,
1221
+
1222
+ /**
1223
+ * @cfg {Boolean} batch
1224
+ * <p>Defaults to <tt>true</tt> (unless <code>{@link #restful}:true</code>). Multiple
1225
+ * requests for each CRUD action (CREATE, READ, UPDATE and DESTROY) will be combined
1226
+ * and sent as one transaction. Only applies when <code>{@link #autoSave}</code> is set
1227
+ * to <tt>false</tt>.</p>
1228
+ * <br><p>If Store is RESTful, the DataProxy is also RESTful, and a unique transaction is
1229
+ * generated for each record.</p>
1230
+ */
1231
+ batch : true,
1232
+
1233
+ /**
1234
+ * @cfg {Boolean} restful
1235
+ * Defaults to <tt>false</tt>. Set to <tt>true</tt> to have the Store and the set
1236
+ * Proxy operate in a RESTful manner. The store will automatically generate GET, POST,
1237
+ * PUT and DELETE requests to the server. The HTTP method used for any given CRUD
1238
+ * action is described in {@link Ext.data.Api#restActions}. For additional information
1239
+ * see {@link Ext.data.DataProxy#restful}.
1240
+ * <p><b>Note</b>: if <code>{@link #restful}:true</code> <code>batch</code> will
1241
+ * internally be set to <tt>false</tt>.</p>
1242
+ */
1243
+ restful: false,
1244
+
1245
+ /**
1246
+ * @cfg {Object} paramNames
1247
+ * <p>An object containing properties which specify the names of the paging and
1248
+ * sorting parameters passed to remote servers when loading blocks of data. By default, this
1249
+ * object takes the following form:</p><pre><code>
1250
+ {
1251
+ start : 'start', // The parameter name which specifies the start row
1252
+ limit : 'limit', // The parameter name which specifies number of rows to return
1253
+ sort : 'sort', // The parameter name which specifies the column to sort on
1254
+ dir : 'dir' // The parameter name which specifies the sort direction
1255
+ }
1256
+ </code></pre>
1257
+ * <p>The server must produce the requested data block upon receipt of these parameter names.
1258
+ * If different parameter names are required, this property can be overriden using a configuration
1259
+ * property.</p>
1260
+ * <p>A {@link Ext.PagingToolbar PagingToolbar} bound to this Store uses this property to determine
1261
+ * the parameter names to use in its {@link #load requests}.
1262
+ */
1263
+ paramNames : undefined,
1264
+
1265
+ /**
1266
+ * @cfg {Object} defaultParamNames
1267
+ * Provides the default values for the {@link #paramNames} property. To globally modify the parameters
1268
+ * for all stores, this object should be changed on the store prototype.
1269
+ */
1270
+ defaultParamNames : {
1271
+ start : 'start',
1272
+ limit : 'limit',
1273
+ sort : 'sort',
1274
+ dir : 'dir'
1275
+ },
1276
+
1277
+ /**
1278
+ * Destroys the store.
1279
+ */
1280
+ destroy : function(){
1281
+ if(this.storeId){
1282
+ Ext.StoreMgr.unregister(this);
1283
+ }
1284
+ this.data = null;
1285
+ Ext.destroy(this.proxy);
1286
+ this.reader = this.writer = null;
1287
+ this.purgeListeners();
1288
+ },
1289
+
1290
+ /**
1291
+ * Add Records to the Store and fires the {@link #add} event. To add Records
1292
+ * to the store from a remote source use <code>{@link #load}({add:true})</code>.
1293
+ * See also <code>{@link #recordType}</code> and <code>{@link #insert}</code>.
1294
+ * @param {Ext.data.Record[]} records An Array of Ext.data.Record objects
1295
+ * to add to the cache. See {@link #recordType}.
1296
+ */
1297
+ add : function(records){
1298
+ records = [].concat(records);
1299
+ if(records.length < 1){
1300
+ return;
1301
+ }
1302
+ for(var i = 0, len = records.length; i < len; i++){
1303
+ records[i].join(this);
1304
+ }
1305
+ var index = this.data.length;
1306
+ this.data.addAll(records);
1307
+ if(this.snapshot){
1308
+ this.snapshot.addAll(records);
1309
+ }
1310
+ this.fireEvent('add', this, records, index);
1311
+ },
1312
+
1313
+ /**
1314
+ * (Local sort only) Inserts the passed Record into the Store at the index where it
1315
+ * should go based on the current sort information.
1316
+ * @param {Ext.data.Record} record
1317
+ */
1318
+ addSorted : function(record){
1319
+ var index = this.findInsertIndex(record);
1320
+ this.insert(index, record);
1321
+ },
1322
+
1323
+ /**
1324
+ * Remove a Record from the Store and fires the {@link #remove} event.
1325
+ * @param {Ext.data.Record} record The Ext.data.Record object to remove from the cache.
1326
+ */
1327
+ remove : function(record){
1328
+ var index = this.data.indexOf(record);
1329
+ if(index > -1){
1330
+ this.data.removeAt(index);
1331
+ if(this.pruneModifiedRecords){
1332
+ this.modified.remove(record);
1333
+ }
1334
+ if(this.snapshot){
1335
+ this.snapshot.remove(record);
1336
+ }
1337
+ this.fireEvent('remove', this, record, index);
1338
+ }
1339
+ },
1340
+
1341
+ /**
1342
+ * Remove a Record from the Store at the specified index. Fires the {@link #remove} event.
1343
+ * @param {Number} index The index of the record to remove.
1344
+ */
1345
+ removeAt : function(index){
1346
+ this.remove(this.getAt(index));
1347
+ },
1348
+
1349
+ /**
1350
+ * Remove all Records from the Store and fires the {@link #clear} event.
1351
+ */
1352
+ removeAll : function(){
1353
+ this.data.clear();
1354
+ if(this.snapshot){
1355
+ this.snapshot.clear();
1356
+ }
1357
+ if(this.pruneModifiedRecords){
1358
+ this.modified = [];
1359
+ }
1360
+ this.fireEvent('clear', this);
1361
+ },
1362
+
1363
+ /**
1364
+ * Inserts Records into the Store at the given index and fires the {@link #add} event.
1365
+ * See also <code>{@link #add}</code> and <code>{@link #addSorted}</code>.
1366
+ * @param {Number} index The start index at which to insert the passed Records.
1367
+ * @param {Ext.data.Record[]} records An Array of Ext.data.Record objects to add to the cache.
1368
+ */
1369
+ insert : function(index, records){
1370
+ records = [].concat(records);
1371
+ for(var i = 0, len = records.length; i < len; i++){
1372
+ this.data.insert(index, records[i]);
1373
+ records[i].join(this);
1374
+ }
1375
+ this.fireEvent('add', this, records, index);
1376
+ },
1377
+
1378
+ /**
1379
+ * Get the index within the cache of the passed Record.
1380
+ * @param {Ext.data.Record} record The Ext.data.Record object to find.
1381
+ * @return {Number} The index of the passed Record. Returns -1 if not found.
1382
+ */
1383
+ indexOf : function(record){
1384
+ return this.data.indexOf(record);
1385
+ },
1386
+
1387
+ /**
1388
+ * Get the index within the cache of the Record with the passed id.
1389
+ * @param {String} id The id of the Record to find.
1390
+ * @return {Number} The index of the Record. Returns -1 if not found.
1391
+ */
1392
+ indexOfId : function(id){
1393
+ return this.data.indexOfKey(id);
1394
+ },
1395
+
1396
+ /**
1397
+ * Get the Record with the specified id.
1398
+ * @param {String} id The id of the Record to find.
1399
+ * @return {Ext.data.Record} The Record with the passed id. Returns undefined if not found.
1400
+ */
1401
+ getById : function(id){
1402
+ return this.data.key(id);
1403
+ },
1404
+
1405
+ /**
1406
+ * Get the Record at the specified index.
1407
+ * @param {Number} index The index of the Record to find.
1408
+ * @return {Ext.data.Record} The Record at the passed index. Returns undefined if not found.
1409
+ */
1410
+ getAt : function(index){
1411
+ return this.data.itemAt(index);
1412
+ },
1413
+
1414
+ /**
1415
+ * Returns a range of Records between specified indices.
1416
+ * @param {Number} startIndex (optional) The starting index (defaults to 0)
1417
+ * @param {Number} endIndex (optional) The ending index (defaults to the last Record in the Store)
1418
+ * @return {Ext.data.Record[]} An array of Records
1419
+ */
1420
+ getRange : function(start, end){
1421
+ return this.data.getRange(start, end);
1422
+ },
1423
+
1424
+ // private
1425
+ storeOptions : function(o){
1426
+ o = Ext.apply({}, o);
1427
+ delete o.callback;
1428
+ delete o.scope;
1429
+ this.lastOptions = o;
1430
+ },
1431
+
1432
+ /**
1433
+ * <p>Loads the Record cache from the configured <tt>{@link #proxy}</tt> using the configured <tt>{@link #reader}</tt>.</p>
1434
+ * <br><p>Notes:</p><div class="mdetail-params"><ul>
1435
+ * <li><b><u>Important</u></b>: loading is asynchronous! This call will return before the new data has been
1436
+ * loaded. To perform any post-processing where information from the load call is required, specify
1437
+ * the <tt>callback</tt> function to be called, or use a {@link Ext.util.Observable#listeners a 'load' event handler}.</li>
1438
+ * <li>If using {@link Ext.PagingToolbar remote paging}, the first load call must specify the <tt>start</tt> and <tt>limit</tt>
1439
+ * properties in the <code>options.params</code> property to establish the initial position within the
1440
+ * dataset, and the number of Records to cache on each read from the Proxy.</li>
1441
+ * <li>If using {@link #remoteSort remote sorting}, the configured <code>{@link #sortInfo}</code>
1442
+ * will be automatically included with the posted parameters according to the specified
1443
+ * <code>{@link #paramNames}</code>.</li>
1444
+ * </ul></div>
1445
+ * @param {Object} options An object containing properties which control loading options:<ul>
1446
+ * <li><b><tt>params</tt></b> :Object<div class="sub-desc"><p>An object containing properties to pass as HTTP
1447
+ * parameters to a remote data source. <b>Note</b>: <code>params</code> will override any
1448
+ * <code>{@link #baseParams}</code> of the same name.</p>
1449
+ * <p>Parameters are encoded as standard HTTP parameters using {@link Ext#urlEncode}.</p></div></li>
1450
+ * <li><b><tt>callback</tt></b> : Function<div class="sub-desc"><p>A function to be called after the Records
1451
+ * have been loaded. The <tt>callback</tt> is called after the load event and is passed the following arguments:<ul>
1452
+ * <li><tt>r</tt> : Ext.data.Record[]</li>
1453
+ * <li><tt>options</tt>: Options object from the load call</li>
1454
+ * <li><tt>success</tt>: Boolean success indicator</li></ul></p></div></li>
1455
+ * <li><b><tt>scope</tt></b> : Object<div class="sub-desc"><p>Scope with which to call the callback (defaults
1456
+ * to the Store object)</p></div></li>
1457
+ * <li><b><tt>add</tt></b> : Boolean<div class="sub-desc"><p>Indicator to append loaded records rather than
1458
+ * replace the current cache. <b>Note</b>: see note for <tt>{@link #loadData}</tt></p></div></li>
1459
+ * </ul>
1460
+ * @return {Boolean} If the <i>developer</i> provided <tt>{@link #beforeload}</tt> event handler returns
1461
+ * <tt>false</tt>, the load call will abort and will return <tt>false</tt>; otherwise will return <tt>true</tt>.
1462
+ */
1463
+ load : function(options) {
1464
+ options = options || {};
1465
+ this.storeOptions(options);
1466
+ if(this.sortInfo && this.remoteSort){
1467
+ var pn = this.paramNames;
1468
+ options.params = options.params || {};
1469
+ options.params[pn.sort] = this.sortInfo.field;
1470
+ options.params[pn.dir] = this.sortInfo.direction;
1471
+ }
1472
+ try {
1473
+ return this.execute('read', null, options); // <-- null represents rs. No rs for load actions.
1474
+ } catch(e) {
1475
+ this.handleException(e);
1476
+ return false;
1477
+ }
1478
+ },
1479
+
1480
+ /**
1481
+ * updateRecord Should not be used directly. This method will be called automatically if a Writer is set.
1482
+ * Listens to 'update' event.
1483
+ * @param {Object} store
1484
+ * @param {Object} record
1485
+ * @param {Object} action
1486
+ * @private
1487
+ */
1488
+ updateRecord : function(store, record, action) {
1489
+ if (action == Ext.data.Record.EDIT && this.autoSave === true && (!record.phantom || (record.phantom && record.isValid))) {
1490
+ this.save();
1491
+ }
1492
+ },
1493
+
1494
+ /**
1495
+ * Should not be used directly. Store#add will call this automatically if a Writer is set
1496
+ * @param {Object} store
1497
+ * @param {Object} rs
1498
+ * @param {Object} index
1499
+ * @private
1500
+ */
1501
+ createRecords : function(store, rs, index) {
1502
+ for (var i = 0, len = rs.length; i < len; i++) {
1503
+ if (rs[i].phantom && rs[i].isValid()) {
1504
+ rs[i].markDirty(); // <-- Mark new records dirty
1505
+ this.modified.push(rs[i]); // <-- add to modified
1506
+ }
1507
+ }
1508
+ if (this.autoSave === true) {
1509
+ this.save();
1510
+ }
1511
+ },
1512
+
1513
+ /**
1514
+ * Destroys a record or records. Should not be used directly. It's called by Store#remove if a Writer is set.
1515
+ * @param {Store} this
1516
+ * @param {Ext.data.Record/Ext.data.Record[]}
1517
+ * @param {Number} index
1518
+ * @private
1519
+ */
1520
+ destroyRecord : function(store, record, index) {
1521
+ if (this.modified.indexOf(record) != -1) { // <-- handled already if @cfg pruneModifiedRecords == true
1522
+ this.modified.remove(record);
1523
+ }
1524
+ if (!record.phantom) {
1525
+ this.removed.push(record);
1526
+
1527
+ // since the record has already been removed from the store but the server request has not yet been executed,
1528
+ // must keep track of the last known index this record existed. If a server error occurs, the record can be
1529
+ // put back into the store. @see Store#createCallback where the record is returned when response status === false
1530
+ record.lastIndex = index;
1531
+
1532
+ if (this.autoSave === true) {
1533
+ this.save();
1534
+ }
1535
+ }
1536
+ },
1537
+
1538
+ /**
1539
+ * This method should generally not be used directly. This method is called internally
1540
+ * by {@link #load}, or if a Writer is set will be called automatically when {@link #add},
1541
+ * {@link #remove}, or {@link #update} events fire.
1542
+ * @param {String} action Action name ('read', 'create', 'update', or 'destroy')
1543
+ * @param {Record/Record[]} rs
1544
+ * @param {Object} options
1545
+ * @throws Error
1546
+ * @private
1547
+ */
1548
+ execute : function(action, rs, options) {
1549
+ // blow up if action not Ext.data.CREATE, READ, UPDATE, DESTROY
1550
+ if (!Ext.data.Api.isAction(action)) {
1551
+ throw new Ext.data.Api.Error('execute', action);
1552
+ }
1553
+ // make sure options has a params key
1554
+ options = Ext.applyIf(options||{}, {
1555
+ params: {}
1556
+ });
1557
+
1558
+ // have to separate before-events since load has a different signature than create,destroy and save events since load does not
1559
+ // include the rs (record resultset) parameter. Capture return values from the beforeaction into doRequest flag.
1560
+ var doRequest = true;
1561
+
1562
+ if (action === 'read') {
1563
+ doRequest = this.fireEvent('beforeload', this, options);
1564
+ }
1565
+ else {
1566
+ // if Writer is configured as listful, force single-recoord rs to be [{}} instead of {}
1567
+ if (this.writer.listful === true && this.restful !== true) {
1568
+ rs = (Ext.isArray(rs)) ? rs : [rs];
1569
+ }
1570
+ // if rs has just a single record, shift it off so that Writer writes data as '{}' rather than '[{}]'
1571
+ else if (Ext.isArray(rs) && rs.length == 1) {
1572
+ rs = rs.shift();
1573
+ }
1574
+ // Write the action to options.params
1575
+ if ((doRequest = this.fireEvent('beforewrite', this, action, rs, options)) !== false) {
1576
+ this.writer.write(action, options.params, rs);
1577
+ }
1578
+ }
1579
+ if (doRequest !== false) {
1580
+ // Send request to proxy.
1581
+ var params = Ext.apply({}, options.params, this.baseParams);
1582
+ if (this.writer && this.proxy.url && !this.proxy.restful && !Ext.data.Api.hasUniqueUrl(this.proxy, action)) {
1583
+ params.xaction = action;
1584
+ }
1585
+ // Note: Up until this point we've been dealing with 'action' as a key from Ext.data.Api.actions. We'll flip it now
1586
+ // and send the value into DataProxy#request, since it's the value which maps to the DataProxy#api
1587
+ this.proxy.request(Ext.data.Api.actions[action], rs, params, this.reader, this.createCallback(action, rs), this, options);
1588
+ }
1589
+ return doRequest;
1590
+ },
1591
+
1592
+ /**
1593
+ * Saves all pending changes to the store. If the commensurate Ext.data.Api.actions action is not configured, then
1594
+ * the configured <code>{@link #url}</code> will be used.
1595
+ * <pre>
1596
+ * change url
1597
+ * --------------- --------------------
1598
+ * removed records Ext.data.Api.actions.destroy
1599
+ * phantom records Ext.data.Api.actions.create
1600
+ * {@link #getModifiedRecords modified records} Ext.data.Api.actions.update
1601
+ * </pre>
1602
+ * @TODO: Create extensions of Error class and send associated Record with thrown exceptions.
1603
+ * e.g.: Ext.data.DataReader.Error or Ext.data.Error or Ext.data.DataProxy.Error, etc.
1604
+ */
1605
+ save : function() {
1606
+ if (!this.writer) {
1607
+ throw new Ext.data.Store.Error('writer-undefined');
1608
+ }
1609
+
1610
+ // DESTROY: First check for removed records. Records in this.removed are guaranteed non-phantoms. @see Store#remove
1611
+ if (this.removed.length) {
1612
+ this.doTransaction('destroy', this.removed);
1613
+ }
1614
+
1615
+ // Check for modified records. Use a copy so Store#rejectChanges will work if server returns error.
1616
+ var rs = [].concat(this.getModifiedRecords());
1617
+ if (!rs.length) { // Bail-out if empty...
1618
+ return true;
1619
+ }
1620
+
1621
+ // CREATE: Next check for phantoms within rs. splice-off and execute create.
1622
+ var phantoms = [];
1623
+ for (var i = rs.length-1; i >= 0; i--) {
1624
+ if (rs[i].phantom === true) {
1625
+ var rec = rs.splice(i, 1).shift();
1626
+ if (rec.isValid()) {
1627
+ phantoms.push(rec);
1628
+ }
1629
+ } else if (!rs[i].isValid()) { // <-- while we're here, splice-off any !isValid real records
1630
+ rs.splice(i,1);
1631
+ }
1632
+ }
1633
+ // If we have valid phantoms, create them...
1634
+ if (phantoms.length) {
1635
+ this.doTransaction('create', phantoms);
1636
+ }
1637
+
1638
+ // UPDATE: And finally, if we're still here after splicing-off phantoms and !isValid real records, update the rest...
1639
+ if (rs.length) {
1640
+ this.doTransaction('update', rs);
1641
+ }
1642
+ return true;
1643
+ },
1644
+
1645
+ // private. Simply wraps call to Store#execute in try/catch. Defers to Store#handleException on error. Loops if batch: false
1646
+ doTransaction : function(action, rs) {
1647
+ function transaction(records) {
1648
+ try {
1649
+ this.execute(action, records);
1650
+ } catch (e) {
1651
+ this.handleException(e);
1652
+ }
1653
+ }
1654
+ if (this.batch === false) {
1655
+ for (var i = 0, len = rs.length; i < len; i++) {
1656
+ transaction.call(this, rs[i]);
1657
+ }
1658
+ } else {
1659
+ transaction.call(this, rs);
1660
+ }
1661
+ },
1662
+
1663
+ // @private callback-handler for remote CRUD actions
1664
+ // Do not override -- override loadRecords, onCreateRecords, onDestroyRecords and onUpdateRecords instead.
1665
+ createCallback : function(action, rs) {
1666
+ var actions = Ext.data.Api.actions;
1667
+ return (action == 'read') ? this.loadRecords : function(data, response, success) {
1668
+ // calls: onCreateRecords | onUpdateRecords | onDestroyRecords
1669
+ this['on' + Ext.util.Format.capitalize(action) + 'Records'](success, rs, data);
1670
+ // If success === false here, exception will have been called in DataProxy
1671
+ if (success === true) {
1672
+ this.fireEvent('write', this, action, data, response, rs);
1673
+ }
1674
+ };
1675
+ },
1676
+
1677
+ // Clears records from modified array after an exception event.
1678
+ // NOTE: records are left marked dirty. Do we want to commit them even though they were not updated/realized?
1679
+ clearModified : function(rs) {
1680
+ if (Ext.isArray(rs)) {
1681
+ for (var n=rs.length-1;n>=0;n--) {
1682
+ this.modified.splice(this.modified.indexOf(rs[n]), 1);
1683
+ }
1684
+ } else {
1685
+ this.modified.splice(this.modified.indexOf(rs), 1);
1686
+ }
1687
+ },
1688
+
1689
+ // remap record ids in MixedCollection after records have been realized. @see Store#onCreateRecords, @see DataReader#realize
1690
+ reMap : function(record) {
1691
+ if (Ext.isArray(record)) {
1692
+ for (var i = 0, len = record.length; i < len; i++) {
1693
+ this.reMap(record[i]);
1694
+ }
1695
+ } else {
1696
+ delete this.data.map[record._phid];
1697
+ this.data.map[record.id] = record;
1698
+ var index = this.data.keys.indexOf(record._phid);
1699
+ this.data.keys.splice(index, 1, record.id);
1700
+ delete record._phid;
1701
+ }
1702
+ },
1703
+
1704
+ // @protected onCreateRecord proxy callback for create action
1705
+ onCreateRecords : function(success, rs, data) {
1706
+ if (success === true) {
1707
+ try {
1708
+ this.reader.realize(rs, data);
1709
+ this.reMap(rs);
1710
+ }
1711
+ catch (e) {
1712
+ this.handleException(e);
1713
+ if (Ext.isArray(rs)) {
1714
+ // Recurse to run back into the try {}. DataReader#realize splices-off the rs until empty.
1715
+ this.onCreateRecords(success, rs, data);
1716
+ }
1717
+ }
1718
+ }
1719
+ },
1720
+
1721
+ // @protected, onUpdateRecords proxy callback for update action
1722
+ onUpdateRecords : function(success, rs, data) {
1723
+ if (success === true) {
1724
+ try {
1725
+ this.reader.update(rs, data);
1726
+ } catch (e) {
1727
+ this.handleException(e);
1728
+ if (Ext.isArray(rs)) {
1729
+ // Recurse to run back into the try {}. DataReader#update splices-off the rs until empty.
1730
+ this.onUpdateRecords(success, rs, data);
1731
+ }
1732
+ }
1733
+ }
1734
+ },
1735
+
1736
+ // @protected onDestroyRecords proxy callback for destroy action
1737
+ onDestroyRecords : function(success, rs, data) {
1738
+ // splice each rec out of this.removed
1739
+ rs = (rs instanceof Ext.data.Record) ? [rs] : rs;
1740
+ for (var i=0,len=rs.length;i<len;i++) {
1741
+ this.removed.splice(this.removed.indexOf(rs[i]), 1);
1742
+ }
1743
+ if (success === false) {
1744
+ // put records back into store if remote destroy fails.
1745
+ // @TODO: Might want to let developer decide.
1746
+ for (i=rs.length-1;i>=0;i--) {
1747
+ this.insert(rs[i].lastIndex, rs[i]); // <-- lastIndex set in Store#destroyRecord
1748
+ }
1749
+ }
1750
+ },
1751
+
1752
+ // protected handleException. Possibly temporary until Ext framework has an exception-handler.
1753
+ handleException : function(e) {
1754
+ // @see core/Error.js
1755
+ Ext.handleError(e);
1756
+ },
1757
+
1758
+ /**
1759
+ * <p>Reloads the Record cache from the configured Proxy using the configured {@link Ext.data.Reader Reader} and
1760
+ * the options from the last load operation performed.</p>
1761
+ * <p><b>Note</b>: see the Important note in {@link #load}.</p>
1762
+ * @param {Object} options (optional) An <tt>Object</tt> containing {@link #load loading options} which may
1763
+ * override the options used in the last {@link #load} operation. See {@link #load} for details (defaults to
1764
+ * <tt>null</tt>, in which case the {@link #lastOptions} are used).
1765
+ */
1766
+ reload : function(options){
1767
+ this.load(Ext.applyIf(options||{}, this.lastOptions));
1768
+ },
1769
+
1770
+ // private
1771
+ // Called as a callback by the Reader during a load operation.
1772
+ loadRecords : function(o, options, success){
1773
+ if(!o || success === false){
1774
+ if(success !== false){
1775
+ this.fireEvent('load', this, [], options);
1776
+ }
1777
+ if(options.callback){
1778
+ options.callback.call(options.scope || this, [], options, false, o);
1779
+ }
1780
+ return;
1781
+ }
1782
+ var r = o.records, t = o.totalRecords || r.length;
1783
+ if(!options || options.add !== true){
1784
+ if(this.pruneModifiedRecords){
1785
+ this.modified = [];
1786
+ }
1787
+ for(var i = 0, len = r.length; i < len; i++){
1788
+ r[i].join(this);
1789
+ }
1790
+ if(this.snapshot){
1791
+ this.data = this.snapshot;
1792
+ delete this.snapshot;
1793
+ }
1794
+ this.data.clear();
1795
+ this.data.addAll(r);
1796
+ this.totalLength = t;
1797
+ this.applySort();
1798
+ this.fireEvent('datachanged', this);
1799
+ }else{
1800
+ this.totalLength = Math.max(t, this.data.length+r.length);
1801
+ this.add(r);
1802
+ }
1803
+ this.fireEvent('load', this, r, options);
1804
+ if(options.callback){
1805
+ options.callback.call(options.scope || this, r, options, true);
1806
+ }
1807
+ },
1808
+
1809
+ /**
1810
+ * Loads data from a passed data block and fires the {@link #load} event. A {@link Ext.data.Reader Reader}
1811
+ * which understands the format of the data must have been configured in the constructor.
1812
+ * @param {Object} data The data block from which to read the Records. The format of the data expected
1813
+ * is dependent on the type of {@link Ext.data.Reader Reader} that is configured and should correspond to
1814
+ * that {@link Ext.data.Reader Reader}'s <tt>{@link Ext.data.Reader#readRecords}</tt> parameter.
1815
+ * @param {Boolean} append (Optional) <tt>true</tt> to append the new Records rather the default to replace
1816
+ * the existing cache.
1817
+ * <b>Note</b>: that Records in a Store are keyed by their {@link Ext.data.Record#id id}, so added Records
1818
+ * with ids which are already present in the Store will <i>replace</i> existing Records. Only Records with
1819
+ * new, unique ids will be added.
1820
+ */
1821
+ loadData : function(o, append){
1822
+ var r = this.reader.readRecords(o);
1823
+ this.loadRecords(r, {add: append}, true);
1824
+ },
1825
+
1826
+ /**
1827
+ * Gets the number of cached records.
1828
+ * <p>If using paging, this may not be the total size of the dataset. If the data object
1829
+ * used by the Reader contains the dataset size, then the {@link #getTotalCount} function returns
1830
+ * the dataset size. <b>Note</b>: see the Important note in {@link #load}.</p>
1831
+ * @return {Number} The number of Records in the Store's cache.
1832
+ */
1833
+ getCount : function(){
1834
+ return this.data.length || 0;
1835
+ },
1836
+
1837
+ /**
1838
+ * Gets the total number of records in the dataset as returned by the server.
1839
+ * <p>If using paging, for this to be accurate, the data object used by the {@link #reader Reader}
1840
+ * must contain the dataset size. For remote data sources, the value for this property
1841
+ * (<tt>totalProperty</tt> for {@link Ext.data.JsonReader JsonReader},
1842
+ * <tt>totalRecords</tt> for {@link Ext.data.XmlReader XmlReader}) shall be returned by a query on the server.
1843
+ * <b>Note</b>: see the Important note in {@link #load}.</p>
1844
+ * @return {Number} The number of Records as specified in the data object passed to the Reader
1845
+ * by the Proxy.
1846
+ * <p><b>Note</b>: this value is not updated when changing the contents of the Store locally.</p>
1847
+ */
1848
+ getTotalCount : function(){
1849
+ return this.totalLength || 0;
1850
+ },
1851
+
1852
+ /**
1853
+ * Returns an object describing the current sort state of this Store.
1854
+ * @return {Object} The sort state of the Store. An object with two properties:<ul>
1855
+ * <li><b>field : String<p class="sub-desc">The name of the field by which the Records are sorted.</p></li>
1856
+ * <li><b>direction : String<p class="sub-desc">The sort order, 'ASC' or 'DESC' (case-sensitive).</p></li>
1857
+ * </ul>
1858
+ * See <tt>{@link #sortInfo}</tt> for additional details.
1859
+ */
1860
+ getSortState : function(){
1861
+ return this.sortInfo;
1862
+ },
1863
+
1864
+ // private
1865
+ applySort : function(){
1866
+ if(this.sortInfo && !this.remoteSort){
1867
+ var s = this.sortInfo, f = s.field;
1868
+ this.sortData(f, s.direction);
1869
+ }
1870
+ },
1871
+
1872
+ // private
1873
+ sortData : function(f, direction){
1874
+ direction = direction || 'ASC';
1875
+ var st = this.fields.get(f).sortType;
1876
+ var fn = function(r1, r2){
1877
+ var v1 = st(r1.data[f]), v2 = st(r2.data[f]);
1878
+ return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
1879
+ };
1880
+ this.data.sort(direction, fn);
1881
+ if(this.snapshot && this.snapshot != this.data){
1882
+ this.snapshot.sort(direction, fn);
1883
+ }
1884
+ },
1885
+
1886
+ /**
1887
+ * Sets the default sort column and order to be used by the next {@link #load} operation.
1888
+ * @param {String} fieldName The name of the field to sort by.
1889
+ * @param {String} dir (optional) The sort order, 'ASC' or 'DESC' (case-sensitive, defaults to <tt>'ASC'</tt>)
1890
+ */
1891
+ setDefaultSort : function(field, dir){
1892
+ dir = dir ? dir.toUpperCase() : 'ASC';
1893
+ this.sortInfo = {field: field, direction: dir};
1894
+ this.sortToggle[field] = dir;
1895
+ },
1896
+
1897
+ /**
1898
+ * Sort the Records.
1899
+ * If remote sorting is used, the sort is performed on the server, and the cache is reloaded. If local
1900
+ * sorting is used, the cache is sorted internally. See also {@link #remoteSort} and {@link #paramNames}.
1901
+ * @param {String} fieldName The name of the field to sort by.
1902
+ * @param {String} dir (optional) The sort order, 'ASC' or 'DESC' (case-sensitive, defaults to <tt>'ASC'</tt>)
1903
+ */
1904
+ sort : function(fieldName, dir){
1905
+ var f = this.fields.get(fieldName);
1906
+ if(!f){
1907
+ return false;
1908
+ }
1909
+ if(!dir){
1910
+ if(this.sortInfo && this.sortInfo.field == f.name){ // toggle sort dir
1911
+ dir = (this.sortToggle[f.name] || 'ASC').toggle('ASC', 'DESC');
1912
+ }else{
1913
+ dir = f.sortDir;
1914
+ }
1915
+ }
1916
+ var st = (this.sortToggle) ? this.sortToggle[f.name] : null;
1917
+ var si = (this.sortInfo) ? this.sortInfo : null;
1918
+
1919
+ this.sortToggle[f.name] = dir;
1920
+ this.sortInfo = {field: f.name, direction: dir};
1921
+ if(!this.remoteSort){
1922
+ this.applySort();
1923
+ this.fireEvent('datachanged', this);
1924
+ }else{
1925
+ if (!this.load(this.lastOptions)) {
1926
+ if (st) {
1927
+ this.sortToggle[f.name] = st;
1928
+ }
1929
+ if (si) {
1930
+ this.sortInfo = si;
1931
+ }
1932
+ }
1933
+ }
1934
+ },
1935
+
1936
+ /**
1937
+ * Calls the specified function for each of the {@link Ext.data.Record Records} in the cache.
1938
+ * @param {Function} fn The function to call. The {@link Ext.data.Record Record} is passed as the first parameter.
1939
+ * Returning <tt>false</tt> aborts and exits the iteration.
1940
+ * @param {Object} scope (optional) The scope in which to call the function (defaults to the {@link Ext.data.Record Record}).
1941
+ */
1942
+ each : function(fn, scope){
1943
+ this.data.each(fn, scope);
1944
+ },
1945
+
1946
+ /**
1947
+ * Gets all {@link Ext.data.Record records} modified since the last commit. Modified records are
1948
+ * persisted across load operations (e.g., during paging). <b>Note</b>: deleted records are not
1949
+ * included. See also <tt>{@link #pruneModifiedRecords}</tt> and
1950
+ * {@link Ext.data.Record}<tt>{@link Ext.data.Record#markDirty markDirty}.</tt>.
1951
+ * @return {Ext.data.Record[]} An array of {@link Ext.data.Record Records} containing outstanding
1952
+ * modifications. To obtain modified fields within a modified record see
1953
+ *{@link Ext.data.Record}<tt>{@link Ext.data.Record#modified modified}.</tt>.
1954
+ */
1955
+ getModifiedRecords : function(){
1956
+ return this.modified;
1957
+ },
1958
+
1959
+ // private
1960
+ createFilterFn : function(property, value, anyMatch, caseSensitive){
1961
+ if(Ext.isEmpty(value, false)){
1962
+ return false;
1963
+ }
1964
+ value = this.data.createValueMatcher(value, anyMatch, caseSensitive);
1965
+ return function(r){
1966
+ return value.test(r.data[property]);
1967
+ };
1968
+ },
1969
+
1970
+ /**
1971
+ * Sums the value of <tt>property</tt> for each {@link Ext.data.Record record} between <tt>start</tt>
1972
+ * and <tt>end</tt> and returns the result.
1973
+ * @param {String} property A field in each record
1974
+ * @param {Number} start (optional) The record index to start at (defaults to <tt>0</tt>)
1975
+ * @param {Number} end (optional) The last record index to include (defaults to length - 1)
1976
+ * @return {Number} The sum
1977
+ */
1978
+ sum : function(property, start, end){
1979
+ var rs = this.data.items, v = 0;
1980
+ start = start || 0;
1981
+ end = (end || end === 0) ? end : rs.length-1;
1982
+
1983
+ for(var i = start; i <= end; i++){
1984
+ v += (rs[i].data[property] || 0);
1985
+ }
1986
+ return v;
1987
+ },
1988
+
1989
+ /**
1990
+ * Filter the {@link Ext.data.Record records} by a specified property.
1991
+ * @param {String} field A field on your records
1992
+ * @param {String/RegExp} value Either a string that the field should begin with, or a RegExp to test
1993
+ * against the field.
1994
+ * @param {Boolean} anyMatch (optional) <tt>true</tt> to match any part not just the beginning
1995
+ * @param {Boolean} caseSensitive (optional) <tt>true</tt> for case sensitive comparison
1996
+ */
1997
+ filter : function(property, value, anyMatch, caseSensitive){
1998
+ var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
1999
+ return fn ? this.filterBy(fn) : this.clearFilter();
2000
+ },
2001
+
2002
+ /**
2003
+ * Filter by a function. The specified function will be called for each
2004
+ * Record in this Store. If the function returns <tt>true</tt> the Record is included,
2005
+ * otherwise it is filtered out.
2006
+ * @param {Function} fn The function to be called. It will be passed the following parameters:<ul>
2007
+ * <li><b>record</b> : Ext.data.Record<p class="sub-desc">The {@link Ext.data.Record record}
2008
+ * to test for filtering. Access field values using {@link Ext.data.Record#get}.</p></li>
2009
+ * <li><b>id</b> : Object<p class="sub-desc">The ID of the Record passed.</p></li>
2010
+ * </ul>
2011
+ * @param {Object} scope (optional) The scope of the function (defaults to this)
2012
+ */
2013
+ filterBy : function(fn, scope){
2014
+ this.snapshot = this.snapshot || this.data;
2015
+ this.data = this.queryBy(fn, scope||this);
2016
+ this.fireEvent('datachanged', this);
2017
+ },
2018
+
2019
+ /**
2020
+ * Query the records by a specified property.
2021
+ * @param {String} field A field on your records
2022
+ * @param {String/RegExp} value Either a string that the field
2023
+ * should begin with, or a RegExp to test against the field.
2024
+ * @param {Boolean} anyMatch (optional) True to match any part not just the beginning
2025
+ * @param {Boolean} caseSensitive (optional) True for case sensitive comparison
2026
+ * @return {MixedCollection} Returns an Ext.util.MixedCollection of the matched records
2027
+ */
2028
+ query : function(property, value, anyMatch, caseSensitive){
2029
+ var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
2030
+ return fn ? this.queryBy(fn) : this.data.clone();
2031
+ },
2032
+
2033
+ /**
2034
+ * Query the cached records in this Store using a filtering function. The specified function
2035
+ * will be called with each record in this Store. If the function returns <tt>true</tt> the record is
2036
+ * included in the results.
2037
+ * @param {Function} fn The function to be called. It will be passed the following parameters:<ul>
2038
+ * <li><b>record</b> : Ext.data.Record<p class="sub-desc">The {@link Ext.data.Record record}
2039
+ * to test for filtering. Access field values using {@link Ext.data.Record#get}.</p></li>
2040
+ * <li><b>id</b> : Object<p class="sub-desc">The ID of the Record passed.</p></li>
2041
+ * </ul>
2042
+ * @param {Object} scope (optional) The scope of the function (defaults to this)
2043
+ * @return {MixedCollection} Returns an Ext.util.MixedCollection of the matched records
2044
+ **/
2045
+ queryBy : function(fn, scope){
2046
+ var data = this.snapshot || this.data;
2047
+ return data.filterBy(fn, scope||this);
2048
+ },
2049
+
2050
+ /**
2051
+ * Finds the index of the first matching record in this store by a specific property/value.
2052
+ * @param {String} property A property on your objects
2053
+ * @param {String/RegExp} value Either a string that the property value
2054
+ * should begin with, or a RegExp to test against the property.
2055
+ * @param {Number} startIndex (optional) The index to start searching at
2056
+ * @param {Boolean} anyMatch (optional) True to match any part of the string, not just the beginning
2057
+ * @param {Boolean} caseSensitive (optional) True for case sensitive comparison
2058
+ * @return {Number} The matched index or -1
2059
+ */
2060
+ find : function(property, value, start, anyMatch, caseSensitive){
2061
+ var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
2062
+ return fn ? this.data.findIndexBy(fn, null, start) : -1;
2063
+ },
2064
+
2065
+ /**
2066
+ * Finds the index of the first matching record in this store by a specific property/value.
2067
+ * @param {String} property A property on your objects
2068
+ * @param {String/RegExp} value The value to match against
2069
+ * @param {Number} startIndex (optional) The index to start searching at
2070
+ * @return {Number} The matched index or -1
2071
+ */
2072
+ findExact: function(property, value, start){
2073
+ return this.data.findIndexBy(function(rec){
2074
+ return rec.get(property) === value;
2075
+ }, this, start);
2076
+ },
2077
+
2078
+ /**
2079
+ * Find the index of the first matching Record in this Store by a function.
2080
+ * If the function returns <tt>true</tt> it is considered a match.
2081
+ * @param {Function} fn The function to be called. It will be passed the following parameters:<ul>
2082
+ * <li><b>record</b> : Ext.data.Record<p class="sub-desc">The {@link Ext.data.Record record}
2083
+ * to test for filtering. Access field values using {@link Ext.data.Record#get}.</p></li>
2084
+ * <li><b>id</b> : Object<p class="sub-desc">The ID of the Record passed.</p></li>
2085
+ * </ul>
2086
+ * @param {Object} scope (optional) The scope of the function (defaults to this)
2087
+ * @param {Number} startIndex (optional) The index to start searching at
2088
+ * @return {Number} The matched index or -1
2089
+ */
2090
+ findBy : function(fn, scope, start){
2091
+ return this.data.findIndexBy(fn, scope, start);
2092
+ },
2093
+
2094
+ /**
2095
+ * Collects unique values for a particular dataIndex from this store.
2096
+ * @param {String} dataIndex The property to collect
2097
+ * @param {Boolean} allowNull (optional) Pass true to allow null, undefined or empty string values
2098
+ * @param {Boolean} bypassFilter (optional) Pass true to collect from all records, even ones which are filtered
2099
+ * @return {Array} An array of the unique values
2100
+ **/
2101
+ collect : function(dataIndex, allowNull, bypassFilter){
2102
+ var d = (bypassFilter === true && this.snapshot) ?
2103
+ this.snapshot.items : this.data.items;
2104
+ var v, sv, r = [], l = {};
2105
+ for(var i = 0, len = d.length; i < len; i++){
2106
+ v = d[i].data[dataIndex];
2107
+ sv = String(v);
2108
+ if((allowNull || !Ext.isEmpty(v)) && !l[sv]){
2109
+ l[sv] = true;
2110
+ r[r.length] = v;
2111
+ }
2112
+ }
2113
+ return r;
2114
+ },
2115
+
2116
+ /**
2117
+ * Revert to a view of the Record cache with no filtering applied.
2118
+ * @param {Boolean} suppressEvent If <tt>true</tt> the filter is cleared silently without firing the
2119
+ * {@link #datachanged} event.
2120
+ */
2121
+ clearFilter : function(suppressEvent){
2122
+ if(this.isFiltered()){
2123
+ this.data = this.snapshot;
2124
+ delete this.snapshot;
2125
+ if(suppressEvent !== true){
2126
+ this.fireEvent('datachanged', this);
2127
+ }
2128
+ }
2129
+ },
2130
+
2131
+ /**
2132
+ * Returns true if this store is currently filtered
2133
+ * @return {Boolean}
2134
+ */
2135
+ isFiltered : function(){
2136
+ return this.snapshot && this.snapshot != this.data;
2137
+ },
2138
+
2139
+ // private
2140
+ afterEdit : function(record){
2141
+ if(this.modified.indexOf(record) == -1){
2142
+ this.modified.push(record);
2143
+ }
2144
+ this.fireEvent('update', this, record, Ext.data.Record.EDIT);
2145
+ },
2146
+
2147
+ // private
2148
+ afterReject : function(record){
2149
+ this.modified.remove(record);
2150
+ this.fireEvent('update', this, record, Ext.data.Record.REJECT);
2151
+ },
2152
+
2153
+ // private
2154
+ afterCommit : function(record){
2155
+ this.modified.remove(record);
2156
+ this.fireEvent('update', this, record, Ext.data.Record.COMMIT);
2157
+ },
2158
+
2159
+ /**
2160
+ * Commit all Records with {@link #getModifiedRecords outstanding changes}. To handle updates for changes,
2161
+ * subscribe to the Store's {@link #update update event}, and perform updating when the third parameter is
2162
+ * Ext.data.Record.COMMIT.
2163
+ */
2164
+ commitChanges : function(){
2165
+ var m = this.modified.slice(0);
2166
+ this.modified = [];
2167
+ for(var i = 0, len = m.length; i < len; i++){
2168
+ m[i].commit();
2169
+ }
2170
+ },
2171
+
2172
+ /**
2173
+ * {@link Ext.data.Record#reject Reject} outstanding changes on all {@link #getModifiedRecords modified records}.
2174
+ */
2175
+ rejectChanges : function(){
2176
+ var m = this.modified.slice(0);
2177
+ this.modified = [];
2178
+ for(var i = 0, len = m.length; i < len; i++){
2179
+ m[i].reject();
2180
+ }
2181
+ },
2182
+
2183
+ // private
2184
+ onMetaChange : function(meta, rtype, o){
2185
+ this.recordType = rtype;
2186
+ this.fields = rtype.prototype.fields;
2187
+ delete this.snapshot;
2188
+ if(meta.sortInfo){
2189
+ this.sortInfo = meta.sortInfo;
2190
+ }else if(this.sortInfo && !this.fields.get(this.sortInfo.field)){
2191
+ delete this.sortInfo;
2192
+ }
2193
+ this.modified = [];
2194
+ this.fireEvent('metachange', this, this.reader.meta);
2195
+ },
2196
+
2197
+ // private
2198
+ findInsertIndex : function(record){
2199
+ this.suspendEvents();
2200
+ var data = this.data.clone();
2201
+ this.data.add(record);
2202
+ this.applySort();
2203
+ var index = this.data.indexOf(record);
2204
+ this.data = data;
2205
+ this.resumeEvents();
2206
+ return index;
2207
+ },
2208
+
2209
+ /**
2210
+ * Set the value for a property name in this store's {@link #baseParams}. Usage:</p><pre><code>
2211
+ myStore.setBaseParam('foo', {bar:3});
2212
+ </code></pre>
2213
+ * @param {String} name Name of the property to assign
2214
+ * @param {Mixed} value Value to assign the <tt>name</tt>d property
2215
+ **/
2216
+ setBaseParam : function (name, value){
2217
+ this.baseParams = this.baseParams || {};
2218
+ this.baseParams[name] = value;
2219
+ }
2220
+ });
2221
+
2222
+ Ext.reg('store', Ext.data.Store);
2223
+
2224
+ /**
2225
+ * @class Ext.data.Store.Error
2226
+ * @extends Ext.Error
2227
+ * Store Error extension.
2228
+ * @param {String} name
2229
+ */
2230
+ Ext.data.Store.Error = Ext.extend(Ext.Error, {
2231
+ name: 'Ext.data.Store'
2232
+ });
2233
+ Ext.apply(Ext.data.Store.Error.prototype, {
2234
+ lang: {
2235
+ 'writer-undefined' : 'Attempted to execute a write-action without a DataWriter installed.'
2236
+ }
2237
+ });
2238
+
2239
+ /**
2240
+ * @class Ext.data.Field
2241
+ * <p>This class encapsulates the field definition information specified in the field definition objects
2242
+ * passed to {@link Ext.data.Record#create}.</p>
2243
+ * <p>Developers do not need to instantiate this class. Instances are created by {@link Ext.data.Record.create}
2244
+ * and cached in the {@link Ext.data.Record#fields fields} property of the created Record constructor's <b>prototype.</b></p>
2245
+ */
2246
+ Ext.data.Field = function(config){
2247
+ if(typeof config == "string"){
2248
+ config = {name: config};
2249
+ }
2250
+ Ext.apply(this, config);
2251
+
2252
+ if(!this.type){
2253
+ this.type = "auto";
2254
+ }
2255
+
2256
+ var st = Ext.data.SortTypes;
2257
+ // named sortTypes are supported, here we look them up
2258
+ if(typeof this.sortType == "string"){
2259
+ this.sortType = st[this.sortType];
2260
+ }
2261
+
2262
+ // set default sortType for strings and dates
2263
+ if(!this.sortType){
2264
+ switch(this.type){
2265
+ case "string":
2266
+ this.sortType = st.asUCString;
2267
+ break;
2268
+ case "date":
2269
+ this.sortType = st.asDate;
2270
+ break;
2271
+ default:
2272
+ this.sortType = st.none;
2273
+ }
2274
+ }
2275
+
2276
+ // define once
2277
+ var stripRe = /[\$,%]/g;
2278
+
2279
+ // prebuilt conversion function for this field, instead of
2280
+ // switching every time we're reading a value
2281
+ if(!this.convert){
2282
+ var cv, dateFormat = this.dateFormat;
2283
+ switch(this.type){
2284
+ case "":
2285
+ case "auto":
2286
+ case undefined:
2287
+ cv = function(v){ return v; };
2288
+ break;
2289
+ case "string":
2290
+ cv = function(v){ return (v === undefined || v === null) ? '' : String(v); };
2291
+ break;
2292
+ case "int":
2293
+ cv = function(v){
2294
+ return v !== undefined && v !== null && v !== '' ?
2295
+ parseInt(String(v).replace(stripRe, ""), 10) : '';
2296
+ };
2297
+ break;
2298
+ case "float":
2299
+ cv = function(v){
2300
+ return v !== undefined && v !== null && v !== '' ?
2301
+ parseFloat(String(v).replace(stripRe, ""), 10) : '';
2302
+ };
2303
+ break;
2304
+ case "bool":
2305
+ case "boolean":
2306
+ cv = function(v){ return v === true || v === "true" || v == 1; };
2307
+ break;
2308
+ case "date":
2309
+ cv = function(v){
2310
+ if(!v){
2311
+ return '';
2312
+ }
2313
+ if(Ext.isDate(v)){
2314
+ return v;
2315
+ }
2316
+ if(dateFormat){
2317
+ if(dateFormat == "timestamp"){
2318
+ return new Date(v*1000);
2319
+ }
2320
+ if(dateFormat == "time"){
2321
+ return new Date(parseInt(v, 10));
2322
+ }
2323
+ return Date.parseDate(v, dateFormat);
2324
+ }
2325
+ var parsed = Date.parse(v);
2326
+ return parsed ? new Date(parsed) : null;
2327
+ };
2328
+ break;
2329
+
2330
+ }
2331
+ this.convert = cv;
2332
+ }
2333
+ };
2334
+
2335
+ Ext.data.Field.prototype = {
2336
+ /**
2337
+ * @cfg {String} name
2338
+ * The name by which the field is referenced within the Record. This is referenced by, for example,
2339
+ * the <tt>dataIndex</tt> property in column definition objects passed to {@link Ext.grid.ColumnModel}.
2340
+ * <p>Note: In the simplest case, if no properties other than <tt>name</tt> are required, a field
2341
+ * definition may consist of just a String for the field name.</p>
2342
+ */
2343
+ /**
2344
+ * @cfg {String} type
2345
+ * (Optional) The data type for conversion to displayable value if <tt>{@link Ext.data.Field#convert convert}</tt>
2346
+ * has not been specified. Possible values are
2347
+ * <div class="mdetail-params"><ul>
2348
+ * <li>auto (Default, implies no conversion)</li>
2349
+ * <li>string</li>
2350
+ * <li>int</li>
2351
+ * <li>float</li>
2352
+ * <li>boolean</li>
2353
+ * <li>date</li></ul></div>
2354
+ */
2355
+ /**
2356
+ * @cfg {Function} convert
2357
+ * (Optional) A function which converts the value provided by the Reader into an object that will be stored
2358
+ * in the Record. It is passed the following parameters:<div class="mdetail-params"><ul>
2359
+ * <li><b>v</b> : Mixed<div class="sub-desc">The data value as read by the Reader, if undefined will use
2360
+ * the configured <tt>{@link Ext.data.Field#defaultValue defaultValue}</tt>.</div></li>
2361
+ * <li><b>rec</b> : Mixed<div class="sub-desc">The data object containing the row as read by the Reader.
2362
+ * Depending on the Reader type, this could be an Array ({@link Ext.data.ArrayReader ArrayReader}), an object
2363
+ * ({@link Ext.data.JsonReader JsonReader}), or an XML element ({@link Ext.data.XMLReader XMLReader}).</div></li>
2364
+ * </ul></div>
2365
+ * <pre><code>
2366
+ // example of convert function
2367
+ function fullName(v, record){
2368
+ return record.name.last + ', ' + record.name.first;
2369
+ }
2370
+
2371
+ function location(v, record){
2372
+ return !record.city ? '' : (record.city + ', ' + record.state);
2373
+ }
2374
+
2375
+ var Dude = Ext.data.Record.create([
2376
+ {name: 'fullname', convert: fullName},
2377
+ {name: 'firstname', mapping: 'name.first'},
2378
+ {name: 'lastname', mapping: 'name.last'},
2379
+ {name: 'city', defaultValue: 'homeless'},
2380
+ 'state',
2381
+ {name: 'location', convert: location}
2382
+ ]);
2383
+
2384
+ // create the data store
2385
+ var store = new Ext.data.Store({
2386
+ reader: new Ext.data.JsonReader(
2387
+ {
2388
+ idProperty: 'key',
2389
+ root: 'daRoot',
2390
+ totalProperty: 'total'
2391
+ },
2392
+ Dude // recordType
2393
+ )
2394
+ });
2395
+
2396
+ var myData = [
2397
+ { key: 1,
2398
+ name: { first: 'Fat', last: 'Albert' }
2399
+ // notice no city, state provided in data object
2400
+ },
2401
+ { key: 2,
2402
+ name: { first: 'Barney', last: 'Rubble' },
2403
+ city: 'Bedrock', state: 'Stoneridge'
2404
+ },
2405
+ { key: 3,
2406
+ name: { first: 'Cliff', last: 'Claven' },
2407
+ city: 'Boston', state: 'MA'
2408
+ }
2409
+ ];
2410
+ * </code></pre>
2411
+ */
2412
+ /**
2413
+ * @cfg {String} dateFormat
2414
+ * (Optional) A format string for the {@link Date#parseDate Date.parseDate} function, or "timestamp" if the
2415
+ * value provided by the Reader is a UNIX timestamp, or "time" if the value provided by the Reader is a
2416
+ * javascript millisecond timestamp.
2417
+ */
2418
+ dateFormat: null,
2419
+ /**
2420
+ * @cfg {Mixed} defaultValue
2421
+ * (Optional) The default value used <b>when a Record is being created by a {@link Ext.data.Reader Reader}</b>
2422
+ * when the item referenced by the <tt>{@link Ext.data.Field#mapping mapping}</tt> does not exist in the data
2423
+ * object (i.e. undefined). (defaults to "")
2424
+ */
2425
+ defaultValue: "",
2426
+ /**
2427
+ * @cfg {String/Number} mapping
2428
+ * <p>(Optional) A path expression for use by the {@link Ext.data.DataReader} implementation
2429
+ * that is creating the {@link Ext.data.Record Record} to extract the Field value from the data object.
2430
+ * If the path expression is the same as the field name, the mapping may be omitted.</p>
2431
+ * <p>The form of the mapping expression depends on the Reader being used.</p>
2432
+ * <div class="mdetail-params"><ul>
2433
+ * <li>{@link Ext.data.JsonReader}<div class="sub-desc">The mapping is a string containing the javascript
2434
+ * expression to reference the data from an element of the data item's {@link Ext.data.JsonReader#root root} Array. Defaults to the field name.</div></li>
2435
+ * <li>{@link Ext.data.XmlReader}<div class="sub-desc">The mapping is an {@link Ext.DomQuery} path to the data
2436
+ * item relative to the DOM element that represents the {@link Ext.data.XmlReader#record record}. Defaults to the field name.</div></li>
2437
+ * <li>{@link Ext.data.ArrayReader}<div class="sub-desc">The mapping is a number indicating the Array index
2438
+ * of the field's value. Defaults to the field specification's Array position.</div></li>
2439
+ * </ul></div>
2440
+ * <p>If a more complex value extraction strategy is required, then configure the Field with a {@link #convert}
2441
+ * function. This is passed the whole row object, and may interrogate it in whatever way is necessary in order to
2442
+ * return the desired data.</p>
2443
+ */
2444
+ mapping: null,
2445
+ /**
2446
+ * @cfg {Function} sortType
2447
+ * (Optional) A function which converts a Field's value to a comparable value in order to ensure
2448
+ * correct sort ordering. Predefined functions are provided in {@link Ext.data.SortTypes}. A custom
2449
+ * sort example:<pre><code>
2450
+ // current sort after sort we want
2451
+ // +-+------+ +-+------+
2452
+ // |1|First | |1|First |
2453
+ // |2|Last | |3|Second|
2454
+ // |3|Second| |2|Last |
2455
+ // +-+------+ +-+------+
2456
+
2457
+ sortType: function(value) {
2458
+ switch (value.toLowerCase()) // native toLowerCase():
2459
+ {
2460
+ case 'first': return 1;
2461
+ case 'second': return 2;
2462
+ default: return 3;
2463
+ }
2464
+ }
2465
+ * </code></pre>
2466
+ */
2467
+ sortType : null,
2468
+ /**
2469
+ * @cfg {String} sortDir
2470
+ * (Optional) Initial direction to sort (<tt>"ASC"</tt> or <tt>"DESC"</tt>). Defaults to
2471
+ * <tt>"ASC"</tt>.
2472
+ */
2473
+ sortDir : "ASC",
2474
+ /**
2475
+ * @cfg {Boolean} allowBlank
2476
+ * (Optional) Used for validating a {@link Ext.data.Record record}, defaults to <tt>true</tt>.
2477
+ * An empty value here will cause {@link Ext.data.Record}.{@link Ext.data.Record#isValid isValid}
2478
+ * to evaluate to <tt>false</tt>.
2479
+ */
2480
+ allowBlank : true
2481
+ };/**
2482
+ * @class Ext.data.DataReader
2483
+ * Abstract base class for reading structured data from a data source and converting
2484
+ * it into an object containing {@link Ext.data.Record} objects and metadata for use
2485
+ * by an {@link Ext.data.Store}. This class is intended to be extended and should not
2486
+ * be created directly. For existing implementations, see {@link Ext.data.ArrayReader},
2487
+ * {@link Ext.data.JsonReader} and {@link Ext.data.XmlReader}.
2488
+ * @constructor Create a new DataReader
2489
+ * @param {Object} meta Metadata configuration options (implementation-specific).
2490
+ * @param {Array/Object} recordType
2491
+ * <p>Either an Array of {@link Ext.data.Field Field} definition objects (which
2492
+ * will be passed to {@link Ext.data.Record#create}, or a {@link Ext.data.Record Record}
2493
+ * constructor created using {@link Ext.data.Record#create}.</p>
2494
+ */
2495
+ Ext.data.DataReader = function(meta, recordType){
2496
+ /**
2497
+ * This DataReader's configured metadata as passed to the constructor.
2498
+ * @type Mixed
2499
+ * @property meta
2500
+ */
2501
+ this.meta = meta;
2502
+ /**
2503
+ * @cfg {Array/Object} fields
2504
+ * <p>Either an Array of {@link Ext.data.Field Field} definition objects (which
2505
+ * will be passed to {@link Ext.data.Record#create}, or a {@link Ext.data.Record Record}
2506
+ * constructor created from {@link Ext.data.Record#create}.</p>
2507
+ */
2508
+ this.recordType = Ext.isArray(recordType) ?
2509
+ Ext.data.Record.create(recordType) : recordType;
2510
+ };
2511
+
2512
+ Ext.data.DataReader.prototype = {
2513
+
2514
+ /**
2515
+ * Abstract method, overridden in {@link Ext.data.JsonReader}
2516
+ */
2517
+ buildExtractors : Ext.emptyFn,
2518
+
2519
+ /**
2520
+ * Used for un-phantoming a record after a successful database insert. Sets the records pk along with new data from server.
2521
+ * You <b>must</b> return at least the database pk using the idProperty defined in your DataReader configuration. The incoming
2522
+ * data from server will be merged with the data in the local record.
2523
+ * In addition, you <b>must</b> return record-data from the server in the same order received.
2524
+ * Will perform a commit as well, un-marking dirty-fields. Store's "update" event will be suppressed.
2525
+ * @param {Record/Record[]} record The phantom record to be realized.
2526
+ * @param {Object/Object[]} data The new record data to apply. Must include the primary-key from database defined in idProperty field.
2527
+ */
2528
+ realize: function(rs, data){
2529
+ if (Ext.isArray(rs)) {
2530
+ for (var i = rs.length - 1; i >= 0; i--) {
2531
+ // recurse
2532
+ if (Ext.isArray(data)) {
2533
+ this.realize(rs.splice(i,1).shift(), data.splice(i,1).shift());
2534
+ }
2535
+ else {
2536
+ // weird...rs is an array but data isn't?? recurse but just send in the whole invalid data object.
2537
+ // the else clause below will detect !this.isData and throw exception.
2538
+ this.realize(rs.splice(i,1).shift(), data);
2539
+ }
2540
+ }
2541
+ }
2542
+ else {
2543
+ // If rs is NOT an array but data IS, see if data contains just 1 record. If so extract it and carry on.
2544
+ if (Ext.isArray(data) && data.length == 1) {
2545
+ data = data.shift();
2546
+ }
2547
+ if (!this.isData(data)) {
2548
+ // TODO: Let exception-handler choose to commit or not rather than blindly rs.commit() here.
2549
+ //rs.commit();
2550
+ throw new Ext.data.DataReader.Error('realize', rs);
2551
+ }
2552
+ this.buildExtractors();
2553
+ var values = this.extractValues(data, rs.fields.items, rs.fields.items.length);
2554
+ rs.phantom = false; // <-- That's what it's all about
2555
+ rs._phid = rs.id; // <-- copy phantom-id -> _phid, so we can remap in Store#onCreateRecords
2556
+ rs.id = data[this.meta.idProperty];
2557
+ rs.data = values;
2558
+ rs.commit();
2559
+ }
2560
+ },
2561
+
2562
+ /**
2563
+ * Used for updating a non-phantom or "real" record's data with fresh data from server after remote-save.
2564
+ * You <b>must</b> return a complete new record from the server. If you don't, your local record's missing fields
2565
+ * will be populated with the default values specified in your Ext.data.Record.create specification. Without a defaultValue,
2566
+ * local fields will be populated with empty string "". So return your entire record's data after both remote create and update.
2567
+ * In addition, you <b>must</b> return record-data from the server in the same order received.
2568
+ * Will perform a commit as well, un-marking dirty-fields. Store's "update" event will be suppressed as the record receives
2569
+ * a fresh new data-hash.
2570
+ * @param {Record/Record[]} rs
2571
+ * @param {Object/Object[]} data
2572
+ */
2573
+ update : function(rs, data) {
2574
+ if (Ext.isArray(rs)) {
2575
+ for (var i=rs.length-1; i >= 0; i--) {
2576
+ if (Ext.isArray(data)) {
2577
+ this.update(rs.splice(i,1).shift(), data.splice(i,1).shift());
2578
+ }
2579
+ else {
2580
+ // weird...rs is an array but data isn't?? recurse but just send in the whole data object.
2581
+ // the else clause below will detect !this.isData and throw exception.
2582
+ this.update(rs.splice(i,1).shift(), data);
2583
+ }
2584
+ }
2585
+ }
2586
+ else {
2587
+ // If rs is NOT an array but data IS, see if data contains just 1 record. If so extract it and carry on.
2588
+ if (Ext.isArray(data) && data.length == 1) {
2589
+ data = data.shift();
2590
+ }
2591
+ if (!this.isData(data)) {
2592
+ // TODO: create custom Exception class to return record in thrown exception. Allow exception-handler the choice
2593
+ // to commit or not rather than blindly rs.commit() here.
2594
+ rs.commit();
2595
+ throw new Ext.data.DataReader.Error('update', rs);
2596
+ }
2597
+ this.buildExtractors();
2598
+ rs.data = this.extractValues(Ext.apply(rs.data, data), rs.fields.items, rs.fields.items.length);
2599
+ rs.commit();
2600
+ }
2601
+ },
2602
+
2603
+ /**
2604
+ * Returns true if the supplied data-hash <b>looks</b> and quacks like data. Checks to see if it has a key
2605
+ * corresponding to idProperty defined in your DataReader config containing non-empty pk.
2606
+ * @param {Object} data
2607
+ * @return {Boolean}
2608
+ */
2609
+ isData : function(data) {
2610
+ return (data && Ext.isObject(data) && !Ext.isEmpty(data[this.meta.idProperty])) ? true : false;
2611
+ }
2612
+ };
2613
+
2614
+ /**
2615
+ * @class Ext.data.DataReader.Error
2616
+ * @extends Ext.Error
2617
+ * General error class for Ext.data.DataReader
2618
+ */
2619
+ Ext.data.DataReader.Error = Ext.extend(Ext.Error, {
2620
+ constructor : function(message, arg) {
2621
+ this.arg = arg;
2622
+ Ext.Error.call(this, message);
2623
+ },
2624
+ name: 'Ext.data.DataReader'
2625
+ });
2626
+ Ext.apply(Ext.data.DataReader.Error.prototype, {
2627
+ lang : {
2628
+ 'update': "#update received invalid data from server. Please see docs for DataReader#update and review your DataReader configuration.",
2629
+ 'realize': "#realize was called with invalid remote-data. Please see the docs for DataReader#realize and review your DataReader configuration.",
2630
+ 'invalid-response': "#readResponse received an invalid response from the server."
2631
+ }
2632
+ });
2633
+
2634
+
2635
+ /**
2636
+ * @class Ext.data.DataWriter
2637
+ * <p>Ext.data.DataWriter facilitates create, update, and destroy actions between
2638
+ * an Ext.data.Store and a server-side framework. A Writer enabled Store will
2639
+ * automatically manage the Ajax requests to perform CRUD actions on a Store.</p>
2640
+ * <p>Ext.data.DataWriter is an abstract base class which is intended to be extended
2641
+ * and should not be created directly. For existing implementations, see
2642
+ * {@link Ext.data.JsonWriter}.</p>
2643
+ * <p>Creating a writer is simple:</p>
2644
+ * <pre><code>
2645
+ var writer = new Ext.data.JsonWriter();
2646
+ * </code></pre>
2647
+ * <p>The proxy for a writer enabled store can be configured with a simple <code>url</code>:</p>
2648
+ * <pre><code>
2649
+ // Create a standard HttpProxy instance.
2650
+ var proxy = new Ext.data.HttpProxy({
2651
+ url: 'app.php/users'
2652
+ });
2653
+ * </code></pre>
2654
+ * <p>For finer grained control, the proxy may also be configured with an <code>api</code>:</p>
2655
+ * <pre><code>
2656
+ // Use the api specification
2657
+ var proxy = new Ext.data.HttpProxy({
2658
+ api: {
2659
+ read : 'app.php/users/read',
2660
+ create : 'app.php/users/create',
2661
+ update : 'app.php/users/update',
2662
+ destroy : 'app.php/users/destroy'
2663
+ }
2664
+ });
2665
+ * </code></pre>
2666
+ * <p>Creating a Writer enabled store:</p>
2667
+ * <pre><code>
2668
+ var store = new Ext.data.Store({
2669
+ proxy: proxy,
2670
+ reader: reader,
2671
+ writer: writer
2672
+ });
2673
+ * </code></pre>
2674
+ * @constructor Create a new DataWriter
2675
+ * @param {Object} meta Metadata configuration options (implementation-specific)
2676
+ * @param {Object} recordType Either an Array of field definition objects as specified
2677
+ * in {@link Ext.data.Record#create}, or an {@link Ext.data.Record} object created
2678
+ * using {@link Ext.data.Record#create}.
2679
+ */
2680
+ Ext.data.DataWriter = function(config){
2681
+ /**
2682
+ * This DataWriter's configured metadata as passed to the constructor.
2683
+ * @type Mixed
2684
+ * @property meta
2685
+ */
2686
+ Ext.apply(this, config);
2687
+ };
2688
+
2689
+ Ext.data.DataWriter.prototype = {
2690
+
2691
+ /**
2692
+ * @cfg {Boolean} writeAllFields
2693
+ * <tt>false</tt> by default. Set <tt>true</tt> to have DataWriter return ALL fields of a modified
2694
+ * record -- not just those that changed.
2695
+ * <tt>false</tt> to have DataWriter only request modified fields from a record.
2696
+ */
2697
+ writeAllFields : false,
2698
+ /**
2699
+ * @cfg {Boolean} listful
2700
+ * <tt>false</tt> by default. Set <tt>true</tt> to have the DataWriter <b>always</b> write HTTP params as a list,
2701
+ * even when acting upon a single record.
2702
+ */
2703
+ listful : false, // <-- listful is actually not used internally here in DataWriter. @see Ext.data.Store#execute.
2704
+
2705
+ /**
2706
+ * Writes data in preparation for server-write action. Simply proxies to DataWriter#update, DataWriter#create
2707
+ * DataWriter#destroy.
2708
+ * @param {String} action [CREATE|UPDATE|DESTROY]
2709
+ * @param {Object} params The params-hash to write-to
2710
+ * @param {Record/Record[]} rs The recordset write.
2711
+ */
2712
+ write : function(action, params, rs) {
2713
+ this.render(action, rs, params, this[action](rs));
2714
+ },
2715
+
2716
+ /**
2717
+ * abstract method meant to be overridden by all DataWriter extensions. It's the extension's job to apply the "data" to the "params".
2718
+ * The data-object provided to render is populated with data according to the meta-info defined in the user's DataReader config,
2719
+ * @param {String} action [Ext.data.Api.actions.create|read|update|destroy]
2720
+ * @param {Record[]} rs Store recordset
2721
+ * @param {Object} params Http params to be sent to server.
2722
+ * @param {Object} data object populated according to DataReader meta-data.
2723
+ */
2724
+ render : Ext.emptyFn,
2725
+
2726
+ /**
2727
+ * update
2728
+ * @param {Object} p Params-hash to apply result to.
2729
+ * @param {Record/Record[]} rs Record(s) to write
2730
+ * @private
2731
+ */
2732
+ update : function(rs) {
2733
+ var params = {};
2734
+ if (Ext.isArray(rs)) {
2735
+ var data = [],
2736
+ ids = [];
2737
+ Ext.each(rs, function(val){
2738
+ ids.push(val.id);
2739
+ data.push(this.updateRecord(val));
2740
+ }, this);
2741
+ params[this.meta.idProperty] = ids;
2742
+ params[this.meta.root] = data;
2743
+ }
2744
+ else if (rs instanceof Ext.data.Record) {
2745
+ params[this.meta.idProperty] = rs.id;
2746
+ params[this.meta.root] = this.updateRecord(rs);
2747
+ }
2748
+ return params;
2749
+ },
2750
+
2751
+ /**
2752
+ * @cfg {Function} saveRecord Abstract method that should be implemented in all subclasses
2753
+ * (e.g.: {@link Ext.data.JsonWriter#saveRecord JsonWriter.saveRecord}
2754
+ */
2755
+ updateRecord : Ext.emptyFn,
2756
+
2757
+ /**
2758
+ * create
2759
+ * @param {Object} p Params-hash to apply result to.
2760
+ * @param {Record/Record[]} rs Record(s) to write
2761
+ * @private
2762
+ */
2763
+ create : function(rs) {
2764
+ var params = {};
2765
+ if (Ext.isArray(rs)) {
2766
+ var data = [];
2767
+ Ext.each(rs, function(val){
2768
+ data.push(this.createRecord(val));
2769
+ }, this);
2770
+ params[this.meta.root] = data;
2771
+ }
2772
+ else if (rs instanceof Ext.data.Record) {
2773
+ params[this.meta.root] = this.createRecord(rs);
2774
+ }
2775
+ return params;
2776
+ },
2777
+
2778
+ /**
2779
+ * @cfg {Function} createRecord Abstract method that should be implemented in all subclasses
2780
+ * (e.g.: {@link Ext.data.JsonWriter#createRecord JsonWriter.createRecord})
2781
+ */
2782
+ createRecord : Ext.emptyFn,
2783
+
2784
+ /**
2785
+ * destroy
2786
+ * @param {Object} p Params-hash to apply result to.
2787
+ * @param {Record/Record[]} rs Record(s) to write
2788
+ * @private
2789
+ */
2790
+ destroy : function(rs) {
2791
+ var params = {};
2792
+ if (Ext.isArray(rs)) {
2793
+ var data = [],
2794
+ ids = [];
2795
+ Ext.each(rs, function(val){
2796
+ data.push(this.destroyRecord(val));
2797
+ }, this);
2798
+ params[this.meta.root] = data;
2799
+ } else if (rs instanceof Ext.data.Record) {
2800
+ params[this.meta.root] = this.destroyRecord(rs);
2801
+ }
2802
+ return params;
2803
+ },
2804
+
2805
+ /**
2806
+ * @cfg {Function} destroyRecord Abstract method that should be implemented in all subclasses
2807
+ * (e.g.: {@link Ext.data.JsonWriter#destroyRecord JsonWriter.destroyRecord})
2808
+ */
2809
+ destroyRecord : Ext.emptyFn,
2810
+
2811
+ /**
2812
+ * Converts a Record to a hash
2813
+ * @param {Record}
2814
+ * @private
2815
+ */
2816
+ toHash : function(rec) {
2817
+ var map = rec.fields.map,
2818
+ data = {},
2819
+ raw = (this.writeAllFields === false && rec.phantom === false) ? rec.getChanges() : rec.data,
2820
+ m;
2821
+ Ext.iterate(raw, function(prop, value){
2822
+ if((m = map[prop])){
2823
+ data[m.mapping ? m.mapping : m.name] = value;
2824
+ }
2825
+ });
2826
+ data[this.meta.idProperty] = rec.id;
2827
+ return data;
2828
+ }
2829
+ };/**
2830
+ * @class Ext.data.DataProxy
2831
+ * @extends Ext.util.Observable
2832
+ * <p>Abstract base class for implementations which provide retrieval of unformatted data objects.
2833
+ * This class is intended to be extended and should not be created directly. For existing implementations,
2834
+ * see {@link Ext.data.DirectProxy}, {@link Ext.data.HttpProxy}, {@link Ext.data.ScriptTagProxy} and
2835
+ * {@link Ext.data.MemoryProxy}.</p>
2836
+ * <p>DataProxy implementations are usually used in conjunction with an implementation of {@link Ext.data.DataReader}
2837
+ * (of the appropriate type which knows how to parse the data object) to provide a block of
2838
+ * {@link Ext.data.Records} to an {@link Ext.data.Store}.</p>
2839
+ * <p>The parameter to a DataProxy constructor may be an {@link Ext.data.Connection} or can also be the
2840
+ * config object to an {@link Ext.data.Connection}.</p>
2841
+ * <p>Custom implementations must implement either the <code><b>doRequest</b></code> method (preferred) or the
2842
+ * <code>load</code> method (deprecated). See
2843
+ * {@link Ext.data.HttpProxy}.{@link Ext.data.HttpProxy#doRequest doRequest} or
2844
+ * {@link Ext.data.HttpProxy}.{@link Ext.data.HttpProxy#load load} for additional details.</p>
2845
+ * <p><b><u>Example 1</u></b></p>
2846
+ * <pre><code>
2847
+ proxy: new Ext.data.ScriptTagProxy({
2848
+ {@link Ext.data.Connection#url url}: 'http://extjs.com/forum/topics-remote.php'
2849
+ }),
2850
+ * </code></pre>
2851
+ * <p><b><u>Example 2</u></b></p>
2852
+ * <pre><code>
2853
+ proxy : new Ext.data.HttpProxy({
2854
+ {@link Ext.data.Connection#method method}: 'GET',
2855
+ {@link Ext.data.HttpProxy#prettyUrls prettyUrls}: false,
2856
+ {@link Ext.data.Connection#url url}: 'local/default.php', // see options parameter for {@link Ext.Ajax#request}
2857
+ {@link #api}: {
2858
+ // all actions except the following will use above url
2859
+ create : 'local/new.php',
2860
+ update : 'local/update.php'
2861
+ }
2862
+ }),
2863
+ * </code></pre>
2864
+ */
2865
+ Ext.data.DataProxy = function(conn){
2866
+ // make sure we have a config object here to support ux proxies.
2867
+ // All proxies should now send config into superclass constructor.
2868
+ conn = conn || {};
2869
+
2870
+ // This line caused a bug when people use custom Connection object having its own request method.
2871
+ // http://extjs.com/forum/showthread.php?t=67194. Have to set DataProxy config
2872
+ //Ext.applyIf(this, conn);
2873
+
2874
+ this.api = conn.api;
2875
+ this.url = conn.url;
2876
+ this.restful = conn.restful;
2877
+ this.listeners = conn.listeners;
2878
+
2879
+ // deprecated
2880
+ this.prettyUrls = conn.prettyUrls;
2881
+
2882
+ /**
2883
+ * @cfg {Object} api
2884
+ * Specific urls to call on CRUD action methods "read", "create", "update" and "destroy".
2885
+ * Defaults to:<pre><code>
2886
+ api: {
2887
+ read : undefined,
2888
+ create : undefined,
2889
+ update : undefined,
2890
+ destroy : undefined
2891
+ }
2892
+ </code></pre>
2893
+ * <p>If the specific URL for a given CRUD action is undefined, the CRUD action request
2894
+ * will be directed to the configured <tt>{@link Ext.data.Connection#url url}</tt>.</p>
2895
+ * <br><p><b>Note</b>: To modify the URL for an action dynamically the appropriate API
2896
+ * property should be modified before the action is requested using the corresponding before
2897
+ * action event. For example to modify the URL associated with the load action:
2898
+ * <pre><code>
2899
+ // modify the url for the action
2900
+ myStore.on({
2901
+ beforeload: {
2902
+ fn: function (store, options) {
2903
+ // use <tt>{@link Ext.data.HttpProxy#setUrl setUrl}</tt> to change the URL for *just* this request.
2904
+ store.proxy.setUrl('changed1.php');
2905
+
2906
+ // set optional second parameter to true to make this URL change
2907
+ // permanent, applying this URL for all subsequent requests.
2908
+ store.proxy.setUrl('changed1.php', true);
2909
+
2910
+ // manually set the <b>private</b> connection URL.
2911
+ // <b>Warning:</b> Accessing the private URL property should be avoided.
2912
+ // Use the public method <tt>{@link Ext.data.HttpProxy#setUrl setUrl}</tt> instead, shown above.
2913
+ // It should be noted that changing the URL like this will affect
2914
+ // the URL for just this request. Subsequent requests will use the
2915
+ // API or URL defined in your initial proxy configuration.
2916
+ store.proxy.conn.url = 'changed1.php';
2917
+
2918
+ // proxy URL will be superseded by API (only if proxy created to use ajax):
2919
+ // It should be noted that proxy API changes are permanent and will
2920
+ // be used for all subsequent requests.
2921
+ store.proxy.api.load = 'changed2.php';
2922
+
2923
+ // However, altering the proxy API should be done using the public
2924
+ // method <tt>{@link Ext.data.DataProxy#setApi setApi}</tt> instead.
2925
+ store.proxy.setApi('load', 'changed2.php');
2926
+
2927
+ // Or set the entire API with a config-object.
2928
+ // When using the config-object option, you must redefine the <b>entire</b>
2929
+ // API -- not just a specific action of it.
2930
+ store.proxy.setApi({
2931
+ read : 'changed_read.php',
2932
+ create : 'changed_create.php',
2933
+ update : 'changed_update.php',
2934
+ destroy : 'changed_destroy.php'
2935
+ });
2936
+ }
2937
+ }
2938
+ });
2939
+ * </code></pre>
2940
+ * </p>
2941
+ */
2942
+ // Prepare the proxy api. Ensures all API-actions are defined with the Object-form.
2943
+ try {
2944
+ Ext.data.Api.prepare(this);
2945
+ } catch (e) {
2946
+ if (e instanceof Ext.data.Api.Error) {
2947
+ e.toConsole();
2948
+ }
2949
+ }
2950
+
2951
+ this.addEvents(
2952
+ /**
2953
+ * @event exception
2954
+ * <p>Fires if an exception occurs in the Proxy during a remote request.
2955
+ * This event is relayed through a corresponding
2956
+ * {@link Ext.data.Store}.{@link Ext.data.Store#exception exception},
2957
+ * so any Store instance may observe this event.
2958
+ * This event can be fired for one of two reasons:</p>
2959
+ * <div class="mdetail-params"><ul>
2960
+ * <li>remote-request <b>failed</b> : <div class="sub-desc">
2961
+ * The server did not return status === 200.
2962
+ * </div></li>
2963
+ * <li>remote-request <b>succeeded</b> : <div class="sub-desc">
2964
+ * The remote-request succeeded but the reader could not read the response.
2965
+ * This means the server returned data, but the configured Reader threw an
2966
+ * error while reading the response. In this case, this event will be
2967
+ * raised and the caught error will be passed along into this event.
2968
+ * </div></li>
2969
+ * </ul></div>
2970
+ * <br><p>This event fires with two different contexts based upon the 2nd
2971
+ * parameter <tt>type [remote|response]</tt>. The first four parameters
2972
+ * are identical between the two contexts -- only the final two parameters
2973
+ * differ.</p>
2974
+ * @param {DataProxy} this The proxy that sent the request
2975
+ * @param {String} type
2976
+ * <p>The value of this parameter will be either <tt>'response'</tt> or <tt>'remote'</tt>.</p>
2977
+ * <div class="mdetail-params"><ul>
2978
+ * <li><b><tt>'response'</tt></b> : <div class="sub-desc">
2979
+ * <p>An <b>invalid</b> response from the server was returned: either 404,
2980
+ * 500 or the response meta-data does not match that defined in the DataReader
2981
+ * (e.g.: root, idProperty, successProperty).</p>
2982
+ * </div></li>
2983
+ * <li><b><tt>'remote'</tt></b> : <div class="sub-desc">
2984
+ * <p>A <b>valid</b> response was returned from the server having
2985
+ * successProperty === false. This response might contain an error-message
2986
+ * sent from the server. For example, the user may have failed
2987
+ * authentication/authorization or a database validation error occurred.</p>
2988
+ * </div></li>
2989
+ * </ul></div>
2990
+ * @param {String} action Name of the action (see {@link Ext.data.Api#actions}.
2991
+ * @param {Object} options The options for the action that were specified in the {@link #request}.
2992
+ * @param {Object} response
2993
+ * <p>The value of this parameter depends on the value of the <code>type</code> parameter:</p>
2994
+ * <div class="mdetail-params"><ul>
2995
+ * <li><b><tt>'response'</tt></b> : <div class="sub-desc">
2996
+ * <p>The raw browser response object (e.g.: XMLHttpRequest)</p>
2997
+ * </div></li>
2998
+ * <li><b><tt>'remote'</tt></b> : <div class="sub-desc">
2999
+ * <p>The decoded response object sent from the server.</p>
3000
+ * </div></li>
3001
+ * </ul></div>
3002
+ * @param {Mixed} arg
3003
+ * <p>The type and value of this parameter depends on the value of the <code>type</code> parameter:</p>
3004
+ * <div class="mdetail-params"><ul>
3005
+ * <li><b><tt>'response'</tt></b> : Error<div class="sub-desc">
3006
+ * <p>The JavaScript Error object caught if the configured Reader could not read the data.
3007
+ * If the remote request returns success===false, this parameter will be null.</p>
3008
+ * </div></li>
3009
+ * <li><b><tt>'remote'</tt></b> : Record/Record[]<div class="sub-desc">
3010
+ * <p>This parameter will only exist if the <tt>action</tt> was a <b>write</b> action
3011
+ * (Ext.data.Api.actions.create|update|destroy).</p>
3012
+ * </div></li>
3013
+ * </ul></div>
3014
+ */
3015
+ 'exception',
3016
+ /**
3017
+ * @event beforeload
3018
+ * Fires before a request to retrieve a data object.
3019
+ * @param {DataProxy} this The proxy for the request
3020
+ * @param {Object} params The params object passed to the {@link #request} function
3021
+ */
3022
+ 'beforeload',
3023
+ /**
3024
+ * @event load
3025
+ * Fires before the load method's callback is called.
3026
+ * @param {DataProxy} this The proxy for the request
3027
+ * @param {Object} o The request transaction object
3028
+ * @param {Object} options The callback's <tt>options</tt> property as passed to the {@link #request} function
3029
+ */
3030
+ 'load',
3031
+ /**
3032
+ * @event loadexception
3033
+ * <p>This event is <b>deprecated</b>. The signature of the loadexception event
3034
+ * varies depending on the proxy, use the catch-all {@link #exception} event instead.
3035
+ * This event will fire in addition to the {@link #exception} event.</p>
3036
+ * @param {misc} misc See {@link #exception}.
3037
+ * @deprecated
3038
+ */
3039
+ 'loadexception',
3040
+ /**
3041
+ * @event beforewrite
3042
+ * Fires before a request is generated for one of the actions Ext.data.Api.actions.create|update|destroy
3043
+ * @param {DataProxy} this The proxy for the request
3044
+ * @param {String} action [Ext.data.Api.actions.create|update|destroy]
3045
+ * @param {Record/Array[Record]} rs The Record(s) to create|update|destroy.
3046
+ * @param {Object} params The request <code>params</code> object. Edit <code>params</code> to add parameters to the request.
3047
+ */
3048
+ 'beforewrite',
3049
+ /**
3050
+ * @event write
3051
+ * Fires before the request-callback is called
3052
+ * @param {DataProxy} this The proxy that sent the request
3053
+ * @param {String} action [Ext.data.Api.actions.create|upate|destroy]
3054
+ * @param {Object} data The data object extracted from the server-response
3055
+ * @param {Object} response The decoded response from server
3056
+ * @param {Record/Record{}} rs The records from Store
3057
+ * @param {Object} options The callback's <tt>options</tt> property as passed to the {@link #request} function
3058
+ */
3059
+ 'write'
3060
+ );
3061
+ Ext.data.DataProxy.superclass.constructor.call(this);
3062
+ };
3063
+
3064
+ Ext.extend(Ext.data.DataProxy, Ext.util.Observable, {
3065
+ /**
3066
+ * @cfg {Boolean} restful
3067
+ * <p>Defaults to <tt>false</tt>. Set to <tt>true</tt> to operate in a RESTful manner.</p>
3068
+ * <br><p> Note: this parameter will automatically be set to <tt>true</tt> if the
3069
+ * {@link Ext.data.Store} it is plugged into is set to <code>restful: true</code>. If the
3070
+ * Store is RESTful, there is no need to set this option on the proxy.</p>
3071
+ * <br><p>RESTful implementations enable the serverside framework to automatically route
3072
+ * actions sent to one url based upon the HTTP method, for example:
3073
+ * <pre><code>
3074
+ store: new Ext.data.Store({
3075
+ restful: true,
3076
+ proxy: new Ext.data.HttpProxy({url:'/users'}); // all requests sent to /users
3077
+ ...
3078
+ )}
3079
+ * </code></pre>
3080
+ * There is no <code>{@link #api}</code> specified in the configuration of the proxy,
3081
+ * all requests will be marshalled to a single RESTful url (/users) so the serverside
3082
+ * framework can inspect the HTTP Method and act accordingly:
3083
+ * <pre>
3084
+ <u>Method</u> <u>url</u> <u>action</u>
3085
+ POST /users create
3086
+ GET /users read
3087
+ PUT /users/23 update
3088
+ DESTROY /users/23 delete
3089
+ * </pre></p>
3090
+ */
3091
+ restful: false,
3092
+
3093
+ /**
3094
+ * <p>Redefines the Proxy's API or a single action of an API. Can be called with two method signatures.</p>
3095
+ * <p>If called with an object as the only parameter, the object should redefine the <b>entire</b> API, e.g.:</p><pre><code>
3096
+ proxy.setApi({
3097
+ read : '/users/read',
3098
+ create : '/users/create',
3099
+ update : '/users/update',
3100
+ destroy : '/users/destroy'
3101
+ });
3102
+ </code></pre>
3103
+ * <p>If called with two parameters, the first parameter should be a string specifying the API action to
3104
+ * redefine and the second parameter should be the URL (or function if using DirectProxy) to call for that action, e.g.:</p><pre><code>
3105
+ proxy.setApi(Ext.data.Api.actions.read, '/users/new_load_url');
3106
+ </code></pre>
3107
+ * @param {String/Object} api An API specification object, or the name of an action.
3108
+ * @param {String/Function} url The URL (or function if using DirectProxy) to call for the action.
3109
+ */
3110
+ setApi : function() {
3111
+ if (arguments.length == 1) {
3112
+ var valid = Ext.data.Api.isValid(arguments[0]);
3113
+ if (valid === true) {
3114
+ this.api = arguments[0];
3115
+ }
3116
+ else {
3117
+ throw new Ext.data.Api.Error('invalid', valid);
3118
+ }
3119
+ }
3120
+ else if (arguments.length == 2) {
3121
+ if (!Ext.data.Api.isAction(arguments[0])) {
3122
+ throw new Ext.data.Api.Error('invalid', arguments[0]);
3123
+ }
3124
+ this.api[arguments[0]] = arguments[1];
3125
+ }
3126
+ Ext.data.Api.prepare(this);
3127
+ },
3128
+
3129
+ /**
3130
+ * Returns true if the specified action is defined as a unique action in the api-config.
3131
+ * request. If all API-actions are routed to unique urls, the xaction parameter is unecessary. However, if no api is defined
3132
+ * and all Proxy actions are routed to DataProxy#url, the server-side will require the xaction parameter to perform a switch to
3133
+ * the corresponding code for CRUD action.
3134
+ * @param {String [Ext.data.Api.CREATE|READ|UPDATE|DESTROY]} action
3135
+ * @return {Boolean}
3136
+ */
3137
+ isApiAction : function(action) {
3138
+ return (this.api[action]) ? true : false;
3139
+ },
3140
+
3141
+ /**
3142
+ * All proxy actions are executed through this method. Automatically fires the "before" + action event
3143
+ * @param {String} action Name of the action
3144
+ * @param {Ext.data.Record/Ext.data.Record[]/null} rs Will be null when action is 'load'
3145
+ * @param {Object} params
3146
+ * @param {Ext.data.DataReader} reader
3147
+ * @param {Function} callback
3148
+ * @param {Object} scope Scope with which to call the callback (defaults to the Proxy object)
3149
+ * @param {Object} options Any options specified for the action (e.g. see {@link Ext.data.Store#load}.
3150
+ */
3151
+ request : function(action, rs, params, reader, callback, scope, options) {
3152
+ if (!this.api[action] && !this.load) {
3153
+ throw new Ext.data.DataProxy.Error('action-undefined', action);
3154
+ }
3155
+ params = params || {};
3156
+ if ((action === Ext.data.Api.actions.read) ? this.fireEvent("beforeload", this, params) : this.fireEvent("beforewrite", this, action, rs, params) !== false) {
3157
+ this.doRequest.apply(this, arguments);
3158
+ }
3159
+ else {
3160
+ callback.call(scope || this, null, options, false);
3161
+ }
3162
+ },
3163
+
3164
+
3165
+ /**
3166
+ * <b>Deprecated</b> load method using old method signature. See {@doRequest} for preferred method.
3167
+ * @deprecated
3168
+ * @param {Object} params
3169
+ * @param {Object} reader
3170
+ * @param {Object} callback
3171
+ * @param {Object} scope
3172
+ * @param {Object} arg
3173
+ */
3174
+ load : null,
3175
+
3176
+ /**
3177
+ * @cfg {Function} doRequest Abstract method that should be implemented in all subclasses
3178
+ * (e.g.: {@link Ext.data.HttpProxy#doRequest HttpProxy.doRequest},
3179
+ * {@link Ext.data.DirectProxy#doRequest DirectProxy.doRequest}).
3180
+ */
3181
+ doRequest : function(action, rs, params, reader, callback, scope, options) {
3182
+ // default implementation of doRequest for backwards compatibility with 2.0 proxies.
3183
+ // If we're executing here, the action is probably "load".
3184
+ // Call with the pre-3.0 method signature.
3185
+ this.load(params, reader, callback, scope, options);
3186
+ },
3187
+
3188
+ /**
3189
+ * buildUrl
3190
+ * Sets the appropriate url based upon the action being executed. If restful is true, and only a single record is being acted upon,
3191
+ * url will be built Rails-style, as in "/controller/action/32". restful will aply iff the supplied record is an
3192
+ * instance of Ext.data.Record rather than an Array of them.
3193
+ * @param {String} action The api action being executed [read|create|update|destroy]
3194
+ * @param {Ext.data.Record/Array[Ext.data.Record]} The record or Array of Records being acted upon.
3195
+ * @return {String} url
3196
+ * @private
3197
+ */
3198
+ buildUrl : function(action, record) {
3199
+ record = record || null;
3200
+ var url = (this.api[action]) ? this.api[action].url : this.url;
3201
+ if (!url) {
3202
+ throw new Ext.data.Api.Error('invalid-url', action);
3203
+ }
3204
+
3205
+ var format = null;
3206
+ var m = url.match(/(.*)(\.\w+)$/); // <-- look for urls with "provides" suffix, e.g.: /users.json, /users.xml, etc
3207
+ if (m) {
3208
+ format = m[2];
3209
+ url = m[1];
3210
+ }
3211
+ // prettyUrls is deprectated in favor of restful-config
3212
+ if ((this.prettyUrls === true || this.restful === true) && record instanceof Ext.data.Record && !record.phantom) {
3213
+ url += '/' + record.id;
3214
+ }
3215
+ if (format) { // <-- append the request format if exists (ie: /users/update/69[.json])
3216
+ url += format;
3217
+ }
3218
+ return url;
3219
+ },
3220
+
3221
+ /**
3222
+ * Destroys the proxy by purging any event listeners and cancelling any active requests.
3223
+ */
3224
+ destroy: function(){
3225
+ this.purgeListeners();
3226
+ }
3227
+ });
3228
+
3229
+ /**
3230
+ * @class Ext.data.DataProxy.Error
3231
+ * @extends Ext.Error
3232
+ * DataProxy Error extension.
3233
+ * constructor
3234
+ * @param {String} name
3235
+ * @param {Record/Array[Record]/Array}
3236
+ */
3237
+ Ext.data.DataProxy.Error = Ext.extend(Ext.Error, {
3238
+ constructor : function(message, arg) {
3239
+ this.arg = arg;
3240
+ Ext.Error.call(this, message);
3241
+ },
3242
+ name: 'Ext.data.DataProxy'
3243
+ });
3244
+ Ext.apply(Ext.data.DataProxy.Error.prototype, {
3245
+ lang: {
3246
+ 'action-undefined': "DataProxy attempted to execute an API-action but found an undefined url / function. Please review your Proxy url/api-configuration.",
3247
+ 'api-invalid': 'Recieved an invalid API-configuration. Please ensure your proxy API-configuration contains only the actions from Ext.data.Api.actions.'
3248
+ }
3249
+ });
3250
+ /**
3251
+ * @class Ext.data.ScriptTagProxy
3252
+ * @extends Ext.data.DataProxy
3253
+ * An implementation of Ext.data.DataProxy that reads a data object from a URL which may be in a domain
3254
+ * other than the originating domain of the running page.<br>
3255
+ * <p>
3256
+ * <b>Note that if you are retrieving data from a page that is in a domain that is NOT the same as the originating domain
3257
+ * of the running page, you must use this class, rather than HttpProxy.</b><br>
3258
+ * <p>
3259
+ * The content passed back from a server resource requested by a ScriptTagProxy <b>must</b> be executable JavaScript
3260
+ * source code because it is used as the source inside a &lt;script> tag.<br>
3261
+ * <p>
3262
+ * In order for the browser to process the returned data, the server must wrap the data object
3263
+ * with a call to a callback function, the name of which is passed as a parameter by the ScriptTagProxy.
3264
+ * Below is a Java example for a servlet which returns data for either a ScriptTagProxy, or an HttpProxy
3265
+ * depending on whether the callback name was passed:
3266
+ * <p>
3267
+ * <pre><code>
3268
+ boolean scriptTag = false;
3269
+ String cb = request.getParameter("callback");
3270
+ if (cb != null) {
3271
+ scriptTag = true;
3272
+ response.setContentType("text/javascript");
3273
+ } else {
3274
+ response.setContentType("application/x-json");
3275
+ }
3276
+ Writer out = response.getWriter();
3277
+ if (scriptTag) {
3278
+ out.write(cb + "(");
3279
+ }
3280
+ out.print(dataBlock.toJsonString());
3281
+ if (scriptTag) {
3282
+ out.write(");");
3283
+ }
3284
+ </code></pre>
3285
+ *
3286
+ * @constructor
3287
+ * @param {Object} config A configuration object.
3288
+ */
3289
+ Ext.data.ScriptTagProxy = function(config){
3290
+ Ext.apply(this, config);
3291
+
3292
+ Ext.data.ScriptTagProxy.superclass.constructor.call(this, config);
3293
+
3294
+ this.head = document.getElementsByTagName("head")[0];
3295
+
3296
+ /**
3297
+ * @event loadexception
3298
+ * <b>Deprecated</b> in favor of 'exception' event.
3299
+ * Fires if an exception occurs in the Proxy during data loading. This event can be fired for one of two reasons:
3300
+ * <ul><li><b>The load call timed out.</b> This means the load callback did not execute within the time limit
3301
+ * specified by {@link #timeout}. In this case, this event will be raised and the
3302
+ * fourth parameter (read error) will be null.</li>
3303
+ * <li><b>The load succeeded but the reader could not read the response.</b> This means the server returned
3304
+ * data, but the configured Reader threw an error while reading the data. In this case, this event will be
3305
+ * raised and the caught error will be passed along as the fourth parameter of this event.</li></ul>
3306
+ * Note that this event is also relayed through {@link Ext.data.Store}, so you can listen for it directly
3307
+ * on any Store instance.
3308
+ * @param {Object} this
3309
+ * @param {Object} options The loading options that were specified (see {@link #load} for details). If the load
3310
+ * call timed out, this parameter will be null.
3311
+ * @param {Object} arg The callback's arg object passed to the {@link #load} function
3312
+ * @param {Error} e The JavaScript Error object caught if the configured Reader could not read the data.
3313
+ * If the remote request returns success: false, this parameter will be null.
3314
+ */
3315
+ };
3316
+
3317
+ Ext.data.ScriptTagProxy.TRANS_ID = 1000;
3318
+
3319
+ Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {
3320
+ /**
3321
+ * @cfg {String} url The URL from which to request the data object.
3322
+ */
3323
+ /**
3324
+ * @cfg {Number} timeout (optional) The number of milliseconds to wait for a response. Defaults to 30 seconds.
3325
+ */
3326
+ timeout : 30000,
3327
+ /**
3328
+ * @cfg {String} callbackParam (Optional) The name of the parameter to pass to the server which tells
3329
+ * the server the name of the callback function set up by the load call to process the returned data object.
3330
+ * Defaults to "callback".<p>The server-side processing must read this parameter value, and generate
3331
+ * javascript output which calls this named function passing the data object as its only parameter.
3332
+ */
3333
+ callbackParam : "callback",
3334
+ /**
3335
+ * @cfg {Boolean} nocache (optional) Defaults to true. Disable caching by adding a unique parameter
3336
+ * name to the request.
3337
+ */
3338
+ nocache : true,
3339
+
3340
+ /**
3341
+ * HttpProxy implementation of DataProxy#doRequest
3342
+ * @param {String} action
3343
+ * @param {Ext.data.Record/Ext.data.Record[]} rs If action is <tt>read</tt>, rs will be null
3344
+ * @param {Object} params An object containing properties which are to be used as HTTP parameters
3345
+ * for the request to the remote server.
3346
+ * @param {Ext.data.DataReader} reader The Reader object which converts the data
3347
+ * object into a block of Ext.data.Records.
3348
+ * @param {Function} callback The function into which to pass the block of Ext.data.Records.
3349
+ * The function must be passed <ul>
3350
+ * <li>The Record block object</li>
3351
+ * <li>The "arg" argument from the load function</li>
3352
+ * <li>A boolean success indicator</li>
3353
+ * </ul>
3354
+ * @param {Object} scope The scope in which to call the callback
3355
+ * @param {Object} arg An optional argument which is passed to the callback as its second parameter.
3356
+ */
3357
+ doRequest : function(action, rs, params, reader, callback, scope, arg) {
3358
+ var p = Ext.urlEncode(Ext.apply(params, this.extraParams));
3359
+
3360
+ var url = this.buildUrl(action, rs);
3361
+ if (!url) {
3362
+ throw new Ext.data.Api.Error('invalid-url', url);
3363
+ }
3364
+ url = Ext.urlAppend(url, p);
3365
+
3366
+ if(this.nocache){
3367
+ url = Ext.urlAppend(url, '_dc=' + (new Date().getTime()));
3368
+ }
3369
+ var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;
3370
+ var trans = {
3371
+ id : transId,
3372
+ action: action,
3373
+ cb : "stcCallback"+transId,
3374
+ scriptId : "stcScript"+transId,
3375
+ params : params,
3376
+ arg : arg,
3377
+ url : url,
3378
+ callback : callback,
3379
+ scope : scope,
3380
+ reader : reader
3381
+ };
3382
+ window[trans.cb] = this.createCallback(action, rs, trans);
3383
+ url += String.format("&{0}={1}", this.callbackParam, trans.cb);
3384
+ if(this.autoAbort !== false){
3385
+ this.abort();
3386
+ }
3387
+
3388
+ trans.timeoutId = this.handleFailure.defer(this.timeout, this, [trans]);
3389
+
3390
+ var script = document.createElement("script");
3391
+ script.setAttribute("src", url);
3392
+ script.setAttribute("type", "text/javascript");
3393
+ script.setAttribute("id", trans.scriptId);
3394
+ this.head.appendChild(script);
3395
+
3396
+ this.trans = trans;
3397
+ },
3398
+
3399
+ // @private createCallback
3400
+ createCallback : function(action, rs, trans) {
3401
+ var self = this;
3402
+ return function(res) {
3403
+ self.trans = false;
3404
+ self.destroyTrans(trans, true);
3405
+ if (action === Ext.data.Api.actions.read) {
3406
+ self.onRead.call(self, action, trans, res);
3407
+ } else {
3408
+ self.onWrite.call(self, action, trans, res, rs);
3409
+ }
3410
+ };
3411
+ },
3412
+ /**
3413
+ * Callback for read actions
3414
+ * @param {String} action [Ext.data.Api.actions.create|read|update|destroy]
3415
+ * @param {Object} trans The request transaction object
3416
+ * @param {Object} res The server response
3417
+ * @private
3418
+ */
3419
+ onRead : function(action, trans, res) {
3420
+ var result;
3421
+ try {
3422
+ result = trans.reader.readRecords(res);
3423
+ }catch(e){
3424
+ // @deprecated: fire loadexception
3425
+ this.fireEvent("loadexception", this, trans, res, e);
3426
+
3427
+ this.fireEvent('exception', this, 'response', action, trans, res, e);
3428
+ trans.callback.call(trans.scope||window, null, trans.arg, false);
3429
+ return;
3430
+ }
3431
+ if (result.success === false) {
3432
+ // @deprecated: fire old loadexception for backwards-compat.
3433
+ this.fireEvent('loadexception', this, trans, res);
3434
+
3435
+ this.fireEvent('exception', this, 'remote', action, trans, res, null);
3436
+ } else {
3437
+ this.fireEvent("load", this, res, trans.arg);
3438
+ }
3439
+ trans.callback.call(trans.scope||window, result, trans.arg, result.success);
3440
+ },
3441
+ /**
3442
+ * Callback for write actions
3443
+ * @param {String} action [Ext.data.Api.actions.create|read|update|destroy]
3444
+ * @param {Object} trans The request transaction object
3445
+ * @param {Object} res The server response
3446
+ * @private
3447
+ */
3448
+ onWrite : function(action, trans, res, rs) {
3449
+ var reader = trans.reader;
3450
+ try {
3451
+ // though we already have a response object here in STP, run through readResponse to catch any meta-data exceptions.
3452
+ reader.readResponse(action, res);
3453
+ } catch (e) {
3454
+ this.fireEvent('exception', this, 'response', action, trans, res, e);
3455
+ trans.callback.call(trans.scope||window, null, res, false);
3456
+ return;
3457
+ }
3458
+ if(!res[reader.meta.successProperty] === true){
3459
+ this.fireEvent('exception', this, 'remote', action, trans, res, rs);
3460
+ trans.callback.call(trans.scope||window, null, res, false);
3461
+ return;
3462
+ }
3463
+ this.fireEvent("write", this, action, res[reader.meta.root], res, rs, trans.arg );
3464
+ trans.callback.call(trans.scope||window, res[reader.meta.root], res, true);
3465
+ },
3466
+
3467
+ // private
3468
+ isLoading : function(){
3469
+ return this.trans ? true : false;
3470
+ },
3471
+
3472
+ /**
3473
+ * Abort the current server request.
3474
+ */
3475
+ abort : function(){
3476
+ if(this.isLoading()){
3477
+ this.destroyTrans(this.trans);
3478
+ }
3479
+ },
3480
+
3481
+ // private
3482
+ destroyTrans : function(trans, isLoaded){
3483
+ this.head.removeChild(document.getElementById(trans.scriptId));
3484
+ clearTimeout(trans.timeoutId);
3485
+ if(isLoaded){
3486
+ window[trans.cb] = undefined;
3487
+ try{
3488
+ delete window[trans.cb];
3489
+ }catch(e){}
3490
+ }else{
3491
+ // if hasn't been loaded, wait for load to remove it to prevent script error
3492
+ window[trans.cb] = function(){
3493
+ window[trans.cb] = undefined;
3494
+ try{
3495
+ delete window[trans.cb];
3496
+ }catch(e){}
3497
+ };
3498
+ }
3499
+ },
3500
+
3501
+ // private
3502
+ handleFailure : function(trans){
3503
+ this.trans = false;
3504
+ this.destroyTrans(trans, false);
3505
+ if (trans.action === Ext.data.Api.actions.read) {
3506
+ // @deprecated firing loadexception
3507
+ this.fireEvent("loadexception", this, null, trans.arg);
3508
+ }
3509
+
3510
+ this.fireEvent('exception', this, 'response', trans.action, {
3511
+ response: null,
3512
+ options: trans.arg
3513
+ });
3514
+ trans.callback.call(trans.scope||window, null, trans.arg, false);
3515
+ },
3516
+
3517
+ // inherit docs
3518
+ destroy: function(){
3519
+ this.abort();
3520
+ Ext.data.ScriptTagProxy.superclass.destroy.call(this);
3521
+ }
3522
+ });/**
3523
+ * @class Ext.data.HttpProxy
3524
+ * @extends Ext.data.DataProxy
3525
+ * <p>An implementation of {@link Ext.data.DataProxy} that processes data requests within the same
3526
+ * domain of the originating page.</p>
3527
+ * <p><b>Note</b>: this class cannot be used to retrieve data from a domain other
3528
+ * than the domain from which the running page was served. For cross-domain requests, use a
3529
+ * {@link Ext.data.ScriptTagProxy ScriptTagProxy}.</p>
3530
+ * <p>Be aware that to enable the browser to parse an XML document, the server must set
3531
+ * the Content-Type header in the HTTP response to "<tt>text/xml</tt>".</p>
3532
+ * @constructor
3533
+ * @param {Object} conn
3534
+ * An {@link Ext.data.Connection} object, or options parameter to {@link Ext.Ajax#request}.
3535
+ * <p>Note that if this HttpProxy is being used by a (@link Ext.data.Store Store}, then the
3536
+ * Store's call to {@link #load} will override any specified <tt>callback</tt> and <tt>params</tt>
3537
+ * options. In this case, use the Store's {@link Ext.data.Store#events events} to modify parameters,
3538
+ * or react to loading events. The Store's {@link Ext.data.Store#baseParams baseParams} may also be
3539
+ * used to pass parameters known at instantiation time.</p>
3540
+ * <p>If an options parameter is passed, the singleton {@link Ext.Ajax} object will be used to make
3541
+ * the request.</p>
3542
+ */
3543
+ Ext.data.HttpProxy = function(conn){
3544
+ Ext.data.HttpProxy.superclass.constructor.call(this, conn);
3545
+
3546
+ /**
3547
+ * The Connection object (Or options parameter to {@link Ext.Ajax#request}) which this HttpProxy
3548
+ * uses to make requests to the server. Properties of this object may be changed dynamically to
3549
+ * change the way data is requested.
3550
+ * @property
3551
+ */
3552
+ this.conn = conn;
3553
+
3554
+ // nullify the connection url. The url param has been copied to 'this' above. The connection
3555
+ // url will be set during each execution of doRequest when buildUrl is called. This makes it easier for users to override the
3556
+ // connection url during beforeaction events (ie: beforeload, beforesave, etc). The connection url will be nullified
3557
+ // after each request as well. Url is always re-defined during doRequest.
3558
+ this.conn.url = null;
3559
+
3560
+ this.useAjax = !conn || !conn.events;
3561
+
3562
+ //private. A hash containing active requests, keyed on action [Ext.data.Api.actions.create|read|update|destroy]
3563
+ var actions = Ext.data.Api.actions;
3564
+ this.activeRequest = {};
3565
+ for (var verb in actions) {
3566
+ this.activeRequest[actions[verb]] = undefined;
3567
+ }
3568
+ };
3569
+
3570
+ Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
3571
+ /**
3572
+ * @cfg {Boolean} restful
3573
+ * <p>If set to <tt>true</tt>, a {@link Ext.data.Record#phantom non-phantom} record's
3574
+ * {@link Ext.data.Record#id id} will be appended to the url (defaults to <tt>false</tt>).</p><br>
3575
+ * <p>The url is built based upon the action being executed <tt>[load|create|save|destroy]</tt>
3576
+ * using the commensurate <tt>{@link #api}</tt> property, or if undefined default to the
3577
+ * configured {@link Ext.data.Store}.{@link Ext.data.Store#url url}.</p><br>
3578
+ * <p>Some MVC (e.g., Ruby on Rails, Merb and Django) support this style of segment based urls
3579
+ * where the segments in the URL follow the Model-View-Controller approach.</p><pre><code>
3580
+ * someSite.com/controller/action/id
3581
+ * </code></pre>
3582
+ * Where the segments in the url are typically:<div class="mdetail-params"><ul>
3583
+ * <li>The first segment : represents the controller class that should be invoked.</li>
3584
+ * <li>The second segment : represents the class function, or method, that should be called.</li>
3585
+ * <li>The third segment : represents the ID (a variable typically passed to the method).</li>
3586
+ * </ul></div></p>
3587
+ * <p>For example:</p>
3588
+ * <pre><code>
3589
+ api: {
3590
+ load : '/controller/load',
3591
+ create : '/controller/new', // Server MUST return idProperty of new record
3592
+ save : '/controller/update',
3593
+ destroy : '/controller/destroy_action'
3594
+ }
3595
+
3596
+ // Alternatively, one can use the object-form to specify each API-action
3597
+ api: {
3598
+ load: {url: 'read.php', method: 'GET'},
3599
+ create: 'create.php',
3600
+ destroy: 'destroy.php',
3601
+ save: 'update.php'
3602
+ }
3603
+ */
3604
+
3605
+ /**
3606
+ * Return the {@link Ext.data.Connection} object being used by this Proxy.
3607
+ * @return {Connection} The Connection object. This object may be used to subscribe to events on
3608
+ * a finer-grained basis than the DataProxy events.
3609
+ */
3610
+ getConnection : function() {
3611
+ return this.useAjax ? Ext.Ajax : this.conn;
3612
+ },
3613
+
3614
+ /**
3615
+ * Used for overriding the url used for a single request. Designed to be called during a beforeaction event. Calling setUrl
3616
+ * will override any urls set via the api configuration parameter. Set the optional parameter makePermanent to set the url for
3617
+ * all subsequent requests. If not set to makePermanent, the next request will use the same url or api configuration defined
3618
+ * in the initial proxy configuration.
3619
+ * @param {String} url
3620
+ * @param {Boolean} makePermanent (Optional) [false]
3621
+ *
3622
+ * (e.g.: beforeload, beforesave, etc).
3623
+ */
3624
+ setUrl : function(url, makePermanent) {
3625
+ this.conn.url = url;
3626
+ if (makePermanent === true) {
3627
+ this.url = url;
3628
+ Ext.data.Api.prepare(this);
3629
+ }
3630
+ },
3631
+
3632
+ /**
3633
+ * HttpProxy implementation of DataProxy#doRequest
3634
+ * @param {String} action The crud action type (create, read, update, destroy)
3635
+ * @param {Ext.data.Record/Ext.data.Record[]} rs If action is load, rs will be null
3636
+ * @param {Object} params An object containing properties which are to be used as HTTP parameters
3637
+ * for the request to the remote server.
3638
+ * @param {Ext.data.DataReader} reader The Reader object which converts the data
3639
+ * object into a block of Ext.data.Records.
3640
+ * @param {Function} callback
3641
+ * <div class="sub-desc"><p>A function to be called after the request.
3642
+ * The <tt>callback</tt> is passed the following arguments:<ul>
3643
+ * <li><tt>r</tt> : Ext.data.Record[] The block of Ext.data.Records.</li>
3644
+ * <li><tt>options</tt>: Options object from the action request</li>
3645
+ * <li><tt>success</tt>: Boolean success indicator</li></ul></p></div>
3646
+ * @param {Object} scope The scope in which to call the callback
3647
+ * @param {Object} arg An optional argument which is passed to the callback as its second parameter.
3648
+ */
3649
+ doRequest : function(action, rs, params, reader, cb, scope, arg) {
3650
+ var o = {
3651
+ method: (this.api[action]) ? this.api[action]['method'] : undefined,
3652
+ request: {
3653
+ callback : cb,
3654
+ scope : scope,
3655
+ arg : arg
3656
+ },
3657
+ reader: reader,
3658
+ callback : this.createCallback(action, rs),
3659
+ scope: this
3660
+ };
3661
+ // Sample the request data: If it's an object, then it hasn't been json-encoded yet.
3662
+ // Transmit data using jsonData config of Ext.Ajax.request
3663
+ if (typeof(params[reader.meta.root]) === 'object') {
3664
+ o.jsonData = params;
3665
+ } else {
3666
+ o.params = params || {};
3667
+ }
3668
+ // Set the connection url. If this.conn.url is not null here,
3669
+ // the user may have overridden the url during a beforeaction event-handler.
3670
+ // this.conn.url is nullified after each request.
3671
+ if (this.conn.url === null) {
3672
+ this.conn.url = this.buildUrl(action, rs);
3673
+ }
3674
+ else if (this.restful === true && rs instanceof Ext.data.Record && !rs.phantom) {
3675
+ this.conn.url += '/' + rs.id;
3676
+ }
3677
+ if(this.useAjax){
3678
+
3679
+ Ext.applyIf(o, this.conn);
3680
+
3681
+ // If a currently running request is found for this action, abort it.
3682
+ if (this.activeRequest[action]) {
3683
+ // Disabled aborting activeRequest while implementing REST. activeRequest[action] will have to become an array
3684
+ //Ext.Ajax.abort(this.activeRequest[action]);
3685
+ }
3686
+ this.activeRequest[action] = Ext.Ajax.request(o);
3687
+ }else{
3688
+ this.conn.request(o);
3689
+ }
3690
+ // request is sent, nullify the connection url in preparation for the next request
3691
+ this.conn.url = null;
3692
+ },
3693
+
3694
+ /**
3695
+ * Returns a callback function for a request. Note a special case is made for the
3696
+ * read action vs all the others.
3697
+ * @param {String} action [create|update|delete|load]
3698
+ * @param {Ext.data.Record[]} rs The Store-recordset being acted upon
3699
+ * @private
3700
+ */
3701
+ createCallback : function(action, rs) {
3702
+ return function(o, success, response) {
3703
+ this.activeRequest[action] = undefined;
3704
+ if (!success) {
3705
+ if (action === Ext.data.Api.actions.read) {
3706
+ // @deprecated: fire loadexception for backwards compat.
3707
+ this.fireEvent('loadexception', this, o, response);
3708
+ }
3709
+ this.fireEvent('exception', this, 'response', action, o, response);
3710
+ o.request.callback.call(o.request.scope, null, o.request.arg, false);
3711
+ return;
3712
+ }
3713
+ if (action === Ext.data.Api.actions.read) {
3714
+ this.onRead(action, o, response);
3715
+ } else {
3716
+ this.onWrite(action, o, response, rs);
3717
+ }
3718
+ }
3719
+ },
3720
+
3721
+ /**
3722
+ * Callback for read action
3723
+ * @param {String} action Action name as per {@link Ext.data.Api.actions#read}.
3724
+ * @param {Object} o The request transaction object
3725
+ * @param {Object} res The server response
3726
+ * @private
3727
+ */
3728
+ onRead : function(action, o, response) {
3729
+ var result;
3730
+ try {
3731
+ result = o.reader.read(response);
3732
+ }catch(e){
3733
+ // @deprecated: fire old loadexception for backwards-compat.
3734
+ this.fireEvent('loadexception', this, o, response, e);
3735
+ this.fireEvent('exception', this, 'response', action, o, response, e);
3736
+ o.request.callback.call(o.request.scope, null, o.request.arg, false);
3737
+ return;
3738
+ }
3739
+ if (result.success === false) {
3740
+ // @deprecated: fire old loadexception for backwards-compat.
3741
+ this.fireEvent('loadexception', this, o, response);
3742
+
3743
+ // Get DataReader read-back a response-object to pass along to exception event
3744
+ var res = o.reader.readResponse(action, response);
3745
+ this.fireEvent('exception', this, 'remote', action, o, res, null);
3746
+ }
3747
+ else {
3748
+ this.fireEvent('load', this, o, o.request.arg);
3749
+ }
3750
+ o.request.callback.call(o.request.scope, result, o.request.arg, result.success);
3751
+ },
3752
+ /**
3753
+ * Callback for write actions
3754
+ * @param {String} action [Ext.data.Api.actions.create|read|update|destroy]
3755
+ * @param {Object} trans The request transaction object
3756
+ * @param {Object} res The server response
3757
+ * @private
3758
+ */
3759
+ onWrite : function(action, o, response, rs) {
3760
+ var reader = o.reader;
3761
+ var res;
3762
+ try {
3763
+ res = reader.readResponse(action, response);
3764
+ } catch (e) {
3765
+ this.fireEvent('exception', this, 'response', action, o, response, e);
3766
+ o.request.callback.call(o.request.scope, null, o.request.arg, false);
3767
+ return;
3768
+ }
3769
+ if (res[reader.meta.successProperty] === false) {
3770
+ this.fireEvent('exception', this, 'remote', action, o, res, rs);
3771
+ } else {
3772
+ this.fireEvent('write', this, action, res[reader.meta.root], res, rs, o.request.arg);
3773
+ }
3774
+ o.request.callback.call(o.request.scope, res[reader.meta.root], res, res[reader.meta.successProperty]);
3775
+ },
3776
+
3777
+ // inherit docs
3778
+ destroy: function(){
3779
+ if(!this.useAjax){
3780
+ this.conn.abort();
3781
+ }else if(this.activeRequest){
3782
+ var actions = Ext.data.Api.actions;
3783
+ for (var verb in actions) {
3784
+ if(this.activeRequest[actions[verb]]){
3785
+ Ext.Ajax.abort(this.activeRequest[actions[verb]]);
3786
+ }
3787
+ }
3788
+ }
3789
+ Ext.data.HttpProxy.superclass.destroy.call(this);
3790
+ }
3791
+ });/**
3792
+ * @class Ext.data.MemoryProxy
3793
+ * @extends Ext.data.DataProxy
3794
+ * An implementation of Ext.data.DataProxy that simply passes the data specified in its constructor
3795
+ * to the Reader when its load method is called.
3796
+ * @constructor
3797
+ * @param {Object} data The data object which the Reader uses to construct a block of Ext.data.Records.
3798
+ */
3799
+ Ext.data.MemoryProxy = function(data){
3800
+ // Must define a dummy api with "read" action to satisfy DataProxy#doRequest and Ext.data.Api#prepare *before* calling super
3801
+ var api = {};
3802
+ api[Ext.data.Api.actions.read] = true;
3803
+ Ext.data.MemoryProxy.superclass.constructor.call(this, {
3804
+ api: api
3805
+ });
3806
+ this.data = data;
3807
+ };
3808
+
3809
+ Ext.extend(Ext.data.MemoryProxy, Ext.data.DataProxy, {
3810
+ /**
3811
+ * @event loadexception
3812
+ * Fires if an exception occurs in the Proxy during data loading. Note that this event is also relayed
3813
+ * through {@link Ext.data.Store}, so you can listen for it directly on any Store instance.
3814
+ * @param {Object} this
3815
+ * @param {Object} arg The callback's arg object passed to the {@link #load} function
3816
+ * @param {Object} null This parameter does not apply and will always be null for MemoryProxy
3817
+ * @param {Error} e The JavaScript Error object caught if the configured Reader could not read the data
3818
+ */
3819
+
3820
+ /**
3821
+ * MemoryProxy implementation of DataProxy#doRequest
3822
+ * @param {String} action
3823
+ * @param {Ext.data.Record/Ext.data.Record[]} rs If action is load, rs will be null
3824
+ * @param {Object} params An object containing properties which are to be used as HTTP parameters
3825
+ * for the request to the remote server.
3826
+ * @param {Ext.data.DataReader} reader The Reader object which converts the data
3827
+ * object into a block of Ext.data.Records.
3828
+ * @param {Function} callback The function into which to pass the block of Ext.data.Records.
3829
+ * The function must be passed <ul>
3830
+ * <li>The Record block object</li>
3831
+ * <li>The "arg" argument from the load function</li>
3832
+ * <li>A boolean success indicator</li>
3833
+ * </ul>
3834
+ * @param {Object} scope The scope in which to call the callback
3835
+ * @param {Object} arg An optional argument which is passed to the callback as its second parameter.
3836
+ */
3837
+ doRequest : function(action, rs, params, reader, callback, scope, arg) {
3838
+ // No implementation for CRUD in MemoryProxy. Assumes all actions are 'load'
3839
+ params = params || {};
3840
+ var result;
3841
+ try {
3842
+ result = reader.readRecords(this.data);
3843
+ }catch(e){
3844
+ // @deprecated loadexception
3845
+ this.fireEvent("loadexception", this, null, arg, e);
3846
+
3847
+ this.fireEvent('exception', this, 'response', action, arg, null, e);
3848
+ callback.call(scope, null, arg, false);
3849
+ return;
3850
+ }
3851
+ callback.call(scope, result, arg, true);
3852
+ }
3853
+ });