lpmp 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (636) hide show
  1. data/LICENSE +3 -0
  2. data/README +3 -0
  3. data/Rakefile +45 -0
  4. data/bin/lpmp +107 -0
  5. data/config/help.yaml +1 -0
  6. data/config/hosts.yaml +2 -0
  7. data/config/log.yaml +1 -0
  8. data/config/memcache.yaml +5 -0
  9. data/erb/index.erb +62 -0
  10. data/lib/bg_pull/caichen.rb +199 -0
  11. data/lib/bg_pull/lpmp.rb +45 -0
  12. data/lib/exception.rb +8 -0
  13. data/lib/lpmp.rb +53 -0
  14. data/lib/pull/lpmp.rb +355 -0
  15. data/lib/remote_lmp.rb +129 -0
  16. data/lib/utils.rb +14 -0
  17. data/lib/xq_push/caichen.rb +174 -0
  18. data/lib/xq_push/lpmp.rb +96 -0
  19. data/log/lpmp1st.log +1 -0
  20. data/public/css/ext-portal.css +40 -0
  21. data/public/css/lpmp.css +6 -0
  22. data/public/designer/caichen.epj +1 -0
  23. data/public/designer/hostmonitor.epj +1 -0
  24. data/public/ext-3.0.0/INCLUDE_ORDER.txt +35 -0
  25. data/public/ext-3.0.0/adapter/ext/ext-base-debug.js +3589 -0
  26. data/public/ext-3.0.0/adapter/ext/ext-base.js +7 -0
  27. data/public/ext-3.0.0/adapter/jquery/ext-jquery-adapter-debug.js +2292 -0
  28. data/public/ext-3.0.0/adapter/jquery/ext-jquery-adapter.js +7 -0
  29. data/public/ext-3.0.0/adapter/prototype/ext-prototype-adapter-debug.js +2346 -0
  30. data/public/ext-3.0.0/adapter/prototype/ext-prototype-adapter.js +7 -0
  31. data/public/ext-3.0.0/adapter/yui/ext-yui-adapter-debug.js +2136 -0
  32. data/public/ext-3.0.0/adapter/yui/ext-yui-adapter.js +7 -0
  33. data/public/ext-3.0.0/ext-all-debug.js +65610 -0
  34. data/public/ext-3.0.0/ext-all.js +11 -0
  35. data/public/ext-3.0.0/license.txt +42 -0
  36. data/public/ext-3.0.0/pkgs/cmp-foundation-debug.js +11287 -0
  37. data/public/ext-3.0.0/pkgs/cmp-foundation.js +7 -0
  38. data/public/ext-3.0.0/pkgs/data-foundation-debug.js +3853 -0
  39. data/public/ext-3.0.0/pkgs/data-foundation.js +7 -0
  40. data/public/ext-3.0.0/pkgs/data-grouping-debug.js +139 -0
  41. data/public/ext-3.0.0/pkgs/data-grouping.js +7 -0
  42. data/public/ext-3.0.0/pkgs/data-json-debug.js +582 -0
  43. data/public/ext-3.0.0/pkgs/data-json.js +7 -0
  44. data/public/ext-3.0.0/pkgs/data-list-views-debug.js +1278 -0
  45. data/public/ext-3.0.0/pkgs/data-list-views.js +7 -0
  46. data/public/ext-3.0.0/pkgs/data-xml-debug.js +234 -0
  47. data/public/ext-3.0.0/pkgs/data-xml.js +7 -0
  48. data/public/ext-3.0.0/pkgs/direct-debug.js +1121 -0
  49. data/public/ext-3.0.0/pkgs/direct.js +7 -0
  50. data/public/ext-3.0.0/pkgs/ext-dd-debug.js +4567 -0
  51. data/public/ext-3.0.0/pkgs/ext-dd.js +7 -0
  52. data/public/ext-3.0.0/pkgs/ext-foundation-debug.js +13417 -0
  53. data/public/ext-3.0.0/pkgs/ext-foundation.js +7 -0
  54. data/public/ext-3.0.0/pkgs/pkg-buttons-debug.js +1060 -0
  55. data/public/ext-3.0.0/pkgs/pkg-buttons.js +7 -0
  56. data/public/ext-3.0.0/pkgs/pkg-charts-debug.js +1621 -0
  57. data/public/ext-3.0.0/pkgs/pkg-charts.js +10 -0
  58. data/public/ext-3.0.0/pkgs/pkg-forms-debug.js +7661 -0
  59. data/public/ext-3.0.0/pkgs/pkg-forms.js +7 -0
  60. data/public/ext-3.0.0/pkgs/pkg-grid-editor-debug.js +560 -0
  61. data/public/ext-3.0.0/pkgs/pkg-grid-editor.js +7 -0
  62. data/public/ext-3.0.0/pkgs/pkg-grid-foundation-debug.js +4765 -0
  63. data/public/ext-3.0.0/pkgs/pkg-grid-foundation.js +7 -0
  64. data/public/ext-3.0.0/pkgs/pkg-grid-grouping-debug.js +517 -0
  65. data/public/ext-3.0.0/pkgs/pkg-grid-grouping.js +7 -0
  66. data/public/ext-3.0.0/pkgs/pkg-grid-property-debug.js +370 -0
  67. data/public/ext-3.0.0/pkgs/pkg-grid-property.js +7 -0
  68. data/public/ext-3.0.0/pkgs/pkg-history-debug.js +203 -0
  69. data/public/ext-3.0.0/pkgs/pkg-history.js +7 -0
  70. data/public/ext-3.0.0/pkgs/pkg-menu-debug.js +1628 -0
  71. data/public/ext-3.0.0/pkgs/pkg-menu.js +7 -0
  72. data/public/ext-3.0.0/pkgs/pkg-tabs-debug.js +1100 -0
  73. data/public/ext-3.0.0/pkgs/pkg-tabs.js +7 -0
  74. data/public/ext-3.0.0/pkgs/pkg-tips-debug.js +994 -0
  75. data/public/ext-3.0.0/pkgs/pkg-tips.js +7 -0
  76. data/public/ext-3.0.0/pkgs/pkg-toolbars-debug.js +1374 -0
  77. data/public/ext-3.0.0/pkgs/pkg-toolbars.js +7 -0
  78. data/public/ext-3.0.0/pkgs/pkg-tree-debug.js +4522 -0
  79. data/public/ext-3.0.0/pkgs/pkg-tree.js +7 -0
  80. data/public/ext-3.0.0/pkgs/resizable-debug.js +760 -0
  81. data/public/ext-3.0.0/pkgs/resizable.js +7 -0
  82. data/public/ext-3.0.0/pkgs/state-debug.js +274 -0
  83. data/public/ext-3.0.0/pkgs/state.js +7 -0
  84. data/public/ext-3.0.0/pkgs/window-debug.js +1888 -0
  85. data/public/ext-3.0.0/pkgs/window.js +7 -0
  86. data/public/ext-3.0.0/resources/charts.swf +0 -0
  87. data/public/ext-3.0.0/resources/css/README.txt +3 -0
  88. data/public/ext-3.0.0/resources/css/ext-all-notheme.css +5345 -0
  89. data/public/ext-3.0.0/resources/css/ext-all.css +6990 -0
  90. data/public/ext-3.0.0/resources/css/reset-min.css +7 -0
  91. data/public/ext-3.0.0/resources/css/structure/borders.css +54 -0
  92. data/public/ext-3.0.0/resources/css/structure/box.css +80 -0
  93. data/public/ext-3.0.0/resources/css/structure/button.css +440 -0
  94. data/public/ext-3.0.0/resources/css/structure/combo.css +45 -0
  95. data/public/ext-3.0.0/resources/css/structure/core.css +326 -0
  96. data/public/ext-3.0.0/resources/css/structure/date-picker.css +265 -0
  97. data/public/ext-3.0.0/resources/css/structure/dd.css +61 -0
  98. data/public/ext-3.0.0/resources/css/structure/debug.css +26 -0
  99. data/public/ext-3.0.0/resources/css/structure/dialog.css +62 -0
  100. data/public/ext-3.0.0/resources/css/structure/editor.css +92 -0
  101. data/public/ext-3.0.0/resources/css/structure/form.css +562 -0
  102. data/public/ext-3.0.0/resources/css/structure/grid.css +552 -0
  103. data/public/ext-3.0.0/resources/css/structure/layout.css +296 -0
  104. data/public/ext-3.0.0/resources/css/structure/list-view.css +85 -0
  105. data/public/ext-3.0.0/resources/css/structure/menu.css +205 -0
  106. data/public/ext-3.0.0/resources/css/structure/panel-reset.css +130 -0
  107. data/public/ext-3.0.0/resources/css/structure/panel.css +468 -0
  108. data/public/ext-3.0.0/resources/css/structure/progress.css +42 -0
  109. data/public/ext-3.0.0/resources/css/structure/qtips.css +153 -0
  110. data/public/ext-3.0.0/resources/css/structure/reset.css +7 -0
  111. data/public/ext-3.0.0/resources/css/structure/resizable.css +149 -0
  112. data/public/ext-3.0.0/resources/css/structure/slider.css +103 -0
  113. data/public/ext-3.0.0/resources/css/structure/tabs.css +372 -0
  114. data/public/ext-3.0.0/resources/css/structure/toolbar.css +259 -0
  115. data/public/ext-3.0.0/resources/css/structure/tree.css +203 -0
  116. data/public/ext-3.0.0/resources/css/structure/window.css +222 -0
  117. data/public/ext-3.0.0/resources/css/visual/borders.css +25 -0
  118. data/public/ext-3.0.0/resources/css/visual/box.css +74 -0
  119. data/public/ext-3.0.0/resources/css/visual/button.css +94 -0
  120. data/public/ext-3.0.0/resources/css/visual/combo.css +43 -0
  121. data/public/ext-3.0.0/resources/css/visual/core.css +76 -0
  122. data/public/ext-3.0.0/resources/css/visual/date-picker.css +143 -0
  123. data/public/ext-3.0.0/resources/css/visual/dd.css +29 -0
  124. data/public/ext-3.0.0/resources/css/visual/debug.css +24 -0
  125. data/public/ext-3.0.0/resources/css/visual/dialog.css +34 -0
  126. data/public/ext-3.0.0/resources/css/visual/editor.css +13 -0
  127. data/public/ext-3.0.0/resources/css/visual/form.css +117 -0
  128. data/public/ext-3.0.0/resources/css/visual/grid.css +272 -0
  129. data/public/ext-3.0.0/resources/css/visual/layout.css +53 -0
  130. data/public/ext-3.0.0/resources/css/visual/list-view.css +37 -0
  131. data/public/ext-3.0.0/resources/css/visual/menu.css +82 -0
  132. data/public/ext-3.0.0/resources/css/visual/panel.css +87 -0
  133. data/public/ext-3.0.0/resources/css/visual/progress.css +32 -0
  134. data/public/ext-3.0.0/resources/css/visual/qtips.css +44 -0
  135. data/public/ext-3.0.0/resources/css/visual/resizable.css +43 -0
  136. data/public/ext-3.0.0/resources/css/visual/slider.css +21 -0
  137. data/public/ext-3.0.0/resources/css/visual/tabs.css +119 -0
  138. data/public/ext-3.0.0/resources/css/visual/toolbar.css +103 -0
  139. data/public/ext-3.0.0/resources/css/visual/tree.css +157 -0
  140. data/public/ext-3.0.0/resources/css/visual/window.css +86 -0
  141. data/public/ext-3.0.0/resources/css/xtheme-blue.css +1652 -0
  142. data/public/ext-3.0.0/resources/expressinstall.swf +0 -0
  143. data/public/ext-3.0.0/resources/images/default/box/corners-blue.gif +0 -0
  144. data/public/ext-3.0.0/resources/images/default/box/corners.gif +0 -0
  145. data/public/ext-3.0.0/resources/images/default/box/l-blue.gif +0 -0
  146. data/public/ext-3.0.0/resources/images/default/box/l.gif +0 -0
  147. data/public/ext-3.0.0/resources/images/default/box/r-blue.gif +0 -0
  148. data/public/ext-3.0.0/resources/images/default/box/r.gif +0 -0
  149. data/public/ext-3.0.0/resources/images/default/box/tb-blue.gif +0 -0
  150. data/public/ext-3.0.0/resources/images/default/box/tb.gif +0 -0
  151. data/public/ext-3.0.0/resources/images/default/button/arrow.gif +0 -0
  152. data/public/ext-3.0.0/resources/images/default/button/btn.gif +0 -0
  153. data/public/ext-3.0.0/resources/images/default/button/group-cs.gif +0 -0
  154. data/public/ext-3.0.0/resources/images/default/button/group-lr.gif +0 -0
  155. data/public/ext-3.0.0/resources/images/default/button/group-tb.gif +0 -0
  156. data/public/ext-3.0.0/resources/images/default/button/s-arrow-b-noline.gif +0 -0
  157. data/public/ext-3.0.0/resources/images/default/button/s-arrow-b.gif +0 -0
  158. data/public/ext-3.0.0/resources/images/default/button/s-arrow-bo.gif +0 -0
  159. data/public/ext-3.0.0/resources/images/default/button/s-arrow-noline.gif +0 -0
  160. data/public/ext-3.0.0/resources/images/default/button/s-arrow-o.gif +0 -0
  161. data/public/ext-3.0.0/resources/images/default/button/s-arrow.gif +0 -0
  162. data/public/ext-3.0.0/resources/images/default/dd/drop-add.gif +0 -0
  163. data/public/ext-3.0.0/resources/images/default/dd/drop-no.gif +0 -0
  164. data/public/ext-3.0.0/resources/images/default/dd/drop-yes.gif +0 -0
  165. data/public/ext-3.0.0/resources/images/default/editor/tb-sprite.gif +0 -0
  166. data/public/ext-3.0.0/resources/images/default/form/checkbox.gif +0 -0
  167. data/public/ext-3.0.0/resources/images/default/form/clear-trigger.gif +0 -0
  168. data/public/ext-3.0.0/resources/images/default/form/clear-trigger.psd +0 -0
  169. data/public/ext-3.0.0/resources/images/default/form/date-trigger.gif +0 -0
  170. data/public/ext-3.0.0/resources/images/default/form/date-trigger.psd +0 -0
  171. data/public/ext-3.0.0/resources/images/default/form/error-tip-corners.gif +0 -0
  172. data/public/ext-3.0.0/resources/images/default/form/exclamation.gif +0 -0
  173. data/public/ext-3.0.0/resources/images/default/form/radio.gif +0 -0
  174. data/public/ext-3.0.0/resources/images/default/form/search-trigger.gif +0 -0
  175. data/public/ext-3.0.0/resources/images/default/form/search-trigger.psd +0 -0
  176. data/public/ext-3.0.0/resources/images/default/form/text-bg.gif +0 -0
  177. data/public/ext-3.0.0/resources/images/default/form/trigger-tpl.gif +0 -0
  178. data/public/ext-3.0.0/resources/images/default/form/trigger.gif +0 -0
  179. data/public/ext-3.0.0/resources/images/default/form/trigger.psd +0 -0
  180. data/public/ext-3.0.0/resources/images/default/gradient-bg.gif +0 -0
  181. data/public/ext-3.0.0/resources/images/default/grid/arrow-left-white.gif +0 -0
  182. data/public/ext-3.0.0/resources/images/default/grid/arrow-right-white.gif +0 -0
  183. data/public/ext-3.0.0/resources/images/default/grid/col-move-bottom.gif +0 -0
  184. data/public/ext-3.0.0/resources/images/default/grid/col-move-top.gif +0 -0
  185. data/public/ext-3.0.0/resources/images/default/grid/columns.gif +0 -0
  186. data/public/ext-3.0.0/resources/images/default/grid/dirty.gif +0 -0
  187. data/public/ext-3.0.0/resources/images/default/grid/done.gif +0 -0
  188. data/public/ext-3.0.0/resources/images/default/grid/drop-no.gif +0 -0
  189. data/public/ext-3.0.0/resources/images/default/grid/drop-yes.gif +0 -0
  190. data/public/ext-3.0.0/resources/images/default/grid/footer-bg.gif +0 -0
  191. data/public/ext-3.0.0/resources/images/default/grid/grid-blue-hd.gif +0 -0
  192. data/public/ext-3.0.0/resources/images/default/grid/grid-blue-split.gif +0 -0
  193. data/public/ext-3.0.0/resources/images/default/grid/grid-hrow.gif +0 -0
  194. data/public/ext-3.0.0/resources/images/default/grid/grid-loading.gif +0 -0
  195. data/public/ext-3.0.0/resources/images/default/grid/grid-split.gif +0 -0
  196. data/public/ext-3.0.0/resources/images/default/grid/grid-vista-hd.gif +0 -0
  197. data/public/ext-3.0.0/resources/images/default/grid/grid3-hd-btn.gif +0 -0
  198. data/public/ext-3.0.0/resources/images/default/grid/grid3-hrow-over.gif +0 -0
  199. data/public/ext-3.0.0/resources/images/default/grid/grid3-hrow.gif +0 -0
  200. data/public/ext-3.0.0/resources/images/default/grid/grid3-special-col-bg.gif +0 -0
  201. data/public/ext-3.0.0/resources/images/default/grid/grid3-special-col-sel-bg.gif +0 -0
  202. data/public/ext-3.0.0/resources/images/default/grid/group-by.gif +0 -0
  203. data/public/ext-3.0.0/resources/images/default/grid/group-collapse.gif +0 -0
  204. data/public/ext-3.0.0/resources/images/default/grid/group-expand-sprite.gif +0 -0
  205. data/public/ext-3.0.0/resources/images/default/grid/group-expand.gif +0 -0
  206. data/public/ext-3.0.0/resources/images/default/grid/hd-pop.gif +0 -0
  207. data/public/ext-3.0.0/resources/images/default/grid/hmenu-asc.gif +0 -0
  208. data/public/ext-3.0.0/resources/images/default/grid/hmenu-desc.gif +0 -0
  209. data/public/ext-3.0.0/resources/images/default/grid/hmenu-lock.gif +0 -0
  210. data/public/ext-3.0.0/resources/images/default/grid/hmenu-lock.png +0 -0
  211. data/public/ext-3.0.0/resources/images/default/grid/hmenu-unlock.gif +0 -0
  212. data/public/ext-3.0.0/resources/images/default/grid/hmenu-unlock.png +0 -0
  213. data/public/ext-3.0.0/resources/images/default/grid/invalid_line.gif +0 -0
  214. data/public/ext-3.0.0/resources/images/default/grid/loading.gif +0 -0
  215. data/public/ext-3.0.0/resources/images/default/grid/mso-hd.gif +0 -0
  216. data/public/ext-3.0.0/resources/images/default/grid/nowait.gif +0 -0
  217. data/public/ext-3.0.0/resources/images/default/grid/page-first-disabled.gif +0 -0
  218. data/public/ext-3.0.0/resources/images/default/grid/page-first.gif +0 -0
  219. data/public/ext-3.0.0/resources/images/default/grid/page-last-disabled.gif +0 -0
  220. data/public/ext-3.0.0/resources/images/default/grid/page-last.gif +0 -0
  221. data/public/ext-3.0.0/resources/images/default/grid/page-next-disabled.gif +0 -0
  222. data/public/ext-3.0.0/resources/images/default/grid/page-next.gif +0 -0
  223. data/public/ext-3.0.0/resources/images/default/grid/page-prev-disabled.gif +0 -0
  224. data/public/ext-3.0.0/resources/images/default/grid/page-prev.gif +0 -0
  225. data/public/ext-3.0.0/resources/images/default/grid/pick-button.gif +0 -0
  226. data/public/ext-3.0.0/resources/images/default/grid/refresh.gif +0 -0
  227. data/public/ext-3.0.0/resources/images/default/grid/row-check-sprite.gif +0 -0
  228. data/public/ext-3.0.0/resources/images/default/grid/row-expand-sprite.gif +0 -0
  229. data/public/ext-3.0.0/resources/images/default/grid/row-over.gif +0 -0
  230. data/public/ext-3.0.0/resources/images/default/grid/row-sel.gif +0 -0
  231. data/public/ext-3.0.0/resources/images/default/grid/sort-hd.gif +0 -0
  232. data/public/ext-3.0.0/resources/images/default/grid/sort_asc.gif +0 -0
  233. data/public/ext-3.0.0/resources/images/default/grid/sort_desc.gif +0 -0
  234. data/public/ext-3.0.0/resources/images/default/grid/wait.gif +0 -0
  235. data/public/ext-3.0.0/resources/images/default/layout/collapse.gif +0 -0
  236. data/public/ext-3.0.0/resources/images/default/layout/expand.gif +0 -0
  237. data/public/ext-3.0.0/resources/images/default/layout/gradient-bg.gif +0 -0
  238. data/public/ext-3.0.0/resources/images/default/layout/mini-bottom.gif +0 -0
  239. data/public/ext-3.0.0/resources/images/default/layout/mini-left.gif +0 -0
  240. data/public/ext-3.0.0/resources/images/default/layout/mini-right.gif +0 -0
  241. data/public/ext-3.0.0/resources/images/default/layout/mini-top.gif +0 -0
  242. data/public/ext-3.0.0/resources/images/default/layout/ns-collapse.gif +0 -0
  243. data/public/ext-3.0.0/resources/images/default/layout/ns-expand.gif +0 -0
  244. data/public/ext-3.0.0/resources/images/default/layout/panel-close.gif +0 -0
  245. data/public/ext-3.0.0/resources/images/default/layout/panel-title-bg.gif +0 -0
  246. data/public/ext-3.0.0/resources/images/default/layout/panel-title-light-bg.gif +0 -0
  247. data/public/ext-3.0.0/resources/images/default/layout/stick.gif +0 -0
  248. data/public/ext-3.0.0/resources/images/default/layout/stuck.gif +0 -0
  249. data/public/ext-3.0.0/resources/images/default/layout/tab-close-on.gif +0 -0
  250. data/public/ext-3.0.0/resources/images/default/layout/tab-close.gif +0 -0
  251. data/public/ext-3.0.0/resources/images/default/menu/checked.gif +0 -0
  252. data/public/ext-3.0.0/resources/images/default/menu/group-checked.gif +0 -0
  253. data/public/ext-3.0.0/resources/images/default/menu/item-over.gif +0 -0
  254. data/public/ext-3.0.0/resources/images/default/menu/menu-parent.gif +0 -0
  255. data/public/ext-3.0.0/resources/images/default/menu/menu.gif +0 -0
  256. data/public/ext-3.0.0/resources/images/default/menu/unchecked.gif +0 -0
  257. data/public/ext-3.0.0/resources/images/default/panel/corners-sprite.gif +0 -0
  258. data/public/ext-3.0.0/resources/images/default/panel/left-right.gif +0 -0
  259. data/public/ext-3.0.0/resources/images/default/panel/light-hd.gif +0 -0
  260. data/public/ext-3.0.0/resources/images/default/panel/tool-sprite-tpl.gif +0 -0
  261. data/public/ext-3.0.0/resources/images/default/panel/tool-sprites.gif +0 -0
  262. data/public/ext-3.0.0/resources/images/default/panel/tools-sprites-trans.gif +0 -0
  263. data/public/ext-3.0.0/resources/images/default/panel/top-bottom.gif +0 -0
  264. data/public/ext-3.0.0/resources/images/default/panel/top-bottom.png +0 -0
  265. data/public/ext-3.0.0/resources/images/default/panel/white-corners-sprite.gif +0 -0
  266. data/public/ext-3.0.0/resources/images/default/panel/white-left-right.gif +0 -0
  267. data/public/ext-3.0.0/resources/images/default/panel/white-top-bottom.gif +0 -0
  268. data/public/ext-3.0.0/resources/images/default/progress/progress-bg.gif +0 -0
  269. data/public/ext-3.0.0/resources/images/default/qtip/bg.gif +0 -0
  270. data/public/ext-3.0.0/resources/images/default/qtip/close.gif +0 -0
  271. data/public/ext-3.0.0/resources/images/default/qtip/tip-anchor-sprite.gif +0 -0
  272. data/public/ext-3.0.0/resources/images/default/qtip/tip-sprite.gif +0 -0
  273. data/public/ext-3.0.0/resources/images/default/s.gif +0 -0
  274. data/public/ext-3.0.0/resources/images/default/shadow-c.png +0 -0
  275. data/public/ext-3.0.0/resources/images/default/shadow-lr.png +0 -0
  276. data/public/ext-3.0.0/resources/images/default/shadow.png +0 -0
  277. data/public/ext-3.0.0/resources/images/default/shared/blue-loading.gif +0 -0
  278. data/public/ext-3.0.0/resources/images/default/shared/calendar.gif +0 -0
  279. data/public/ext-3.0.0/resources/images/default/shared/glass-bg.gif +0 -0
  280. data/public/ext-3.0.0/resources/images/default/shared/hd-sprite.gif +0 -0
  281. data/public/ext-3.0.0/resources/images/default/shared/large-loading.gif +0 -0
  282. data/public/ext-3.0.0/resources/images/default/shared/left-btn.gif +0 -0
  283. data/public/ext-3.0.0/resources/images/default/shared/loading-balls.gif +0 -0
  284. data/public/ext-3.0.0/resources/images/default/shared/right-btn.gif +0 -0
  285. data/public/ext-3.0.0/resources/images/default/shared/warning.gif +0 -0
  286. data/public/ext-3.0.0/resources/images/default/sizer/e-handle-dark.gif +0 -0
  287. data/public/ext-3.0.0/resources/images/default/sizer/e-handle.gif +0 -0
  288. data/public/ext-3.0.0/resources/images/default/sizer/ne-handle-dark.gif +0 -0
  289. data/public/ext-3.0.0/resources/images/default/sizer/ne-handle.gif +0 -0
  290. data/public/ext-3.0.0/resources/images/default/sizer/nw-handle-dark.gif +0 -0
  291. data/public/ext-3.0.0/resources/images/default/sizer/nw-handle.gif +0 -0
  292. data/public/ext-3.0.0/resources/images/default/sizer/s-handle-dark.gif +0 -0
  293. data/public/ext-3.0.0/resources/images/default/sizer/s-handle.gif +0 -0
  294. data/public/ext-3.0.0/resources/images/default/sizer/se-handle-dark.gif +0 -0
  295. data/public/ext-3.0.0/resources/images/default/sizer/se-handle.gif +0 -0
  296. data/public/ext-3.0.0/resources/images/default/sizer/square.gif +0 -0
  297. data/public/ext-3.0.0/resources/images/default/sizer/sw-handle-dark.gif +0 -0
  298. data/public/ext-3.0.0/resources/images/default/sizer/sw-handle.gif +0 -0
  299. data/public/ext-3.0.0/resources/images/default/slider/slider-bg.png +0 -0
  300. data/public/ext-3.0.0/resources/images/default/slider/slider-thumb.png +0 -0
  301. data/public/ext-3.0.0/resources/images/default/slider/slider-v-bg.png +0 -0
  302. data/public/ext-3.0.0/resources/images/default/slider/slider-v-thumb.png +0 -0
  303. data/public/ext-3.0.0/resources/images/default/tabs/scroll-left.gif +0 -0
  304. data/public/ext-3.0.0/resources/images/default/tabs/scroll-right.gif +0 -0
  305. data/public/ext-3.0.0/resources/images/default/tabs/scroller-bg.gif +0 -0
  306. data/public/ext-3.0.0/resources/images/default/tabs/tab-btm-inactive-left-bg.gif +0 -0
  307. data/public/ext-3.0.0/resources/images/default/tabs/tab-btm-inactive-right-bg.gif +0 -0
  308. data/public/ext-3.0.0/resources/images/default/tabs/tab-btm-left-bg.gif +0 -0
  309. data/public/ext-3.0.0/resources/images/default/tabs/tab-btm-right-bg.gif +0 -0
  310. data/public/ext-3.0.0/resources/images/default/tabs/tab-close.gif +0 -0
  311. data/public/ext-3.0.0/resources/images/default/tabs/tab-strip-bg.gif +0 -0
  312. data/public/ext-3.0.0/resources/images/default/tabs/tab-strip-bg.png +0 -0
  313. data/public/ext-3.0.0/resources/images/default/tabs/tab-strip-btm-bg.gif +0 -0
  314. data/public/ext-3.0.0/resources/images/default/tabs/tabs-sprite.gif +0 -0
  315. data/public/ext-3.0.0/resources/images/default/toolbar/bg.gif +0 -0
  316. data/public/ext-3.0.0/resources/images/default/toolbar/btn-arrow-light.gif +0 -0
  317. data/public/ext-3.0.0/resources/images/default/toolbar/btn-arrow.gif +0 -0
  318. data/public/ext-3.0.0/resources/images/default/toolbar/btn-over-bg.gif +0 -0
  319. data/public/ext-3.0.0/resources/images/default/toolbar/gray-bg.gif +0 -0
  320. data/public/ext-3.0.0/resources/images/default/toolbar/more.gif +0 -0
  321. data/public/ext-3.0.0/resources/images/default/toolbar/tb-bg.gif +0 -0
  322. data/public/ext-3.0.0/resources/images/default/toolbar/tb-btn-sprite.gif +0 -0
  323. data/public/ext-3.0.0/resources/images/default/toolbar/tb-xl-btn-sprite.gif +0 -0
  324. data/public/ext-3.0.0/resources/images/default/toolbar/tb-xl-sep.gif +0 -0
  325. data/public/ext-3.0.0/resources/images/default/tree/arrows.gif +0 -0
  326. data/public/ext-3.0.0/resources/images/default/tree/drop-add.gif +0 -0
  327. data/public/ext-3.0.0/resources/images/default/tree/drop-between.gif +0 -0
  328. data/public/ext-3.0.0/resources/images/default/tree/drop-no.gif +0 -0
  329. data/public/ext-3.0.0/resources/images/default/tree/drop-over.gif +0 -0
  330. data/public/ext-3.0.0/resources/images/default/tree/drop-under.gif +0 -0
  331. data/public/ext-3.0.0/resources/images/default/tree/drop-yes.gif +0 -0
  332. data/public/ext-3.0.0/resources/images/default/tree/elbow-end-minus-nl.gif +0 -0
  333. data/public/ext-3.0.0/resources/images/default/tree/elbow-end-minus.gif +0 -0
  334. data/public/ext-3.0.0/resources/images/default/tree/elbow-end-plus-nl.gif +0 -0
  335. data/public/ext-3.0.0/resources/images/default/tree/elbow-end-plus.gif +0 -0
  336. data/public/ext-3.0.0/resources/images/default/tree/elbow-end.gif +0 -0
  337. data/public/ext-3.0.0/resources/images/default/tree/elbow-line.gif +0 -0
  338. data/public/ext-3.0.0/resources/images/default/tree/elbow-minus-nl.gif +0 -0
  339. data/public/ext-3.0.0/resources/images/default/tree/elbow-minus.gif +0 -0
  340. data/public/ext-3.0.0/resources/images/default/tree/elbow-plus-nl.gif +0 -0
  341. data/public/ext-3.0.0/resources/images/default/tree/elbow-plus.gif +0 -0
  342. data/public/ext-3.0.0/resources/images/default/tree/elbow.gif +0 -0
  343. data/public/ext-3.0.0/resources/images/default/tree/folder-open.gif +0 -0
  344. data/public/ext-3.0.0/resources/images/default/tree/folder.gif +0 -0
  345. data/public/ext-3.0.0/resources/images/default/tree/leaf.gif +0 -0
  346. data/public/ext-3.0.0/resources/images/default/tree/loading.gif +0 -0
  347. data/public/ext-3.0.0/resources/images/default/tree/s.gif +0 -0
  348. data/public/ext-3.0.0/resources/images/default/window/icon-error.gif +0 -0
  349. data/public/ext-3.0.0/resources/images/default/window/icon-info.gif +0 -0
  350. data/public/ext-3.0.0/resources/images/default/window/icon-question.gif +0 -0
  351. data/public/ext-3.0.0/resources/images/default/window/icon-warning.gif +0 -0
  352. data/public/ext-3.0.0/resources/images/default/window/left-corners.png +0 -0
  353. data/public/ext-3.0.0/resources/images/default/window/left-corners.psd +0 -0
  354. data/public/ext-3.0.0/resources/images/default/window/left-right.png +0 -0
  355. data/public/ext-3.0.0/resources/images/default/window/left-right.psd +0 -0
  356. data/public/ext-3.0.0/resources/images/default/window/right-corners.png +0 -0
  357. data/public/ext-3.0.0/resources/images/default/window/right-corners.psd +0 -0
  358. data/public/ext-3.0.0/resources/images/default/window/top-bottom.png +0 -0
  359. data/public/ext-3.0.0/resources/images/default/window/top-bottom.psd +0 -0
  360. data/public/ext-3.0.0/resources/images/icon/chart.gif +0 -0
  361. data/public/ext-3.0.0/src/adapter/core/ext-base-ajax.js +371 -0
  362. data/public/ext-3.0.0/src/adapter/core/ext-base-anim-extra.js +301 -0
  363. data/public/ext-3.0.0/src/adapter/core/ext-base-anim.js +477 -0
  364. data/public/ext-3.0.0/src/adapter/core/ext-base-begin.js +18 -0
  365. data/public/ext-3.0.0/src/adapter/core/ext-base-dom.js +157 -0
  366. data/public/ext-3.0.0/src/adapter/core/ext-base-end.js +21 -0
  367. data/public/ext-3.0.0/src/adapter/core/ext-base-event.js +453 -0
  368. data/public/ext-3.0.0/src/adapter/core/ext-base-point.js +17 -0
  369. data/public/ext-3.0.0/src/adapter/core/ext-base-region.js +81 -0
  370. data/public/ext-3.0.0/src/adapter/ext-base-dom-more.js +9 -0
  371. data/public/ext-3.0.0/src/adapter/jquery-bridge.js +546 -0
  372. data/public/ext-3.0.0/src/adapter/prototype-bridge.js +600 -0
  373. data/public/ext-3.0.0/src/adapter/yui-bridge.js +390 -0
  374. data/public/ext-3.0.0/src/core/CompositeElement.js +136 -0
  375. data/public/ext-3.0.0/src/core/CompositeElementLite-more.js +102 -0
  376. data/public/ext-3.0.0/src/core/DomHelper-more.js +179 -0
  377. data/public/ext-3.0.0/src/core/Element-more.js +192 -0
  378. data/public/ext-3.0.0/src/core/Element.alignment.js +370 -0
  379. data/public/ext-3.0.0/src/core/Element.dd.js +46 -0
  380. data/public/ext-3.0.0/src/core/Element.fx-more.js +152 -0
  381. data/public/ext-3.0.0/src/core/Element.insertion-more.js +52 -0
  382. data/public/ext-3.0.0/src/core/Element.keys.js +48 -0
  383. data/public/ext-3.0.0/src/core/Element.legacy.js +42 -0
  384. data/public/ext-3.0.0/src/core/Element.position-more.js +165 -0
  385. data/public/ext-3.0.0/src/core/Element.scroll-more.js +110 -0
  386. data/public/ext-3.0.0/src/core/Element.style-more.js +318 -0
  387. data/public/ext-3.0.0/src/core/Error.js +81 -0
  388. data/public/ext-3.0.0/src/core/EventManager-more.js +334 -0
  389. data/public/ext-3.0.0/src/core/Ext-more.js +669 -0
  390. data/public/ext-3.0.0/src/core/Template-more.js +115 -0
  391. data/public/ext-3.0.0/src/core/core/CompositeElementLite.js +197 -0
  392. data/public/ext-3.0.0/src/core/core/DomHelper.js +378 -0
  393. data/public/ext-3.0.0/src/core/core/DomQuery.js +826 -0
  394. data/public/ext-3.0.0/src/core/core/Element.fx.js +324 -0
  395. data/public/ext-3.0.0/src/core/core/Element.insertion.js +147 -0
  396. data/public/ext-3.0.0/src/core/core/Element.js +945 -0
  397. data/public/ext-3.0.0/src/core/core/Element.position.js +303 -0
  398. data/public/ext-3.0.0/src/core/core/Element.scroll.js +58 -0
  399. data/public/ext-3.0.0/src/core/core/Element.style.js +439 -0
  400. data/public/ext-3.0.0/src/core/core/Element.traversal.js +176 -0
  401. data/public/ext-3.0.0/src/core/core/EventManager.js +623 -0
  402. data/public/ext-3.0.0/src/core/core/Ext.js +922 -0
  403. data/public/ext-3.0.0/src/core/core/Fx.js +1115 -0
  404. data/public/ext-3.0.0/src/core/core/Template.js +185 -0
  405. data/public/ext-3.0.0/src/data/Api.js +210 -0
  406. data/public/ext-3.0.0/src/data/ArrayReader.js +102 -0
  407. data/public/ext-3.0.0/src/data/ArrayStore.js +70 -0
  408. data/public/ext-3.0.0/src/data/DataField.js +249 -0
  409. data/public/ext-3.0.0/src/data/DataProxy.js +427 -0
  410. data/public/ext-3.0.0/src/data/DataReader.js +160 -0
  411. data/public/ext-3.0.0/src/data/DataWriter.js +201 -0
  412. data/public/ext-3.0.0/src/data/DirectProxy.js +141 -0
  413. data/public/ext-3.0.0/src/data/DirectStore.js +52 -0
  414. data/public/ext-3.0.0/src/data/GroupingStore.js +139 -0
  415. data/public/ext-3.0.0/src/data/HttpProxy.js +276 -0
  416. data/public/ext-3.0.0/src/data/JsonReader.js +311 -0
  417. data/public/ext-3.0.0/src/data/JsonStore.js +49 -0
  418. data/public/ext-3.0.0/src/data/JsonWriter.js +77 -0
  419. data/public/ext-3.0.0/src/data/MemoryProxy.js +69 -0
  420. data/public/ext-3.0.0/src/data/Record.js +400 -0
  421. data/public/ext-3.0.0/src/data/ScriptTagProxy.js +279 -0
  422. data/public/ext-3.0.0/src/data/SortTypes.js +91 -0
  423. data/public/ext-3.0.0/src/data/Store.js +1492 -0
  424. data/public/ext-3.0.0/src/data/StoreMgr.js +72 -0
  425. data/public/ext-3.0.0/src/data/Tree.js +785 -0
  426. data/public/ext-3.0.0/src/data/XmlReader.js +128 -0
  427. data/public/ext-3.0.0/src/data/XmlStore.js +75 -0
  428. data/public/ext-3.0.0/src/data/XmlWriter.js +45 -0
  429. data/public/ext-3.0.0/src/data/core/Connection.js +575 -0
  430. data/public/ext-3.0.0/src/dd/DDCore.js +2992 -0
  431. data/public/ext-3.0.0/src/dd/DragSource.js +365 -0
  432. data/public/ext-3.0.0/src/dd/DragTracker.js +217 -0
  433. data/public/ext-3.0.0/src/dd/DragZone.js +133 -0
  434. data/public/ext-3.0.0/src/dd/DropTarget.js +115 -0
  435. data/public/ext-3.0.0/src/dd/DropZone.js +262 -0
  436. data/public/ext-3.0.0/src/dd/Registry.js +127 -0
  437. data/public/ext-3.0.0/src/dd/ScrollManager.js +201 -0
  438. data/public/ext-3.0.0/src/dd/StatusProxy.js +171 -0
  439. data/public/ext-3.0.0/src/debug.js +906 -0
  440. data/public/ext-3.0.0/src/direct/Direct.js +235 -0
  441. data/public/ext-3.0.0/src/direct/Event.js +34 -0
  442. data/public/ext-3.0.0/src/direct/JsonProvider.js +45 -0
  443. data/public/ext-3.0.0/src/direct/PollingProvider.js +151 -0
  444. data/public/ext-3.0.0/src/direct/Provider.js +110 -0
  445. data/public/ext-3.0.0/src/direct/RemotingProvider.js +373 -0
  446. data/public/ext-3.0.0/src/direct/Transaction.js +32 -0
  447. data/public/ext-3.0.0/src/locale/ext-lang-af.js +184 -0
  448. data/public/ext-3.0.0/src/locale/ext-lang-bg.js +278 -0
  449. data/public/ext-3.0.0/src/locale/ext-lang-ca.js +315 -0
  450. data/public/ext-3.0.0/src/locale/ext-lang-cs.js +293 -0
  451. data/public/ext-3.0.0/src/locale/ext-lang-da.js +296 -0
  452. data/public/ext-3.0.0/src/locale/ext-lang-de.js +326 -0
  453. data/public/ext-3.0.0/src/locale/ext-lang-el_GR.js +309 -0
  454. data/public/ext-3.0.0/src/locale/ext-lang-en.js +335 -0
  455. data/public/ext-3.0.0/src/locale/ext-lang-en_GB.js +315 -0
  456. data/public/ext-3.0.0/src/locale/ext-lang-es.js +318 -0
  457. data/public/ext-3.0.0/src/locale/ext-lang-fa.js +272 -0
  458. data/public/ext-3.0.0/src/locale/ext-lang-fi.js +302 -0
  459. data/public/ext-3.0.0/src/locale/ext-lang-fr.js +335 -0
  460. data/public/ext-3.0.0/src/locale/ext-lang-fr_CA.js +218 -0
  461. data/public/ext-3.0.0/src/locale/ext-lang-gr.js +175 -0
  462. data/public/ext-3.0.0/src/locale/ext-lang-he.js +292 -0
  463. data/public/ext-3.0.0/src/locale/ext-lang-hr.js +295 -0
  464. data/public/ext-3.0.0/src/locale/ext-lang-hu.js +296 -0
  465. data/public/ext-3.0.0/src/locale/ext-lang-id.js +302 -0
  466. data/public/ext-3.0.0/src/locale/ext-lang-it.js +295 -0
  467. data/public/ext-3.0.0/src/locale/ext-lang-ja.js +318 -0
  468. data/public/ext-3.0.0/src/locale/ext-lang-ko.js +267 -0
  469. data/public/ext-3.0.0/src/locale/ext-lang-lt.js +333 -0
  470. data/public/ext-3.0.0/src/locale/ext-lang-lv.js +176 -0
  471. data/public/ext-3.0.0/src/locale/ext-lang-mk.js +176 -0
  472. data/public/ext-3.0.0/src/locale/ext-lang-nl.js +323 -0
  473. data/public/ext-3.0.0/src/locale/ext-lang-no_NB.js +294 -0
  474. data/public/ext-3.0.0/src/locale/ext-lang-no_NN.js +294 -0
  475. data/public/ext-3.0.0/src/locale/ext-lang-pl.js +304 -0
  476. data/public/ext-3.0.0/src/locale/ext-lang-pt.js +260 -0
  477. data/public/ext-3.0.0/src/locale/ext-lang-pt_BR.js +302 -0
  478. data/public/ext-3.0.0/src/locale/ext-lang-pt_PT.js +298 -0
  479. data/public/ext-3.0.0/src/locale/ext-lang-ro.js +295 -0
  480. data/public/ext-3.0.0/src/locale/ext-lang-ru.js +319 -0
  481. data/public/ext-3.0.0/src/locale/ext-lang-sk.js +182 -0
  482. data/public/ext-3.0.0/src/locale/ext-lang-sl.js +176 -0
  483. data/public/ext-3.0.0/src/locale/ext-lang-sr.js +179 -0
  484. data/public/ext-3.0.0/src/locale/ext-lang-sr_RS.js +178 -0
  485. data/public/ext-3.0.0/src/locale/ext-lang-sv_SE.js +178 -0
  486. data/public/ext-3.0.0/src/locale/ext-lang-th.js +294 -0
  487. data/public/ext-3.0.0/src/locale/ext-lang-tr.js +306 -0
  488. data/public/ext-3.0.0/src/locale/ext-lang-ukr.js +258 -0
  489. data/public/ext-3.0.0/src/locale/ext-lang-vn.js +181 -0
  490. data/public/ext-3.0.0/src/locale/ext-lang-zh_CN.js +174 -0
  491. data/public/ext-3.0.0/src/locale/ext-lang-zh_TW.js +178 -0
  492. data/public/ext-3.0.0/src/state/CookieProvider.js +91 -0
  493. data/public/ext-3.0.0/src/state/Provider.js +127 -0
  494. data/public/ext-3.0.0/src/state/StateManager.js +69 -0
  495. data/public/ext-3.0.0/src/util/CSS.js +161 -0
  496. data/public/ext-3.0.0/src/util/ClickRepeater.js +200 -0
  497. data/public/ext-3.0.0/src/util/Cookies.js +96 -0
  498. data/public/ext-3.0.0/src/util/Date.js +1317 -0
  499. data/public/ext-3.0.0/src/util/Format.js +356 -0
  500. data/public/ext-3.0.0/src/util/History.js +203 -0
  501. data/public/ext-3.0.0/src/util/KeyMap.js +242 -0
  502. data/public/ext-3.0.0/src/util/KeyNav.js +161 -0
  503. data/public/ext-3.0.0/src/util/MixedCollection.js +576 -0
  504. data/public/ext-3.0.0/src/util/Observable-more.js +178 -0
  505. data/public/ext-3.0.0/src/util/TextMetrics.js +131 -0
  506. data/public/ext-3.0.0/src/util/UpdateManager.js +536 -0
  507. data/public/ext-3.0.0/src/util/XTemplate.js +379 -0
  508. data/public/ext-3.0.0/src/util/core/DelayedTask.js +68 -0
  509. data/public/ext-3.0.0/src/util/core/JSON.js +174 -0
  510. data/public/ext-3.0.0/src/util/core/Observable.js +483 -0
  511. data/public/ext-3.0.0/src/util/core/TaskMgr.js +174 -0
  512. data/public/ext-3.0.0/src/widgets/Action.js +252 -0
  513. data/public/ext-3.0.0/src/widgets/BoxComponent.js +519 -0
  514. data/public/ext-3.0.0/src/widgets/Button.js +762 -0
  515. data/public/ext-3.0.0/src/widgets/ButtonGroup.js +103 -0
  516. data/public/ext-3.0.0/src/widgets/ColorPalette.js +148 -0
  517. data/public/ext-3.0.0/src/widgets/Component.js +1540 -0
  518. data/public/ext-3.0.0/src/widgets/ComponentMgr.js +159 -0
  519. data/public/ext-3.0.0/src/widgets/Container.js +894 -0
  520. data/public/ext-3.0.0/src/widgets/CycleButton.js +188 -0
  521. data/public/ext-3.0.0/src/widgets/DataView.js +749 -0
  522. data/public/ext-3.0.0/src/widgets/DatePicker.js +771 -0
  523. data/public/ext-3.0.0/src/widgets/Editor.js +385 -0
  524. data/public/ext-3.0.0/src/widgets/Layer.js +466 -0
  525. data/public/ext-3.0.0/src/widgets/LoadMask.js +123 -0
  526. data/public/ext-3.0.0/src/widgets/MessageBox.js +626 -0
  527. data/public/ext-3.0.0/src/widgets/PagingToolbar.js +502 -0
  528. data/public/ext-3.0.0/src/widgets/Panel.js +1772 -0
  529. data/public/ext-3.0.0/src/widgets/PanelDD.js +154 -0
  530. data/public/ext-3.0.0/src/widgets/ProgressBar.js +289 -0
  531. data/public/ext-3.0.0/src/widgets/Resizable.js +760 -0
  532. data/public/ext-3.0.0/src/widgets/Shadow.js +192 -0
  533. data/public/ext-3.0.0/src/widgets/Slider.js +426 -0
  534. data/public/ext-3.0.0/src/widgets/SplitBar.js +436 -0
  535. data/public/ext-3.0.0/src/widgets/SplitButton.js +124 -0
  536. data/public/ext-3.0.0/src/widgets/TabPanel.js +1100 -0
  537. data/public/ext-3.0.0/src/widgets/Toolbar.js +781 -0
  538. data/public/ext-3.0.0/src/widgets/Viewport.js +124 -0
  539. data/public/ext-3.0.0/src/widgets/Window.js +941 -0
  540. data/public/ext-3.0.0/src/widgets/WindowManager.js +187 -0
  541. data/public/ext-3.0.0/src/widgets/chart/Chart.js +721 -0
  542. data/public/ext-3.0.0/src/widgets/chart/EventProxy.js +20 -0
  543. data/public/ext-3.0.0/src/widgets/chart/FlashComponent.js +117 -0
  544. data/public/ext-3.0.0/src/widgets/chart/swfobject.js +783 -0
  545. data/public/ext-3.0.0/src/widgets/form/Action.js +626 -0
  546. data/public/ext-3.0.0/src/widgets/form/BasicForm.js +735 -0
  547. data/public/ext-3.0.0/src/widgets/form/Checkbox.js +177 -0
  548. data/public/ext-3.0.0/src/widgets/form/CheckboxGroup.js +419 -0
  549. data/public/ext-3.0.0/src/widgets/form/Combo.js +1232 -0
  550. data/public/ext-3.0.0/src/widgets/form/DateField.js +389 -0
  551. data/public/ext-3.0.0/src/widgets/form/DisplayField.js +98 -0
  552. data/public/ext-3.0.0/src/widgets/form/Field.js +640 -0
  553. data/public/ext-3.0.0/src/widgets/form/FieldSet.js +305 -0
  554. data/public/ext-3.0.0/src/widgets/form/Form.js +335 -0
  555. data/public/ext-3.0.0/src/widgets/form/Hidden.js +39 -0
  556. data/public/ext-3.0.0/src/widgets/form/HtmlEditor.js +1179 -0
  557. data/public/ext-3.0.0/src/widgets/form/Label.js +64 -0
  558. data/public/ext-3.0.0/src/widgets/form/NumberField.js +139 -0
  559. data/public/ext-3.0.0/src/widgets/form/Radio.js +81 -0
  560. data/public/ext-3.0.0/src/widgets/form/RadioGroup.js +116 -0
  561. data/public/ext-3.0.0/src/widgets/form/TextArea.js +117 -0
  562. data/public/ext-3.0.0/src/widgets/form/TextField.js +491 -0
  563. data/public/ext-3.0.0/src/widgets/form/TimeField.js +146 -0
  564. data/public/ext-3.0.0/src/widgets/form/TriggerField.js +328 -0
  565. data/public/ext-3.0.0/src/widgets/form/VTypes.js +135 -0
  566. data/public/ext-3.0.0/src/widgets/grid/AbstractSelectionModel.js +57 -0
  567. data/public/ext-3.0.0/src/widgets/grid/CellSelectionModel.js +262 -0
  568. data/public/ext-3.0.0/src/widgets/grid/CheckboxSelectionModel.js +103 -0
  569. data/public/ext-3.0.0/src/widgets/grid/Column.js +406 -0
  570. data/public/ext-3.0.0/src/widgets/grid/ColumnDD.js +199 -0
  571. data/public/ext-3.0.0/src/widgets/grid/ColumnModel.js +592 -0
  572. data/public/ext-3.0.0/src/widgets/grid/ColumnSplitDD.js +62 -0
  573. data/public/ext-3.0.0/src/widgets/grid/EditorGrid.js +291 -0
  574. data/public/ext-3.0.0/src/widgets/grid/GridDD.js +95 -0
  575. data/public/ext-3.0.0/src/widgets/grid/GridEditor.js +21 -0
  576. data/public/ext-3.0.0/src/widgets/grid/GridPanel.js +952 -0
  577. data/public/ext-3.0.0/src/widgets/grid/GridView.js +1776 -0
  578. data/public/ext-3.0.0/src/widgets/grid/GroupingView.js +517 -0
  579. data/public/ext-3.0.0/src/widgets/grid/PropertyGrid.js +370 -0
  580. data/public/ext-3.0.0/src/widgets/grid/RowNumberer.js +61 -0
  581. data/public/ext-3.0.0/src/widgets/grid/RowSelectionModel.js +530 -0
  582. data/public/ext-3.0.0/src/widgets/layout/AbsoluteLayout.js +82 -0
  583. data/public/ext-3.0.0/src/widgets/layout/AccordionLayout.js +177 -0
  584. data/public/ext-3.0.0/src/widgets/layout/AnchorLayout.js +200 -0
  585. data/public/ext-3.0.0/src/widgets/layout/BorderLayout.js +1108 -0
  586. data/public/ext-3.0.0/src/widgets/layout/BoxLayout.js +417 -0
  587. data/public/ext-3.0.0/src/widgets/layout/CardLayout.js +127 -0
  588. data/public/ext-3.0.0/src/widgets/layout/ColumnLayout.js +130 -0
  589. data/public/ext-3.0.0/src/widgets/layout/ContainerLayout.js +215 -0
  590. data/public/ext-3.0.0/src/widgets/layout/FitLayout.js +48 -0
  591. data/public/ext-3.0.0/src/widgets/layout/FormLayout.js +266 -0
  592. data/public/ext-3.0.0/src/widgets/layout/TableLayout.js +194 -0
  593. data/public/ext-3.0.0/src/widgets/list/ColumnResizer.js +123 -0
  594. data/public/ext-3.0.0/src/widgets/list/ListView.js +357 -0
  595. data/public/ext-3.0.0/src/widgets/list/Sorter.js +70 -0
  596. data/public/ext-3.0.0/src/widgets/menu/BaseItem.js +160 -0
  597. data/public/ext-3.0.0/src/widgets/menu/CheckItem.js +114 -0
  598. data/public/ext-3.0.0/src/widgets/menu/ColorMenu.js +72 -0
  599. data/public/ext-3.0.0/src/widgets/menu/DateMenu.js +90 -0
  600. data/public/ext-3.0.0/src/widgets/menu/Item.js +211 -0
  601. data/public/ext-3.0.0/src/widgets/menu/Menu.js +733 -0
  602. data/public/ext-3.0.0/src/widgets/menu/MenuMgr.js +211 -0
  603. data/public/ext-3.0.0/src/widgets/menu/Separator.js +46 -0
  604. data/public/ext-3.0.0/src/widgets/menu/TextItem.js +46 -0
  605. data/public/ext-3.0.0/src/widgets/tips/QuickTip.js +207 -0
  606. data/public/ext-3.0.0/src/widgets/tips/QuickTips.js +159 -0
  607. data/public/ext-3.0.0/src/widgets/tips/Tip.js +157 -0
  608. data/public/ext-3.0.0/src/widgets/tips/ToolTip.js +492 -0
  609. data/public/ext-3.0.0/src/widgets/tree/AsyncTreeNode.js +114 -0
  610. data/public/ext-3.0.0/src/widgets/tree/TreeDragZone.js +82 -0
  611. data/public/ext-3.0.0/src/widgets/tree/TreeDropZone.js +321 -0
  612. data/public/ext-3.0.0/src/widgets/tree/TreeEditor.js +160 -0
  613. data/public/ext-3.0.0/src/widgets/tree/TreeEventModel.js +169 -0
  614. data/public/ext-3.0.0/src/widgets/tree/TreeFilter.js +114 -0
  615. data/public/ext-3.0.0/src/widgets/tree/TreeLoader.js +342 -0
  616. data/public/ext-3.0.0/src/widgets/tree/TreeNode.js +546 -0
  617. data/public/ext-3.0.0/src/widgets/tree/TreeNodeUI.js +633 -0
  618. data/public/ext-3.0.0/src/widgets/tree/TreePanel.js +918 -0
  619. data/public/ext-3.0.0/src/widgets/tree/TreeSelectionModel.js +315 -0
  620. data/public/ext-3.0.0/src/widgets/tree/TreeSorter.js +106 -0
  621. data/public/js/ext-portal.js +235 -0
  622. data/public/js/global.js +7 -0
  623. data/public/js/outerframe.js +47 -0
  624. data/public/js/portal.js +713 -0
  625. data/public/js/test_chart.js +152 -0
  626. data/test/config.rb +62 -0
  627. data/test/config/hosts.yaml +5 -0
  628. data/test/config/log.yaml +1 -0
  629. data/test/config/memcache.yaml +5 -0
  630. data/test/exception.rb +39 -0
  631. data/test/method_missing.rb +14 -0
  632. data/test/module.rb +39 -0
  633. data/test/remote_lmp.rb +126 -0
  634. data/test/sinatra.rb +29 -0
  635. data/test/sinatra_base.rb +16 -0
  636. metadata +690 -0
@@ -0,0 +1,7 @@
1
+ /*
2
+ * Ext JS Library 3.0.0
3
+ * Copyright(c) 2006-2009 Ext JS, LLC
4
+ * licensing@extjs.com
5
+ * http://www.extjs.com/license
6
+ */
7
+ Ext.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
+ });