extjs-rails 4.1.0.alpha1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (517) hide show
  1. data/.gitignore +18 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE +36 -0
  4. data/README.md +29 -0
  5. data/Rakefile +2 -0
  6. data/app/assets/javascripts/extjs-rails/extjs-rails.js +1 -0
  7. data/app/assets/javascripts/extjs-rails/index.js.erb +9 -0
  8. data/app/assets/javascripts/extjs-rails/sdk.jsb3 +2017 -0
  9. data/app/assets/javascripts/extjs-rails/src/AbstractComponent.js +3290 -0
  10. data/app/assets/javascripts/extjs-rails/src/AbstractManager.js +144 -0
  11. data/app/assets/javascripts/extjs-rails/src/AbstractPlugin.js +72 -0
  12. data/app/assets/javascripts/extjs-rails/src/Action.js +276 -0
  13. data/app/assets/javascripts/extjs-rails/src/Ajax.js +99 -0
  14. data/app/assets/javascripts/extjs-rails/src/Component.js +1344 -0
  15. data/app/assets/javascripts/extjs-rails/src/ComponentLoader.js +202 -0
  16. data/app/assets/javascripts/extjs-rails/src/ComponentManager.js +47 -0
  17. data/app/assets/javascripts/extjs-rails/src/ComponentQuery.js +521 -0
  18. data/app/assets/javascripts/extjs-rails/src/Editor.js +494 -0
  19. data/app/assets/javascripts/extjs-rails/src/ElementLoader.js +404 -0
  20. data/app/assets/javascripts/extjs-rails/src/FocusManager.js +712 -0
  21. data/app/assets/javascripts/extjs-rails/src/Img.js +111 -0
  22. data/app/assets/javascripts/extjs-rails/src/Layer.js +543 -0
  23. data/app/assets/javascripts/extjs-rails/src/LoadMask.js +432 -0
  24. data/app/assets/javascripts/extjs-rails/src/ModelManager.js +186 -0
  25. data/app/assets/javascripts/extjs-rails/src/PluginManager.js +110 -0
  26. data/app/assets/javascripts/extjs-rails/src/ProgressBar.js +336 -0
  27. data/app/assets/javascripts/extjs-rails/src/Shadow.js +233 -0
  28. data/app/assets/javascripts/extjs-rails/src/ShadowPool.js +43 -0
  29. data/app/assets/javascripts/extjs-rails/src/Template.js +331 -0
  30. data/app/assets/javascripts/extjs-rails/src/XTemplate.js +365 -0
  31. data/app/assets/javascripts/extjs-rails/src/XTemplateCompiler.js +450 -0
  32. data/app/assets/javascripts/extjs-rails/src/XTemplateParser.js +249 -0
  33. data/app/assets/javascripts/extjs-rails/src/ZIndexManager.js +519 -0
  34. data/app/assets/javascripts/extjs-rails/src/app/Application.js +271 -0
  35. data/app/assets/javascripts/extjs-rails/src/app/Controller.js +458 -0
  36. data/app/assets/javascripts/extjs-rails/src/app/EventBus.js +112 -0
  37. data/app/assets/javascripts/extjs-rails/src/button/Button.js +1483 -0
  38. data/app/assets/javascripts/extjs-rails/src/button/Cycle.js +215 -0
  39. data/app/assets/javascripts/extjs-rails/src/button/Split.js +99 -0
  40. data/app/assets/javascripts/extjs-rails/src/chart/Callout.js +140 -0
  41. data/app/assets/javascripts/extjs-rails/src/chart/Chart.js +966 -0
  42. data/app/assets/javascripts/extjs-rails/src/chart/Highlight.js +172 -0
  43. data/app/assets/javascripts/extjs-rails/src/chart/Label.js +241 -0
  44. data/app/assets/javascripts/extjs-rails/src/chart/Legend.js +474 -0
  45. data/app/assets/javascripts/extjs-rails/src/chart/LegendItem.js +217 -0
  46. data/app/assets/javascripts/extjs-rails/src/chart/Mask.js +230 -0
  47. data/app/assets/javascripts/extjs-rails/src/chart/MaskLayer.js +48 -0
  48. data/app/assets/javascripts/extjs-rails/src/chart/Navigation.js +79 -0
  49. data/app/assets/javascripts/extjs-rails/src/chart/Shape.js +106 -0
  50. data/app/assets/javascripts/extjs-rails/src/chart/Tip.js +98 -0
  51. data/app/assets/javascripts/extjs-rails/src/chart/TipSurface.js +42 -0
  52. data/app/assets/javascripts/extjs-rails/src/chart/axis/Abstract.js +73 -0
  53. data/app/assets/javascripts/extjs-rails/src/chart/axis/Axis.js +961 -0
  54. data/app/assets/javascripts/extjs-rails/src/chart/axis/Category.js +130 -0
  55. data/app/assets/javascripts/extjs-rails/src/chart/axis/Gauge.js +203 -0
  56. data/app/assets/javascripts/extjs-rails/src/chart/axis/Numeric.js +235 -0
  57. data/app/assets/javascripts/extjs-rails/src/chart/axis/Radial.js +204 -0
  58. data/app/assets/javascripts/extjs-rails/src/chart/axis/Time.js +135 -0
  59. data/app/assets/javascripts/extjs-rails/src/chart/series/Area.js +803 -0
  60. data/app/assets/javascripts/extjs-rails/src/chart/series/Bar.js +853 -0
  61. data/app/assets/javascripts/extjs-rails/src/chart/series/Cartesian.js +328 -0
  62. data/app/assets/javascripts/extjs-rails/src/chart/series/Column.js +104 -0
  63. data/app/assets/javascripts/extjs-rails/src/chart/series/Gauge.js +490 -0
  64. data/app/assets/javascripts/extjs-rails/src/chart/series/Line.js +1104 -0
  65. data/app/assets/javascripts/extjs-rails/src/chart/series/Pie.js +1072 -0
  66. data/app/assets/javascripts/extjs-rails/src/chart/series/Radar.js +440 -0
  67. data/app/assets/javascripts/extjs-rails/src/chart/series/Scatter.js +668 -0
  68. data/app/assets/javascripts/extjs-rails/src/chart/series/Series.js +443 -0
  69. data/app/assets/javascripts/extjs-rails/src/chart/theme/Base.js +175 -0
  70. data/app/assets/javascripts/extjs-rails/src/chart/theme/Theme.js +253 -0
  71. data/app/assets/javascripts/extjs-rails/src/container/AbstractContainer.js +1062 -0
  72. data/app/assets/javascripts/extjs-rails/src/container/ButtonGroup.js +143 -0
  73. data/app/assets/javascripts/extjs-rails/src/container/Container.js +212 -0
  74. data/app/assets/javascripts/extjs-rails/src/container/DockingContainer.js +265 -0
  75. data/app/assets/javascripts/extjs-rails/src/container/Viewport.js +184 -0
  76. data/app/assets/javascripts/extjs-rails/src/core/dom/Element.form.js +50 -0
  77. data/app/assets/javascripts/extjs-rails/src/core/dom/Element.static-more.js +159 -0
  78. data/app/assets/javascripts/extjs-rails/src/core/examples/index.html +321 -0
  79. data/app/assets/javascripts/extjs-rails/src/core/examples/index.js +6 -0
  80. data/app/assets/javascripts/extjs-rails/src/core/examples/src/Sample/CTO.js +25 -0
  81. data/app/assets/javascripts/extjs-rails/src/core/examples/src/Sample/CoolGuy.js +20 -0
  82. data/app/assets/javascripts/extjs-rails/src/core/examples/src/Sample/Developer.js +43 -0
  83. data/app/assets/javascripts/extjs-rails/src/core/examples/src/Sample/Gun.js +3 -0
  84. data/app/assets/javascripts/extjs-rails/src/core/examples/src/Sample/HumanResource.js +23 -0
  85. data/app/assets/javascripts/extjs-rails/src/core/examples/src/Sample/Musician.js +20 -0
  86. data/app/assets/javascripts/extjs-rails/src/core/examples/src/Sample/Person.js +50 -0
  87. data/app/assets/javascripts/extjs-rails/src/core/examples/src/Sample/ability/CanComposeSongs.js +9 -0
  88. data/app/assets/javascripts/extjs-rails/src/core/examples/src/Sample/ability/CanPlayGuitar.js +9 -0
  89. data/app/assets/javascripts/extjs-rails/src/core/examples/src/Sample/ability/CanSing.js +18 -0
  90. data/app/assets/javascripts/extjs-rails/src/core/examples/src/Sample/deadlock/A.js +3 -0
  91. data/app/assets/javascripts/extjs-rails/src/core/examples/src/Sample/deadlock/B.js +3 -0
  92. data/app/assets/javascripts/extjs-rails/src/core/examples/src/Sample/deadlock/C.js +3 -0
  93. data/app/assets/javascripts/extjs-rails/src/core/examples/src/Sample/deadlock/D.js +3 -0
  94. data/app/assets/javascripts/extjs-rails/src/core/examples/src/Sample/deadlock/E.js +3 -0
  95. data/app/assets/javascripts/extjs-rails/src/core/examples/src/Sample/notdeadlock/A.js +3 -0
  96. data/app/assets/javascripts/extjs-rails/src/core/examples/src/Sample/notdeadlock/B.js +4 -0
  97. data/app/assets/javascripts/extjs-rails/src/core/examples/src/Sample/notdeadlock/C.js +3 -0
  98. data/app/assets/javascripts/extjs-rails/src/core/src/EventManager.js +1167 -0
  99. data/app/assets/javascripts/extjs-rails/src/core/src/EventObject.js +883 -0
  100. data/app/assets/javascripts/extjs-rails/src/core/src/Ext-more.js +1283 -0
  101. data/app/assets/javascripts/extjs-rails/src/core/src/Ext.js +736 -0
  102. data/app/assets/javascripts/extjs-rails/src/core/src/Support.js +662 -0
  103. data/app/assets/javascripts/extjs-rails/src/core/src/class/Base.js +1085 -0
  104. data/app/assets/javascripts/extjs-rails/src/core/src/class/Class.js +676 -0
  105. data/app/assets/javascripts/extjs-rails/src/core/src/class/ClassManager.js +1591 -0
  106. data/app/assets/javascripts/extjs-rails/src/core/src/class/Loader.js +1423 -0
  107. data/app/assets/javascripts/extjs-rails/src/core/src/dom/AbstractElement.alignment.js +173 -0
  108. data/app/assets/javascripts/extjs-rails/src/core/src/dom/AbstractElement.insertion.js +193 -0
  109. data/app/assets/javascripts/extjs-rails/src/core/src/dom/AbstractElement.js +681 -0
  110. data/app/assets/javascripts/extjs-rails/src/core/src/dom/AbstractElement.position.js +356 -0
  111. data/app/assets/javascripts/extjs-rails/src/core/src/dom/AbstractElement.static.js +474 -0
  112. data/app/assets/javascripts/extjs-rails/src/core/src/dom/AbstractElement.style.js +851 -0
  113. data/app/assets/javascripts/extjs-rails/src/core/src/dom/AbstractElement.traversal.js +180 -0
  114. data/app/assets/javascripts/extjs-rails/src/core/src/dom/AbstractHelper.js +291 -0
  115. data/app/assets/javascripts/extjs-rails/src/core/src/dom/AbstractQuery.js +72 -0
  116. data/app/assets/javascripts/extjs-rails/src/core/src/dom/CompositeElement.js +75 -0
  117. data/app/assets/javascripts/extjs-rails/src/core/src/dom/CompositeElementLite.js +436 -0
  118. data/app/assets/javascripts/extjs-rails/src/core/src/dom/DomQuery-aria.js +1049 -0
  119. data/app/assets/javascripts/extjs-rails/src/core/src/env/Browser.js +186 -0
  120. data/app/assets/javascripts/extjs-rails/src/core/src/env/FeatureDetector.js +274 -0
  121. data/app/assets/javascripts/extjs-rails/src/core/src/env/OS.js +141 -0
  122. data/app/assets/javascripts/extjs-rails/src/core/src/lang/Array.js +1205 -0
  123. data/app/assets/javascripts/extjs-rails/src/core/src/lang/Date.js +1463 -0
  124. data/app/assets/javascripts/extjs-rails/src/core/src/lang/Error.js +326 -0
  125. data/app/assets/javascripts/extjs-rails/src/core/src/lang/Function.js +485 -0
  126. data/app/assets/javascripts/extjs-rails/src/core/src/lang/Number.js +175 -0
  127. data/app/assets/javascripts/extjs-rails/src/core/src/lang/Object.js +606 -0
  128. data/app/assets/javascripts/extjs-rails/src/core/src/lang/String.js +333 -0
  129. data/app/assets/javascripts/extjs-rails/src/core/src/misc/JSON.js +236 -0
  130. data/app/assets/javascripts/extjs-rails/src/core/src/perf/Accumulator.js +244 -0
  131. data/app/assets/javascripts/extjs-rails/src/core/src/perf/Monitor.js +197 -0
  132. data/app/assets/javascripts/extjs-rails/src/core/src/util/DelayedTask.js +71 -0
  133. data/app/assets/javascripts/extjs-rails/src/core/src/util/Event.js +215 -0
  134. data/app/assets/javascripts/extjs-rails/src/core/src/util/Format.js +551 -0
  135. data/app/assets/javascripts/extjs-rails/src/core/src/util/TaskManager.js +417 -0
  136. data/app/assets/javascripts/extjs-rails/src/core/src/version/Version.js +364 -0
  137. data/app/assets/javascripts/extjs-rails/src/core/test/unit/README.MD +91 -0
  138. data/app/assets/javascripts/extjs-rails/src/core/test/unit/bootstrap.js +39 -0
  139. data/app/assets/javascripts/extjs-rails/src/core/test/unit/build/build-data.js +34 -0
  140. data/app/assets/javascripts/extjs-rails/src/core/test/unit/build/build.sh +2 -0
  141. data/app/assets/javascripts/extjs-rails/src/core/test/unit/data.js +27 -0
  142. data/app/assets/javascripts/extjs-rails/src/core/test/unit/index.html +15 -0
  143. data/app/assets/javascripts/extjs-rails/src/core/test/unit/other_specs/dom.html +40 -0
  144. data/app/assets/javascripts/extjs-rails/src/core/test/unit/other_specs/dom/extjs-api.js +12 -0
  145. data/app/assets/javascripts/extjs-rails/src/core/test/unit/other_specs/dom/platform-api.js +134 -0
  146. data/app/assets/javascripts/extjs-rails/src/core/test/unit/other_specs/dom/sanity.js +4 -0
  147. data/app/assets/javascripts/extjs-rails/src/core/test/unit/other_specs/dom/touch-api-out.js +128 -0
  148. data/app/assets/javascripts/extjs-rails/src/core/test/unit/other_specs/dom/touch-api.js +89 -0
  149. data/app/assets/javascripts/extjs-rails/src/core/test/unit/other_specs/env/Environment.js +357 -0
  150. data/app/assets/javascripts/extjs-rails/src/core/test/unit/resources/APITest.js +37 -0
  151. data/app/assets/javascripts/extjs-rails/src/core/test/unit/resources/jsb3.js +14 -0
  152. data/app/assets/javascripts/extjs-rails/src/core/test/unit/resources/test-setup.js +137 -0
  153. data/app/assets/javascripts/extjs-rails/src/core/test/unit/spec/EventManager.js +629 -0
  154. data/app/assets/javascripts/extjs-rails/src/core/test/unit/spec/Ext-mess.backup +198 -0
  155. data/app/assets/javascripts/extjs-rails/src/core/test/unit/spec/Ext-more.js +520 -0
  156. data/app/assets/javascripts/extjs-rails/src/core/test/unit/spec/Ext.js +1550 -0
  157. data/app/assets/javascripts/extjs-rails/src/core/test/unit/spec/Support.js +250 -0
  158. data/app/assets/javascripts/extjs-rails/src/core/test/unit/spec/class/Base.js +47 -0
  159. data/app/assets/javascripts/extjs-rails/src/core/test/unit/spec/class/Class.js +561 -0
  160. data/app/assets/javascripts/extjs-rails/src/core/test/unit/spec/class/ClassManager.js +555 -0
  161. data/app/assets/javascripts/extjs-rails/src/core/test/unit/spec/dom/CompositeElementLite.js +409 -0
  162. data/app/assets/javascripts/extjs-rails/src/core/test/unit/spec/dom/DomHelper.js +444 -0
  163. data/app/assets/javascripts/extjs-rails/src/core/test/unit/spec/dom/Element.insertion.js +342 -0
  164. data/app/assets/javascripts/extjs-rails/src/core/test/unit/spec/dom/Element.js +731 -0
  165. data/app/assets/javascripts/extjs-rails/src/core/test/unit/spec/dom/Element.static.js +201 -0
  166. data/app/assets/javascripts/extjs-rails/src/core/test/unit/spec/dom/Element.style.js +118 -0
  167. data/app/assets/javascripts/extjs-rails/src/core/test/unit/spec/dom/Element.traversal.js +336 -0
  168. data/app/assets/javascripts/extjs-rails/src/core/test/unit/spec/lang/Array.js +1229 -0
  169. data/app/assets/javascripts/extjs-rails/src/core/test/unit/spec/lang/Date.js +697 -0
  170. data/app/assets/javascripts/extjs-rails/src/core/test/unit/spec/lang/Error.js +277 -0
  171. data/app/assets/javascripts/extjs-rails/src/core/test/unit/spec/lang/Function.js +536 -0
  172. data/app/assets/javascripts/extjs-rails/src/core/test/unit/spec/lang/Number.js +323 -0
  173. data/app/assets/javascripts/extjs-rails/src/core/test/unit/spec/lang/Object.js +591 -0
  174. data/app/assets/javascripts/extjs-rails/src/core/test/unit/spec/lang/String.js +451 -0
  175. data/app/assets/javascripts/extjs-rails/src/core/test/unit/spec/misc/JSON.js +252 -0
  176. data/app/assets/javascripts/extjs-rails/src/core/test/unit/spec/util/Format.js +521 -0
  177. data/app/assets/javascripts/extjs-rails/src/core/test/unit/spec/version/Version.js +148 -0
  178. data/app/assets/javascripts/extjs-rails/src/core/test/unit/specs.html +19 -0
  179. data/app/assets/javascripts/extjs-rails/src/data/AbstractStore.js +887 -0
  180. data/app/assets/javascripts/extjs-rails/src/data/ArrayStore.js +74 -0
  181. data/app/assets/javascripts/extjs-rails/src/data/Batch.js +236 -0
  182. data/app/assets/javascripts/extjs-rails/src/data/BufferStore.js +13 -0
  183. data/app/assets/javascripts/extjs-rails/src/data/Connection.js +969 -0
  184. data/app/assets/javascripts/extjs-rails/src/data/DirectStore.js +50 -0
  185. data/app/assets/javascripts/extjs-rails/src/data/Errors.js +52 -0
  186. data/app/assets/javascripts/extjs-rails/src/data/Field.js +341 -0
  187. data/app/assets/javascripts/extjs-rails/src/data/IdGenerator.js +198 -0
  188. data/app/assets/javascripts/extjs-rails/src/data/JsonP.js +253 -0
  189. data/app/assets/javascripts/extjs-rails/src/data/JsonPStore.js +51 -0
  190. data/app/assets/javascripts/extjs-rails/src/data/JsonStore.js +60 -0
  191. data/app/assets/javascripts/extjs-rails/src/data/Model.js +1673 -0
  192. data/app/assets/javascripts/extjs-rails/src/data/NodeInterface.js +1294 -0
  193. data/app/assets/javascripts/extjs-rails/src/data/NodeStore.js +254 -0
  194. data/app/assets/javascripts/extjs-rails/src/data/Operation.js +331 -0
  195. data/app/assets/javascripts/extjs-rails/src/data/Request.js +40 -0
  196. data/app/assets/javascripts/extjs-rails/src/data/ResultSet.js +56 -0
  197. data/app/assets/javascripts/extjs-rails/src/data/SequentialIdGenerator.js +61 -0
  198. data/app/assets/javascripts/extjs-rails/src/data/SortTypes.js +125 -0
  199. data/app/assets/javascripts/extjs-rails/src/data/Store.js +2609 -0
  200. data/app/assets/javascripts/extjs-rails/src/data/StoreManager.js +156 -0
  201. data/app/assets/javascripts/extjs-rails/src/data/Tree.js +290 -0
  202. data/app/assets/javascripts/extjs-rails/src/data/TreeStore.js +655 -0
  203. data/app/assets/javascripts/extjs-rails/src/data/Types.js +190 -0
  204. data/app/assets/javascripts/extjs-rails/src/data/UuidGenerator.js +215 -0
  205. data/app/assets/javascripts/extjs-rails/src/data/XmlStore.js +76 -0
  206. data/app/assets/javascripts/extjs-rails/src/data/association/Association.js +243 -0
  207. data/app/assets/javascripts/extjs-rails/src/data/association/BelongsTo.js +291 -0
  208. data/app/assets/javascripts/extjs-rails/src/data/association/HasMany.js +289 -0
  209. data/app/assets/javascripts/extjs-rails/src/data/association/HasOne.js +304 -0
  210. data/app/assets/javascripts/extjs-rails/src/data/proxy/Ajax.js +282 -0
  211. data/app/assets/javascripts/extjs-rails/src/data/proxy/Client.js +21 -0
  212. data/app/assets/javascripts/extjs-rails/src/data/proxy/Direct.js +181 -0
  213. data/app/assets/javascripts/extjs-rails/src/data/proxy/JsonP.js +313 -0
  214. data/app/assets/javascripts/extjs-rails/src/data/proxy/LocalStorage.js +69 -0
  215. data/app/assets/javascripts/extjs-rails/src/data/proxy/Memory.js +156 -0
  216. data/app/assets/javascripts/extjs-rails/src/data/proxy/Proxy.js +433 -0
  217. data/app/assets/javascripts/extjs-rails/src/data/proxy/Rest.js +173 -0
  218. data/app/assets/javascripts/extjs-rails/src/data/proxy/Server.js +460 -0
  219. data/app/assets/javascripts/extjs-rails/src/data/proxy/SessionStorage.js +39 -0
  220. data/app/assets/javascripts/extjs-rails/src/data/proxy/WebStorage.js +546 -0
  221. data/app/assets/javascripts/extjs-rails/src/data/reader/Array.js +68 -0
  222. data/app/assets/javascripts/extjs-rails/src/data/reader/Json.js +383 -0
  223. data/app/assets/javascripts/extjs-rails/src/data/reader/Reader.js +735 -0
  224. data/app/assets/javascripts/extjs-rails/src/data/reader/Xml.js +292 -0
  225. data/app/assets/javascripts/extjs-rails/src/data/validations.js +149 -0
  226. data/app/assets/javascripts/extjs-rails/src/data/writer/Json.js +81 -0
  227. data/app/assets/javascripts/extjs-rails/src/data/writer/Writer.js +147 -0
  228. data/app/assets/javascripts/extjs-rails/src/data/writer/Xml.js +88 -0
  229. data/app/assets/javascripts/extjs-rails/src/dd/DD.js +300 -0
  230. data/app/assets/javascripts/extjs-rails/src/dd/DDProxy.js +204 -0
  231. data/app/assets/javascripts/extjs-rails/src/dd/DDTarget.js +171 -0
  232. data/app/assets/javascripts/extjs-rails/src/dd/DragDrop.js +1101 -0
  233. data/app/assets/javascripts/extjs-rails/src/dd/DragDropManager.js +1264 -0
  234. data/app/assets/javascripts/extjs-rails/src/dd/DragSource.js +392 -0
  235. data/app/assets/javascripts/extjs-rails/src/dd/DragTracker.js +562 -0
  236. data/app/assets/javascripts/extjs-rails/src/dd/DragZone.js +137 -0
  237. data/app/assets/javascripts/extjs-rails/src/dd/DropTarget.js +118 -0
  238. data/app/assets/javascripts/extjs-rails/src/dd/DropZone.js +254 -0
  239. data/app/assets/javascripts/extjs-rails/src/dd/Registry.js +117 -0
  240. data/app/assets/javascripts/extjs-rails/src/dd/ScrollManager.js +218 -0
  241. data/app/assets/javascripts/extjs-rails/src/dd/StatusProxy.js +179 -0
  242. data/app/assets/javascripts/extjs-rails/src/diag/layout/Context.js +523 -0
  243. data/app/assets/javascripts/extjs-rails/src/diag/layout/ContextItem.js +179 -0
  244. data/app/assets/javascripts/extjs-rails/src/direct/Event.js +35 -0
  245. data/app/assets/javascripts/extjs-rails/src/direct/ExceptionEvent.js +16 -0
  246. data/app/assets/javascripts/extjs-rails/src/direct/JsonProvider.js +82 -0
  247. data/app/assets/javascripts/extjs-rails/src/direct/Manager.js +263 -0
  248. data/app/assets/javascripts/extjs-rails/src/direct/PollingProvider.js +156 -0
  249. data/app/assets/javascripts/extjs-rails/src/direct/Provider.js +96 -0
  250. data/app/assets/javascripts/extjs-rails/src/direct/RemotingEvent.js +24 -0
  251. data/app/assets/javascripts/extjs-rails/src/direct/RemotingMethod.js +100 -0
  252. data/app/assets/javascripts/extjs-rails/src/direct/RemotingProvider.js +510 -0
  253. data/app/assets/javascripts/extjs-rails/src/direct/Transaction.js +41 -0
  254. data/app/assets/javascripts/extjs-rails/src/dom/Element.alignment.js +378 -0
  255. data/app/assets/javascripts/extjs-rails/src/dom/Element.anim.js +962 -0
  256. data/app/assets/javascripts/extjs-rails/src/dom/Element.dd.js +40 -0
  257. data/app/assets/javascripts/extjs-rails/src/dom/Element.fx.js +194 -0
  258. data/app/assets/javascripts/extjs-rails/src/dom/Element.js +1407 -0
  259. data/app/assets/javascripts/extjs-rails/src/dom/Element.position.js +501 -0
  260. data/app/assets/javascripts/extjs-rails/src/dom/Element.scroll.js +214 -0
  261. data/app/assets/javascripts/extjs-rails/src/dom/Element.style.js +792 -0
  262. data/app/assets/javascripts/extjs-rails/src/dom/Element.traversal.js +8 -0
  263. data/app/assets/javascripts/extjs-rails/src/dom/Helper.js +466 -0
  264. data/app/assets/javascripts/extjs-rails/src/dom/Query.js +1067 -0
  265. data/app/assets/javascripts/extjs-rails/src/draw/Color.js +303 -0
  266. data/app/assets/javascripts/extjs-rails/src/draw/Component.js +245 -0
  267. data/app/assets/javascripts/extjs-rails/src/draw/CompositeSprite.js +299 -0
  268. data/app/assets/javascripts/extjs-rails/src/draw/Draw.js +1217 -0
  269. data/app/assets/javascripts/extjs-rails/src/draw/Matrix.js +183 -0
  270. data/app/assets/javascripts/extjs-rails/src/draw/Sprite.js +554 -0
  271. data/app/assets/javascripts/extjs-rails/src/draw/SpriteDD.js +87 -0
  272. data/app/assets/javascripts/extjs-rails/src/draw/Surface.js +1001 -0
  273. data/app/assets/javascripts/extjs-rails/src/draw/Text.js +175 -0
  274. data/app/assets/javascripts/extjs-rails/src/draw/engine/ImageExporter.js +106 -0
  275. data/app/assets/javascripts/extjs-rails/src/draw/engine/Svg.js +734 -0
  276. data/app/assets/javascripts/extjs-rails/src/draw/engine/SvgExporter.js +280 -0
  277. data/app/assets/javascripts/extjs-rails/src/draw/engine/Vml.js +916 -0
  278. data/app/assets/javascripts/extjs-rails/src/flash/Component.js +248 -0
  279. data/app/assets/javascripts/extjs-rails/src/form/Basic.js +1018 -0
  280. data/app/assets/javascripts/extjs-rails/src/form/CheckboxGroup.js +441 -0
  281. data/app/assets/javascripts/extjs-rails/src/form/CheckboxManager.js +26 -0
  282. data/app/assets/javascripts/extjs-rails/src/form/FieldAncestor.js +210 -0
  283. data/app/assets/javascripts/extjs-rails/src/form/FieldContainer.js +290 -0
  284. data/app/assets/javascripts/extjs-rails/src/form/FieldSet.js +506 -0
  285. data/app/assets/javascripts/extjs-rails/src/form/Label.js +110 -0
  286. data/app/assets/javascripts/extjs-rails/src/form/Labelable.js +764 -0
  287. data/app/assets/javascripts/extjs-rails/src/form/Panel.js +335 -0
  288. data/app/assets/javascripts/extjs-rails/src/form/RadioGroup.js +124 -0
  289. data/app/assets/javascripts/extjs-rails/src/form/RadioManager.js +26 -0
  290. data/app/assets/javascripts/extjs-rails/src/form/action/Action.js +307 -0
  291. data/app/assets/javascripts/extjs-rails/src/form/action/DirectLoad.js +107 -0
  292. data/app/assets/javascripts/extjs-rails/src/form/action/DirectSubmit.js +119 -0
  293. data/app/assets/javascripts/extjs-rails/src/form/action/Load.js +120 -0
  294. data/app/assets/javascripts/extjs-rails/src/form/action/StandardSubmit.js +34 -0
  295. data/app/assets/javascripts/extjs-rails/src/form/action/Submit.js +257 -0
  296. data/app/assets/javascripts/extjs-rails/src/form/field/Base.js +813 -0
  297. data/app/assets/javascripts/extjs-rails/src/form/field/Checkbox.js +505 -0
  298. data/app/assets/javascripts/extjs-rails/src/form/field/ComboBox.js +1427 -0
  299. data/app/assets/javascripts/extjs-rails/src/form/field/Date.js +578 -0
  300. data/app/assets/javascripts/extjs-rails/src/form/field/Display.js +155 -0
  301. data/app/assets/javascripts/extjs-rails/src/form/field/Field.js +430 -0
  302. data/app/assets/javascripts/extjs-rails/src/form/field/File.js +265 -0
  303. data/app/assets/javascripts/extjs-rails/src/form/field/Hidden.js +75 -0
  304. data/app/assets/javascripts/extjs-rails/src/form/field/HtmlEditor.js +1439 -0
  305. data/app/assets/javascripts/extjs-rails/src/form/field/Number.js +380 -0
  306. data/app/assets/javascripts/extjs-rails/src/form/field/Picker.js +321 -0
  307. data/app/assets/javascripts/extjs-rails/src/form/field/Radio.js +279 -0
  308. data/app/assets/javascripts/extjs-rails/src/form/field/Spinner.js +321 -0
  309. data/app/assets/javascripts/extjs-rails/src/form/field/Text.js +727 -0
  310. data/app/assets/javascripts/extjs-rails/src/form/field/TextArea.js +228 -0
  311. data/app/assets/javascripts/extjs-rails/src/form/field/Time.js +459 -0
  312. data/app/assets/javascripts/extjs-rails/src/form/field/Trigger.js +469 -0
  313. data/app/assets/javascripts/extjs-rails/src/form/field/VTypes.js +172 -0
  314. data/app/assets/javascripts/extjs-rails/src/fx/Anim.js +472 -0
  315. data/app/assets/javascripts/extjs-rails/src/fx/Animator.js +410 -0
  316. data/app/assets/javascripts/extjs-rails/src/fx/CubicBezier.js +77 -0
  317. data/app/assets/javascripts/extjs-rails/src/fx/Easing.js +136 -0
  318. data/app/assets/javascripts/extjs-rails/src/fx/Manager.js +353 -0
  319. data/app/assets/javascripts/extjs-rails/src/fx/PropertyHandler.js +381 -0
  320. data/app/assets/javascripts/extjs-rails/src/fx/Queue.js +123 -0
  321. data/app/assets/javascripts/extjs-rails/src/fx/target/Component.js +118 -0
  322. data/app/assets/javascripts/extjs-rails/src/fx/target/CompositeElement.js +46 -0
  323. data/app/assets/javascripts/extjs-rails/src/fx/target/CompositeElementCSS.js +22 -0
  324. data/app/assets/javascripts/extjs-rails/src/fx/target/CompositeSprite.js +34 -0
  325. data/app/assets/javascripts/extjs-rails/src/fx/target/Element.js +83 -0
  326. data/app/assets/javascripts/extjs-rails/src/fx/target/ElementCSS.js +77 -0
  327. data/app/assets/javascripts/extjs-rails/src/fx/target/Sprite.js +128 -0
  328. data/app/assets/javascripts/extjs-rails/src/fx/target/Target.js +36 -0
  329. data/app/assets/javascripts/extjs-rails/src/grid/CellEditor.js +172 -0
  330. data/app/assets/javascripts/extjs-rails/src/grid/ColumnComponentLayout.js +34 -0
  331. data/app/assets/javascripts/extjs-rails/src/grid/ColumnLayout.js +201 -0
  332. data/app/assets/javascripts/extjs-rails/src/grid/Lockable.js +863 -0
  333. data/app/assets/javascripts/extjs-rails/src/grid/LockingView.js +169 -0
  334. data/app/assets/javascripts/extjs-rails/src/grid/PagingScroller.js +539 -0
  335. data/app/assets/javascripts/extjs-rails/src/grid/Panel.js +393 -0
  336. data/app/assets/javascripts/extjs-rails/src/grid/RowEditor.js +731 -0
  337. data/app/assets/javascripts/extjs-rails/src/grid/RowNumberer.js +76 -0
  338. data/app/assets/javascripts/extjs-rails/src/grid/Scroller.js +5 -0
  339. data/app/assets/javascripts/extjs-rails/src/grid/View.js +44 -0
  340. data/app/assets/javascripts/extjs-rails/src/grid/ViewDropZone.js +41 -0
  341. data/app/assets/javascripts/extjs-rails/src/grid/column/Action.js +318 -0
  342. data/app/assets/javascripts/extjs-rails/src/grid/column/Boolean.js +82 -0
  343. data/app/assets/javascripts/extjs-rails/src/grid/column/Column.js +835 -0
  344. data/app/assets/javascripts/extjs-rails/src/grid/column/Date.js +63 -0
  345. data/app/assets/javascripts/extjs-rails/src/grid/column/Number.js +52 -0
  346. data/app/assets/javascripts/extjs-rails/src/grid/column/Template.js +58 -0
  347. data/app/assets/javascripts/extjs-rails/src/grid/feature/AbstractSummary.js +154 -0
  348. data/app/assets/javascripts/extjs-rails/src/grid/feature/Chunking.js +77 -0
  349. data/app/assets/javascripts/extjs-rails/src/grid/feature/Feature.js +158 -0
  350. data/app/assets/javascripts/extjs-rails/src/grid/feature/Grouping.js +822 -0
  351. data/app/assets/javascripts/extjs-rails/src/grid/feature/GroupingSummary.js +243 -0
  352. data/app/assets/javascripts/extjs-rails/src/grid/feature/RowBody.js +116 -0
  353. data/app/assets/javascripts/extjs-rails/src/grid/feature/RowWrap.js +120 -0
  354. data/app/assets/javascripts/extjs-rails/src/grid/feature/Summary.js +167 -0
  355. data/app/assets/javascripts/extjs-rails/src/grid/header/Container.js +965 -0
  356. data/app/assets/javascripts/extjs-rails/src/grid/header/DragZone.js +69 -0
  357. data/app/assets/javascripts/extjs-rails/src/grid/header/DropZone.js +265 -0
  358. data/app/assets/javascripts/extjs-rails/src/grid/plugin/CellEditing.js +453 -0
  359. data/app/assets/javascripts/extjs-rails/src/grid/plugin/DragDrop.js +254 -0
  360. data/app/assets/javascripts/extjs-rails/src/grid/plugin/Editing.js +561 -0
  361. data/app/assets/javascripts/extjs-rails/src/grid/plugin/HeaderReorderer.js +49 -0
  362. data/app/assets/javascripts/extjs-rails/src/grid/plugin/HeaderResizer.js +292 -0
  363. data/app/assets/javascripts/extjs-rails/src/grid/plugin/RowEditing.js +339 -0
  364. data/app/assets/javascripts/extjs-rails/src/grid/property/Grid.js +351 -0
  365. data/app/assets/javascripts/extjs-rails/src/grid/property/HeaderContainer.js +109 -0
  366. data/app/assets/javascripts/extjs-rails/src/grid/property/Property.js +36 -0
  367. data/app/assets/javascripts/extjs-rails/src/grid/property/Store.js +141 -0
  368. data/app/assets/javascripts/extjs-rails/src/layout/ClassList.js +90 -0
  369. data/app/assets/javascripts/extjs-rails/src/layout/Context.js +1232 -0
  370. data/app/assets/javascripts/extjs-rails/src/layout/ContextItem.js +1470 -0
  371. data/app/assets/javascripts/extjs-rails/src/layout/Layout.js +761 -0
  372. data/app/assets/javascripts/extjs-rails/src/layout/component/Auto.js +220 -0
  373. data/app/assets/javascripts/extjs-rails/src/layout/component/Body.js +80 -0
  374. data/app/assets/javascripts/extjs-rails/src/layout/component/BoundList.js +95 -0
  375. data/app/assets/javascripts/extjs-rails/src/layout/component/Button.js +261 -0
  376. data/app/assets/javascripts/extjs-rails/src/layout/component/Component.js +427 -0
  377. data/app/assets/javascripts/extjs-rails/src/layout/component/Dock.js +1132 -0
  378. data/app/assets/javascripts/extjs-rails/src/layout/component/Draw.js +79 -0
  379. data/app/assets/javascripts/extjs-rails/src/layout/component/FieldSet.js +62 -0
  380. data/app/assets/javascripts/extjs-rails/src/layout/component/ProgressBar.js +54 -0
  381. data/app/assets/javascripts/extjs-rails/src/layout/component/Tab.js +23 -0
  382. data/app/assets/javascripts/extjs-rails/src/layout/component/field/ComboBox.js +52 -0
  383. data/app/assets/javascripts/extjs-rails/src/layout/component/field/Field.js +372 -0
  384. data/app/assets/javascripts/extjs-rails/src/layout/component/field/FieldContainer.js +48 -0
  385. data/app/assets/javascripts/extjs-rails/src/layout/component/field/HtmlEditor.js +54 -0
  386. data/app/assets/javascripts/extjs-rails/src/layout/component/field/Slider.js +58 -0
  387. data/app/assets/javascripts/extjs-rails/src/layout/component/field/Text.js +75 -0
  388. data/app/assets/javascripts/extjs-rails/src/layout/component/field/TextArea.js +51 -0
  389. data/app/assets/javascripts/extjs-rails/src/layout/component/field/Trigger.js +132 -0
  390. data/app/assets/javascripts/extjs-rails/src/layout/container/Absolute.js +121 -0
  391. data/app/assets/javascripts/extjs-rails/src/layout/container/Accordion.js +308 -0
  392. data/app/assets/javascripts/extjs-rails/src/layout/container/Anchor.js +403 -0
  393. data/app/assets/javascripts/extjs-rails/src/layout/container/Auto.js +70 -0
  394. data/app/assets/javascripts/extjs-rails/src/layout/container/Border-old-js +1079 -0
  395. data/app/assets/javascripts/extjs-rails/src/layout/container/Border.js +816 -0
  396. data/app/assets/javascripts/extjs-rails/src/layout/container/Box.js +929 -0
  397. data/app/assets/javascripts/extjs-rails/src/layout/container/Card.js +361 -0
  398. data/app/assets/javascripts/extjs-rails/src/layout/container/CheckboxGroup.js +376 -0
  399. data/app/assets/javascripts/extjs-rails/src/layout/container/Column.js +234 -0
  400. data/app/assets/javascripts/extjs-rails/src/layout/container/Container.js +961 -0
  401. data/app/assets/javascripts/extjs-rails/src/layout/container/Editor.js +74 -0
  402. data/app/assets/javascripts/extjs-rails/src/layout/container/Fit.js +287 -0
  403. data/app/assets/javascripts/extjs-rails/src/layout/container/Form.js +157 -0
  404. data/app/assets/javascripts/extjs-rails/src/layout/container/HBox.js +134 -0
  405. data/app/assets/javascripts/extjs-rails/src/layout/container/Table.js +412 -0
  406. data/app/assets/javascripts/extjs-rails/src/layout/container/VBox.js +139 -0
  407. data/app/assets/javascripts/extjs-rails/src/layout/container/boxOverflow/Menu.js +365 -0
  408. data/app/assets/javascripts/extjs-rails/src/layout/container/boxOverflow/None.js +83 -0
  409. data/app/assets/javascripts/extjs-rails/src/layout/container/boxOverflow/Scroller.js +475 -0
  410. data/app/assets/javascripts/extjs-rails/src/menu/CheckItem.js +169 -0
  411. data/app/assets/javascripts/extjs-rails/src/menu/ColorPicker.js +110 -0
  412. data/app/assets/javascripts/extjs-rails/src/menu/DatePicker.js +100 -0
  413. data/app/assets/javascripts/extjs-rails/src/menu/Item.js +553 -0
  414. data/app/assets/javascripts/extjs-rails/src/menu/KeyNav.js +134 -0
  415. data/app/assets/javascripts/extjs-rails/src/menu/Manager.js +219 -0
  416. data/app/assets/javascripts/extjs-rails/src/menu/Menu.js +579 -0
  417. data/app/assets/javascripts/extjs-rails/src/menu/Separator.js +126 -0
  418. data/app/assets/javascripts/extjs-rails/src/panel/AbstractPanel.js +323 -0
  419. data/app/assets/javascripts/extjs-rails/src/panel/DD.js +99 -0
  420. data/app/assets/javascripts/extjs-rails/src/panel/Header.js +518 -0
  421. data/app/assets/javascripts/extjs-rails/src/panel/Panel.js +2150 -0
  422. data/app/assets/javascripts/extjs-rails/src/panel/Proxy.js +131 -0
  423. data/app/assets/javascripts/extjs-rails/src/panel/Table.js +1018 -0
  424. data/app/assets/javascripts/extjs-rails/src/panel/Tool.js +304 -0
  425. data/app/assets/javascripts/extjs-rails/src/picker/Color.js +219 -0
  426. data/app/assets/javascripts/extjs-rails/src/picker/Date.js +1140 -0
  427. data/app/assets/javascripts/extjs-rails/src/picker/Month.js +490 -0
  428. data/app/assets/javascripts/extjs-rails/src/picker/Time.js +165 -0
  429. data/app/assets/javascripts/extjs-rails/src/resizer/BorderSplitter.js +22 -0
  430. data/app/assets/javascripts/extjs-rails/src/resizer/BorderSplitterTracker.js +210 -0
  431. data/app/assets/javascripts/extjs-rails/src/resizer/Handle.js +29 -0
  432. data/app/assets/javascripts/extjs-rails/src/resizer/ResizeTracker.js +346 -0
  433. data/app/assets/javascripts/extjs-rails/src/resizer/Resizer.js +477 -0
  434. data/app/assets/javascripts/extjs-rails/src/resizer/Splitter.js +242 -0
  435. data/app/assets/javascripts/extjs-rails/src/resizer/SplitterTracker.js +230 -0
  436. data/app/assets/javascripts/extjs-rails/src/selection/CellModel.js +395 -0
  437. data/app/assets/javascripts/extjs-rails/src/selection/CheckboxModel.js +234 -0
  438. data/app/assets/javascripts/extjs-rails/src/selection/DataViewModel.js +160 -0
  439. data/app/assets/javascripts/extjs-rails/src/selection/Model.js +646 -0
  440. data/app/assets/javascripts/extjs-rails/src/selection/RowModel.js +499 -0
  441. data/app/assets/javascripts/extjs-rails/src/selection/TreeModel.js +78 -0
  442. data/app/assets/javascripts/extjs-rails/src/slider/Multi.js +835 -0
  443. data/app/assets/javascripts/extjs-rails/src/slider/Single.js +56 -0
  444. data/app/assets/javascripts/extjs-rails/src/slider/Thumb.js +259 -0
  445. data/app/assets/javascripts/extjs-rails/src/slider/Tip.js +130 -0
  446. data/app/assets/javascripts/extjs-rails/src/state/CookieProvider.js +120 -0
  447. data/app/assets/javascripts/extjs-rails/src/state/LocalStorageProvider.js +72 -0
  448. data/app/assets/javascripts/extjs-rails/src/state/Manager.js +70 -0
  449. data/app/assets/javascripts/extjs-rails/src/state/Provider.js +182 -0
  450. data/app/assets/javascripts/extjs-rails/src/state/Stateful.js +364 -0
  451. data/app/assets/javascripts/extjs-rails/src/tab/Bar.js +258 -0
  452. data/app/assets/javascripts/extjs-rails/src/tab/Panel.js +654 -0
  453. data/app/assets/javascripts/extjs-rails/src/tab/Tab.js +358 -0
  454. data/app/assets/javascripts/extjs-rails/src/tail.js +10 -0
  455. data/app/assets/javascripts/extjs-rails/src/tip/QuickTip.js +335 -0
  456. data/app/assets/javascripts/extjs-rails/src/tip/QuickTipManager.js +239 -0
  457. data/app/assets/javascripts/extjs-rails/src/tip/Tip.js +160 -0
  458. data/app/assets/javascripts/extjs-rails/src/tip/ToolTip.js +691 -0
  459. data/app/assets/javascripts/extjs-rails/src/toolbar/Fill.js +28 -0
  460. data/app/assets/javascripts/extjs-rails/src/toolbar/Item.js +16 -0
  461. data/app/assets/javascripts/extjs-rails/src/toolbar/Paging.js +600 -0
  462. data/app/assets/javascripts/extjs-rails/src/toolbar/Separator.js +23 -0
  463. data/app/assets/javascripts/extjs-rails/src/toolbar/Spacer.js +33 -0
  464. data/app/assets/javascripts/extjs-rails/src/toolbar/TextItem.js +57 -0
  465. data/app/assets/javascripts/extjs-rails/src/toolbar/Toolbar-legacy.js +123 -0
  466. data/app/assets/javascripts/extjs-rails/src/toolbar/Toolbar.js +447 -0
  467. data/app/assets/javascripts/extjs-rails/src/tree/Column.js +90 -0
  468. data/app/assets/javascripts/extjs-rails/src/tree/Panel.js +505 -0
  469. data/app/assets/javascripts/extjs-rails/src/tree/View.js +658 -0
  470. data/app/assets/javascripts/extjs-rails/src/tree/ViewDragZone.js +49 -0
  471. data/app/assets/javascripts/extjs-rails/src/tree/ViewDropZone.js +287 -0
  472. data/app/assets/javascripts/extjs-rails/src/tree/plugin/TreeViewDragDrop.js +244 -0
  473. data/app/assets/javascripts/extjs-rails/src/util/AbstractMixedCollection.js +772 -0
  474. data/app/assets/javascripts/extjs-rails/src/util/Animate.js +426 -0
  475. data/app/assets/javascripts/extjs-rails/src/util/Bindable.js +102 -0
  476. data/app/assets/javascripts/extjs-rails/src/util/CSS.js +185 -0
  477. data/app/assets/javascripts/extjs-rails/src/util/ClickRepeater.js +238 -0
  478. data/app/assets/javascripts/extjs-rails/src/util/ComponentDragger.js +126 -0
  479. data/app/assets/javascripts/extjs-rails/src/util/Cookies.js +91 -0
  480. data/app/assets/javascripts/extjs-rails/src/util/ElementContainer.js +293 -0
  481. data/app/assets/javascripts/extjs-rails/src/util/Filter.js +159 -0
  482. data/app/assets/javascripts/extjs-rails/src/util/Floating.js +321 -0
  483. data/app/assets/javascripts/extjs-rails/src/util/Grouper.js +26 -0
  484. data/app/assets/javascripts/extjs-rails/src/util/HashMap.js +356 -0
  485. data/app/assets/javascripts/extjs-rails/src/util/History.js +285 -0
  486. data/app/assets/javascripts/extjs-rails/src/util/Inflector.js +297 -0
  487. data/app/assets/javascripts/extjs-rails/src/util/KeyMap.js +427 -0
  488. data/app/assets/javascripts/extjs-rails/src/util/KeyNav.js +239 -0
  489. data/app/assets/javascripts/extjs-rails/src/util/LruCache.js +257 -0
  490. data/app/assets/javascripts/extjs-rails/src/util/Memento.js +131 -0
  491. data/app/assets/javascripts/extjs-rails/src/util/MixedCollection.js +239 -0
  492. data/app/assets/javascripts/extjs-rails/src/util/Observable.js +1003 -0
  493. data/app/assets/javascripts/extjs-rails/src/util/Offset.js +60 -0
  494. data/app/assets/javascripts/extjs-rails/src/util/Point.js +93 -0
  495. data/app/assets/javascripts/extjs-rails/src/util/ProtoElement.js +205 -0
  496. data/app/assets/javascripts/extjs-rails/src/util/Queue.js +76 -0
  497. data/app/assets/javascripts/extjs-rails/src/util/Region.js +388 -0
  498. data/app/assets/javascripts/extjs-rails/src/util/Renderable.js +1079 -0
  499. data/app/assets/javascripts/extjs-rails/src/util/Sortable.js +248 -0
  500. data/app/assets/javascripts/extjs-rails/src/util/Sorter.js +179 -0
  501. data/app/assets/javascripts/extjs-rails/src/util/TextMetrics.js +148 -0
  502. data/app/assets/javascripts/extjs-rails/src/view/AbstractView.js +1103 -0
  503. data/app/assets/javascripts/extjs-rails/src/view/BoundList.js +207 -0
  504. data/app/assets/javascripts/extjs-rails/src/view/BoundListKeyNav.js +92 -0
  505. data/app/assets/javascripts/extjs-rails/src/view/DragZone.js +106 -0
  506. data/app/assets/javascripts/extjs-rails/src/view/DropZone.js +240 -0
  507. data/app/assets/javascripts/extjs-rails/src/view/Table.js +1229 -0
  508. data/app/assets/javascripts/extjs-rails/src/view/TableChunker.js +139 -0
  509. data/app/assets/javascripts/extjs-rails/src/view/View.js +636 -0
  510. data/app/assets/javascripts/extjs-rails/src/window/MessageBox.js +880 -0
  511. data/app/assets/javascripts/extjs-rails/src/window/Window-legacy.js +56 -0
  512. data/app/assets/javascripts/extjs-rails/src/window/Window.js +793 -0
  513. data/extjs-rails.gemspec +24 -0
  514. data/lib/extjs-rails.rb +7 -0
  515. data/lib/extjs-rails/engine.rb +7 -0
  516. data/lib/extjs-rails/version.rb +5 -0
  517. metadata +660 -0
@@ -0,0 +1,253 @@
1
+ /**
2
+ * @class Ext.data.JsonP
3
+ * @singleton
4
+ * This class is used to create JSONP requests. JSONP is a mechanism that allows for making
5
+ * requests for data cross domain. More information is available <a href="http://en.wikipedia.org/wiki/JSONP">here</a>.
6
+ */
7
+ Ext.define('Ext.data.JsonP', {
8
+
9
+ /* Begin Definitions */
10
+
11
+ singleton: true,
12
+
13
+ statics: {
14
+ requestCount: 0,
15
+ requests: {}
16
+ },
17
+
18
+ /* End Definitions */
19
+
20
+ /**
21
+ * @property timeout
22
+ * @type Number
23
+ * A default timeout for any JsonP requests. If the request has not completed in this time the
24
+ * failure callback will be fired. The timeout is in ms. Defaults to <tt>30000</tt>.
25
+ */
26
+ timeout: 30000,
27
+
28
+ /**
29
+ * @property disableCaching
30
+ * @type Boolean
31
+ * True to add a unique cache-buster param to requests. Defaults to <tt>true</tt>.
32
+ */
33
+ disableCaching: true,
34
+
35
+ /**
36
+ * @property disableCachingParam
37
+ * @type String
38
+ * Change the parameter which is sent went disabling caching through a cache buster. Defaults to <tt>'_dc'</tt>.
39
+ */
40
+ disableCachingParam: '_dc',
41
+
42
+ /**
43
+ * @property callbackKey
44
+ * @type String
45
+ * Specifies the GET parameter that will be sent to the server containing the function name to be executed when
46
+ * the request completes. Defaults to <tt>callback</tt>. Thus, a common request will be in the form of
47
+ * url?callback=Ext.data.JsonP.callback1
48
+ */
49
+ callbackKey: 'callback',
50
+
51
+ /**
52
+ * Makes a JSONP request.
53
+ * @param {Object} options An object which may contain the following properties. Note that options will
54
+ * take priority over any defaults that are specified in the class.
55
+ * <ul>
56
+ * <li><b>url</b> : String <div class="sub-desc">The URL to request.</div></li>
57
+ * <li><b>params</b> : Object (Optional)<div class="sub-desc">An object containing a series of
58
+ * key value pairs that will be sent along with the request.</div></li>
59
+ * <li><b>timeout</b> : Number (Optional) <div class="sub-desc">See {@link #timeout}</div></li>
60
+ * <li><b>callbackKey</b> : String (Optional) <div class="sub-desc">See {@link #callbackKey}</div></li>
61
+ * <li><b>callbackName</b> : String (Optional) <div class="sub-desc">The function name to use for this request.
62
+ * By default this name will be auto-generated: Ext.data.JsonP.callback1, Ext.data.JsonP.callback2, etc.
63
+ * Setting this option to "my_name" will force the function name to be Ext.data.JsonP.my_name.
64
+ * Use this if you want deterministic behavior, but be careful - the callbackName should be different
65
+ * in each JsonP request that you make.</div></li>
66
+ * <li><b>disableCaching</b> : Boolean (Optional) <div class="sub-desc">See {@link #disableCaching}</div></li>
67
+ * <li><b>disableCachingParam</b> : String (Optional) <div class="sub-desc">See {@link #disableCachingParam}</div></li>
68
+ * <li><b>success</b> : Function (Optional) <div class="sub-desc">A function to execute if the request succeeds.</div></li>
69
+ * <li><b>failure</b> : Function (Optional) <div class="sub-desc">A function to execute if the request fails.</div></li>
70
+ * <li><b>callback</b> : Function (Optional) <div class="sub-desc">A function to execute when the request
71
+ * completes, whether it is a success or failure.</div></li>
72
+ * <li><b>scope</b> : Object (Optional)<div class="sub-desc">The scope in
73
+ * which to execute the callbacks: The "this" object for the callback function. Defaults to the browser window.</div></li>
74
+ * </ul>
75
+ * @return {Object} request An object containing the request details.
76
+ */
77
+ request: function(options){
78
+ options = Ext.apply({}, options);
79
+
80
+ //<debug>
81
+ if (!options.url) {
82
+ Ext.Error.raise('A url must be specified for a JSONP request.');
83
+ }
84
+ //</debug>
85
+
86
+ var me = this,
87
+ disableCaching = Ext.isDefined(options.disableCaching) ? options.disableCaching : me.disableCaching,
88
+ cacheParam = options.disableCachingParam || me.disableCachingParam,
89
+ id = ++me.statics().requestCount,
90
+ callbackName = options.callbackName || 'callback' + id,
91
+ callbackKey = options.callbackKey || me.callbackKey,
92
+ timeout = Ext.isDefined(options.timeout) ? options.timeout : me.timeout,
93
+ params = Ext.apply({}, options.params),
94
+ url = options.url,
95
+ name = Ext.name,
96
+ request,
97
+ script;
98
+
99
+ params[callbackKey] = name + '.data.JsonP.' + callbackName;
100
+ if (disableCaching) {
101
+ params[cacheParam] = new Date().getTime();
102
+ }
103
+
104
+ script = me.createScript(url, params, options);
105
+
106
+ me.statics().requests[id] = request = {
107
+ url: url,
108
+ params: params,
109
+ script: script,
110
+ id: id,
111
+ scope: options.scope,
112
+ success: options.success,
113
+ failure: options.failure,
114
+ callback: options.callback,
115
+ callbackKey: callbackKey,
116
+ callbackName: callbackName
117
+ };
118
+
119
+ if (timeout > 0) {
120
+ request.timeout = setTimeout(Ext.bind(me.handleTimeout, me, [request]), timeout);
121
+ }
122
+
123
+ me.setupErrorHandling(request);
124
+ me[callbackName] = Ext.bind(me.handleResponse, me, [request], true);
125
+ me.loadScript(request);
126
+ return request;
127
+ },
128
+
129
+ /**
130
+ * Abort a request. If the request parameter is not specified all open requests will
131
+ * be aborted.
132
+ * @param {Object/String} request (Optional) The request to abort
133
+ */
134
+ abort: function(request){
135
+ var me = this,
136
+ requests = me.statics().requests,
137
+ key;
138
+
139
+ if (request) {
140
+ if (!request.id) {
141
+ request = requests[request];
142
+ }
143
+ me.handleAbort(request);
144
+ } else {
145
+ for (key in requests) {
146
+ if (requests.hasOwnProperty(key)) {
147
+ me.abort(requests[key]);
148
+ }
149
+ }
150
+ }
151
+ },
152
+
153
+ /**
154
+ * Sets up error handling for the script
155
+ * @private
156
+ * @param {Object} request The request
157
+ */
158
+ setupErrorHandling: function(request){
159
+ request.script.onerror = Ext.bind(this.handleError, this, [request]);
160
+ },
161
+
162
+ /**
163
+ * Handles any aborts when loading the script
164
+ * @private
165
+ * @param {Object} request The request
166
+ */
167
+ handleAbort: function(request){
168
+ request.errorType = 'abort';
169
+ this.handleResponse(null, request);
170
+ },
171
+
172
+ /**
173
+ * Handles any script errors when loading the script
174
+ * @private
175
+ * @param {Object} request The request
176
+ */
177
+ handleError: function(request){
178
+ request.errorType = 'error';
179
+ this.handleResponse(null, request);
180
+ },
181
+
182
+ /**
183
+ * Cleans up anu script handling errors
184
+ * @private
185
+ * @param {Object} request The request
186
+ */
187
+ cleanupErrorHandling: function(request){
188
+ request.script.onerror = null;
189
+ },
190
+
191
+ /**
192
+ * Handle any script timeouts
193
+ * @private
194
+ * @param {Object} request The request
195
+ */
196
+ handleTimeout: function(request){
197
+ request.errorType = 'timeout';
198
+ this.handleResponse(null, request);
199
+ },
200
+
201
+ /**
202
+ * Handle a successful response
203
+ * @private
204
+ * @param {Object} result The result from the request
205
+ * @param {Object} request The request
206
+ */
207
+ handleResponse: function(result, request){
208
+
209
+ var success = true;
210
+
211
+ if (request.timeout) {
212
+ clearTimeout(request.timeout);
213
+ }
214
+ delete this[request.callbackName];
215
+ delete this.statics().requests[request.id];
216
+ this.cleanupErrorHandling(request);
217
+ Ext.fly(request.script).remove();
218
+
219
+ if (request.errorType) {
220
+ success = false;
221
+ Ext.callback(request.failure, request.scope, [request.errorType]);
222
+ } else {
223
+ Ext.callback(request.success, request.scope, [result]);
224
+ }
225
+ Ext.callback(request.callback, request.scope, [success, result, request.errorType]);
226
+ },
227
+
228
+ /**
229
+ * Create the script tag given the specified url, params and options. The options
230
+ * parameter is passed to allow an override to access it.
231
+ * @private
232
+ * @param {String} url The url of the request
233
+ * @param {Object} params Any extra params to be sent
234
+ * @param {Object} options The object passed to {@link #request}.
235
+ */
236
+ createScript: function(url, params, options) {
237
+ var script = document.createElement('script');
238
+ script.setAttribute("src", Ext.urlAppend(url, Ext.Object.toQueryString(params)));
239
+ script.setAttribute("async", true);
240
+ script.setAttribute("type", "text/javascript");
241
+ return script;
242
+ },
243
+
244
+ /**
245
+ * Loads the script for the given request by appending it to the HEAD element. This is
246
+ * its own method so that users can override it (as well as {@link #createScript}).
247
+ * @private
248
+ * @param request The request object.
249
+ */
250
+ loadScript: function (request) {
251
+ Ext.getHead().appendChild(request.script);
252
+ }
253
+ });
@@ -0,0 +1,51 @@
1
+ /**
2
+ * @class Ext.data.JsonPStore
3
+ * @extends Ext.data.Store
4
+ * <p>Small helper class to make creating {@link Ext.data.Store}s from different domain JSON data easier.
5
+ * A JsonPStore will be automatically configured with a {@link Ext.data.reader.Json} and a {@link Ext.data.proxy.JsonP JsonPProxy}.</p>
6
+ * <p>A store configuration would be something like:<pre><code>
7
+ var store = new Ext.data.JsonPStore({
8
+ // store configs
9
+ autoDestroy: true,
10
+ storeId: 'myStore',
11
+
12
+ // proxy configs
13
+ url: 'get-images.php',
14
+
15
+ // reader configs
16
+ root: 'images',
17
+ idProperty: 'name',
18
+ fields: ['name', 'url', {name:'size', type: 'float'}, {name:'lastmod', type:'date'}]
19
+ });
20
+ * </code></pre></p>
21
+ * <p>This store is configured to consume a returned object of the form:<pre><code>
22
+ stcCallback({
23
+ images: [
24
+ {name: 'Image one', url:'/GetImage.php?id=1', size:46.5, lastmod: new Date(2007, 10, 29)},
25
+ {name: 'Image Two', url:'/GetImage.php?id=2', size:43.2, lastmod: new Date(2007, 10, 30)}
26
+ ]
27
+ })
28
+ * </code></pre>
29
+ * <p>Where stcCallback is the callback name passed in the request to the remote domain. See {@link Ext.data.proxy.JsonP JsonPProxy}
30
+ * for details of how this works.</p>
31
+ * An object literal of this form could also be used as the {@link #cfg-data} config option.</p>
32
+ * @xtype jsonpstore
33
+ */
34
+ Ext.define('Ext.data.JsonPStore', {
35
+ extend: 'Ext.data.Store',
36
+ alias : 'store.jsonp',
37
+ requires: [
38
+ 'Ext.data.proxy.JsonP',
39
+ 'Ext.data.reader.Json'
40
+ ],
41
+
42
+ constructor: function(config) {
43
+ config = Ext.apply({
44
+ proxy: {
45
+ type: 'jsonp',
46
+ reader: 'json'
47
+ }
48
+ }, config);
49
+ this.callParent([config]);
50
+ }
51
+ });
@@ -0,0 +1,60 @@
1
+ /**
2
+ * @author Ed Spencer
3
+ *
4
+ * <p>Small helper class to make creating {@link Ext.data.Store}s from JSON data easier.
5
+ * A JsonStore will be automatically configured with a {@link Ext.data.reader.Json}.</p>
6
+ *
7
+ * <p>A store configuration would be something like:</p>
8
+ *
9
+ <pre><code>
10
+ var store = new Ext.data.JsonStore({
11
+ // store configs
12
+ autoDestroy: true,
13
+ storeId: 'myStore',
14
+
15
+ proxy: {
16
+ type: 'ajax',
17
+ url: 'get-images.php',
18
+ reader: {
19
+ type: 'json',
20
+ root: 'images',
21
+ idProperty: 'name'
22
+ }
23
+ },
24
+
25
+ //alternatively, a {@link Ext.data.Model} name can be given (see {@link Ext.data.Store} for an example)
26
+ fields: ['name', 'url', {name:'size', type: 'float'}, {name:'lastmod', type:'date'}]
27
+ });
28
+ </code></pre>
29
+ *
30
+ * <p>This store is configured to consume a returned object of the form:<pre><code>
31
+ {
32
+ images: [
33
+ {name: 'Image one', url:'/GetImage.php?id=1', size:46.5, lastmod: new Date(2007, 10, 29)},
34
+ {name: 'Image Two', url:'/GetImage.php?id=2', size:43.2, lastmod: new Date(2007, 10, 30)}
35
+ ]
36
+ }
37
+ </code></pre>
38
+ *
39
+ * <p>An object literal of this form could also be used as the {@link #cfg-data} config option.</p>
40
+ */
41
+ Ext.define('Ext.data.JsonStore', {
42
+ extend: 'Ext.data.Store',
43
+ alias: 'store.json',
44
+ requires: [
45
+ 'Ext.data.proxy.Ajax',
46
+ 'Ext.data.reader.Json',
47
+ 'Ext.data.writer.Json'
48
+ ],
49
+
50
+ constructor: function(config) {
51
+ config = Ext.apply({
52
+ proxy: {
53
+ type : 'ajax',
54
+ reader: 'json',
55
+ writer: 'json'
56
+ }
57
+ }, config);
58
+ this.callParent([config]);
59
+ }
60
+ });
@@ -0,0 +1,1673 @@
1
+ /**
2
+ * @author Ed Spencer
3
+ *
4
+ * A Model represents some object that your application manages. For example, one might define a Model for Users,
5
+ * Products, Cars, or any other real-world object that we want to model in the system. Models are registered via the
6
+ * {@link Ext.ModelManager model manager}, and are used by {@link Ext.data.Store stores}, which are in turn used by many
7
+ * of the data-bound components in Ext.
8
+ *
9
+ * Models are defined as a set of fields and any arbitrary methods and properties relevant to the model. For example:
10
+ *
11
+ * Ext.define('User', {
12
+ * extend: 'Ext.data.Model',
13
+ * fields: [
14
+ * {name: 'name', type: 'string'},
15
+ * {name: 'age', type: 'int', convert: null},
16
+ * {name: 'phone', type: 'string'},
17
+ * {name: 'alive', type: 'boolean', defaultValue: true, convert: null}
18
+ * ],
19
+ *
20
+ * changeName: function() {
21
+ * var oldName = this.get('name'),
22
+ * newName = oldName + " The Barbarian";
23
+ *
24
+ * this.set('name', newName);
25
+ * }
26
+ * });
27
+ *
28
+ * The fields array is turned into a {@link Ext.util.MixedCollection MixedCollection} automatically by the {@link
29
+ * Ext.ModelManager ModelManager}, and all other functions and properties are copied to the new Model's prototype.
30
+ *
31
+ * By default, the built in numeric and boolean field types have a (@link Ext.data.Field#convert} function which coerces string
32
+ * values in raw data into the field's type. For better performance with {@link Ext.data.reader.Json Json} or {@link Ext.data.reader.Array Array}
33
+ * readers *if you are in control of the data fed into this Model*, you can null out the default convert function which will cause
34
+ * the raw property to be copied directly into the Field's value.
35
+ *
36
+ * Now we can create instances of our User model and call any model logic we defined:
37
+ *
38
+ * var user = Ext.create('User', {
39
+ * name : 'Conan',
40
+ * age : 24,
41
+ * phone: '555-555-5555'
42
+ * });
43
+ *
44
+ * user.changeName();
45
+ * user.get('name'); //returns "Conan The Barbarian"
46
+ *
47
+ * # Validations
48
+ *
49
+ * Models have built-in support for validations, which are executed against the validator functions in {@link
50
+ * Ext.data.validations} ({@link Ext.data.validations see all validation functions}). Validations are easy to add to
51
+ * models:
52
+ *
53
+ * Ext.define('User', {
54
+ * extend: 'Ext.data.Model',
55
+ * fields: [
56
+ * {name: 'name', type: 'string'},
57
+ * {name: 'age', type: 'int'},
58
+ * {name: 'phone', type: 'string'},
59
+ * {name: 'gender', type: 'string'},
60
+ * {name: 'username', type: 'string'},
61
+ * {name: 'alive', type: 'boolean', defaultValue: true}
62
+ * ],
63
+ *
64
+ * validations: [
65
+ * {type: 'presence', field: 'age'},
66
+ * {type: 'length', field: 'name', min: 2},
67
+ * {type: 'inclusion', field: 'gender', list: ['Male', 'Female']},
68
+ * {type: 'exclusion', field: 'username', list: ['Admin', 'Operator']},
69
+ * {type: 'format', field: 'username', matcher: /([a-z]+)[0-9]{2,3}/}
70
+ * ]
71
+ * });
72
+ *
73
+ * The validations can be run by simply calling the {@link #validate} function, which returns a {@link Ext.data.Errors}
74
+ * object:
75
+ *
76
+ * var instance = Ext.create('User', {
77
+ * name: 'Ed',
78
+ * gender: 'Male',
79
+ * username: 'edspencer'
80
+ * });
81
+ *
82
+ * var errors = instance.validate();
83
+ *
84
+ * # Associations
85
+ *
86
+ * Models can have associations with other Models via {@link Ext.data.association.HasOne},
87
+ * {@link Ext.data.association.BelongsTo belongsTo} and {@link Ext.data.association.HasMany hasMany} associations.
88
+ * For example, let's say we're writing a blog administration application which deals with Users, Posts and Comments.
89
+ * We can express the relationships between these models like this:
90
+ *
91
+ * Ext.define('Post', {
92
+ * extend: 'Ext.data.Model',
93
+ * fields: ['id', 'user_id'],
94
+ *
95
+ * belongsTo: 'User',
96
+ * hasMany : {model: 'Comment', name: 'comments'}
97
+ * });
98
+ *
99
+ * Ext.define('Comment', {
100
+ * extend: 'Ext.data.Model',
101
+ * fields: ['id', 'user_id', 'post_id'],
102
+ *
103
+ * belongsTo: 'Post'
104
+ * });
105
+ *
106
+ * Ext.define('User', {
107
+ * extend: 'Ext.data.Model',
108
+ * fields: ['id'],
109
+ *
110
+ * hasMany: [
111
+ * 'Post',
112
+ * {model: 'Comment', name: 'comments'}
113
+ * ]
114
+ * });
115
+ *
116
+ * See the docs for {@link Ext.data.association.HasOne}, {@link Ext.data.association.BelongsTo} and
117
+ * {@link Ext.data.association.HasMany} for details on the usage and configuration of associations.
118
+ * Note that associations can also be specified like this:
119
+ *
120
+ * Ext.define('User', {
121
+ * extend: 'Ext.data.Model',
122
+ * fields: ['id'],
123
+ *
124
+ * associations: [
125
+ * {type: 'hasMany', model: 'Post', name: 'posts'},
126
+ * {type: 'hasMany', model: 'Comment', name: 'comments'}
127
+ * ]
128
+ * });
129
+ *
130
+ * # Using a Proxy
131
+ *
132
+ * Models are great for representing types of data and relationships, but sooner or later we're going to want to load or
133
+ * save that data somewhere. All loading and saving of data is handled via a {@link Ext.data.proxy.Proxy Proxy}, which
134
+ * can be set directly on the Model:
135
+ *
136
+ * Ext.define('User', {
137
+ * extend: 'Ext.data.Model',
138
+ * fields: ['id', 'name', 'email'],
139
+ *
140
+ * proxy: {
141
+ * type: 'rest',
142
+ * url : '/users'
143
+ * }
144
+ * });
145
+ *
146
+ * Here we've set up a {@link Ext.data.proxy.Rest Rest Proxy}, which knows how to load and save data to and from a
147
+ * RESTful backend. Let's see how this works:
148
+ *
149
+ * var user = Ext.create('User', {name: 'Ed Spencer', email: 'ed@sencha.com'});
150
+ *
151
+ * user.save(); //POST /users
152
+ *
153
+ * Calling {@link #save} on the new Model instance tells the configured RestProxy that we wish to persist this Model's
154
+ * data onto our server. RestProxy figures out that this Model hasn't been saved before because it doesn't have an id,
155
+ * and performs the appropriate action - in this case issuing a POST request to the url we configured (/users). We
156
+ * configure any Proxy on any Model and always follow this API - see {@link Ext.data.proxy.Proxy} for a full list.
157
+ *
158
+ * Loading data via the Proxy is equally easy:
159
+ *
160
+ * //get a reference to the User model class
161
+ * var User = Ext.ModelManager.getModel('User');
162
+ *
163
+ * //Uses the configured RestProxy to make a GET request to /users/123
164
+ * User.load(123, {
165
+ * success: function(user) {
166
+ * console.log(user.getId()); //logs 123
167
+ * }
168
+ * });
169
+ *
170
+ * Models can also be updated and destroyed easily:
171
+ *
172
+ * //the user Model we loaded in the last snippet:
173
+ * user.set('name', 'Edward Spencer');
174
+ *
175
+ * //tells the Proxy to save the Model. In this case it will perform a PUT request to /users/123 as this Model already has an id
176
+ * user.save({
177
+ * success: function() {
178
+ * console.log('The User was updated');
179
+ * }
180
+ * });
181
+ *
182
+ * //tells the Proxy to destroy the Model. Performs a DELETE request to /users/123
183
+ * user.destroy({
184
+ * success: function() {
185
+ * console.log('The User was destroyed!');
186
+ * }
187
+ * });
188
+ *
189
+ * # Usage in Stores
190
+ *
191
+ * It is very common to want to load a set of Model instances to be displayed and manipulated in the UI. We do this by
192
+ * creating a {@link Ext.data.Store Store}:
193
+ *
194
+ * var store = Ext.create('Ext.data.Store', {
195
+ * model: 'User'
196
+ * });
197
+ *
198
+ * //uses the Proxy we set up on Model to load the Store data
199
+ * store.load();
200
+ *
201
+ * A Store is just a collection of Model instances - usually loaded from a server somewhere. Store can also maintain a
202
+ * set of added, updated and removed Model instances to be synchronized with the server via the Proxy. See the {@link
203
+ * Ext.data.Store Store docs} for more information on Stores.
204
+ *
205
+ * @constructor
206
+ * Creates new Model instance.
207
+ * @param {Object} data An object containing keys corresponding to this model's fields, and their associated values
208
+ */
209
+
210
+ Ext.define('Ext.data.Model', {
211
+ alternateClassName: 'Ext.data.Record',
212
+
213
+ mixins: {
214
+ observable: 'Ext.util.Observable'
215
+ },
216
+
217
+ requires: [
218
+ 'Ext.ModelManager',
219
+ 'Ext.data.IdGenerator',
220
+ 'Ext.data.Field',
221
+ 'Ext.data.Errors',
222
+ 'Ext.data.Operation',
223
+ 'Ext.data.validations',
224
+ 'Ext.util.MixedCollection'
225
+ ],
226
+
227
+ compareConvertFields: function(f1, f2) {
228
+ var f1SpecialConvert = f1.convert && f1.type && f1.convert !== f1.type.convert,
229
+ f2SpecialConvert = f2.convert && f2.type && f2.convert !== f2.type.convert;
230
+
231
+ if (f1SpecialConvert && !f2SpecialConvert) {
232
+ return 1;
233
+ }
234
+
235
+ if (!f1SpecialConvert && f2SpecialConvert) {
236
+ return -1;
237
+ }
238
+ return 0;
239
+ },
240
+
241
+ itemNameFn: function(item) {
242
+ return item.name;
243
+ },
244
+
245
+ onClassExtended: function(cls, data, hooks) {
246
+ var onBeforeClassCreated = hooks.onBeforeCreated;
247
+
248
+ hooks.onBeforeCreated = function(cls, data) {
249
+ var me = this,
250
+ name = Ext.getClassName(cls),
251
+ prototype = cls.prototype,
252
+ superCls = cls.prototype.superclass,
253
+
254
+ validations = data.validations || [],
255
+ fields = data.fields || [],
256
+ associations = data.associations || [],
257
+ addAssociations = function(items, type) {
258
+ var i = 0,
259
+ len,
260
+ item;
261
+
262
+ if (items) {
263
+ items = Ext.Array.from(items);
264
+
265
+ for (len = items.length; i < len; ++i) {
266
+ item = items[i];
267
+
268
+ if (!Ext.isObject(item)) {
269
+ item = {model: item};
270
+ }
271
+
272
+ item.type = type;
273
+ associations.push(item);
274
+ }
275
+ }
276
+ },
277
+ idgen = data.idgen,
278
+
279
+ fieldsMixedCollection = new Ext.util.MixedCollection(false, prototype.itemNameFn),
280
+
281
+ associationsMixedCollection = new Ext.util.MixedCollection(false, prototype.itemNameFn),
282
+
283
+ superValidations = superCls.validations,
284
+ superFields = superCls.fields,
285
+ superAssociations = superCls.associations,
286
+
287
+ association, i, ln,
288
+ dependencies = [],
289
+ idProperty = data.idProperty || cls.prototype.idProperty,
290
+
291
+ // Process each Field upon add into the collection
292
+ onFieldAddReplace = function(arg0, arg1, arg2) {
293
+ var newField,
294
+ pos;
295
+
296
+ if (fieldsMixedCollection.events.add.firing) {
297
+ // Add event signature is (position, value, key);
298
+ pos = arg0;
299
+ newField = arg1;
300
+ } else {
301
+ // Replace event signature is (key, oldValue, newValue);
302
+ newField = arg2;
303
+ pos = arg1.originalIndex;
304
+ }
305
+
306
+ // Set the originalIndex for ArrayReader to get the default mapping from in case
307
+ // compareConvertFields changes the order due to some fields having custom convert functions.
308
+ newField.originalIndex = pos;
309
+
310
+ // The field(s) which encapsulates the idProperty must never have a default value set
311
+ // if no value arrives from the server side. So override any possible prototype-provided
312
+ // defaultValue with undefined which will inhibit generation of defaulting code in Reader.buildRecordDataExtractor
313
+ if (newField.mapping === idProperty || (newField.mapping == null && newField.name === idProperty)) {
314
+ newField.defaultValue = undefined;
315
+ }
316
+ },
317
+
318
+ // Use the proxy from the class definition object if present, otherwise fall back to the inherited one, or the default
319
+ clsProxy = data.proxy || cls.prototype.proxy || cls.prototype.defaultProxyType,
320
+
321
+ // Sort upon add function to be used in case of dynamically added Fields
322
+ fieldConvertSortFn = function() {
323
+ fieldsMixedCollection.sortBy(prototype.compareConvertFields);
324
+ };
325
+
326
+ // Save modelName on class and its prototype
327
+ cls.modelName = name;
328
+ prototype.modelName = name;
329
+
330
+ // Merge the validations of the superclass and the new subclass
331
+ if (superValidations) {
332
+ validations = superValidations.concat(validations);
333
+ }
334
+
335
+ data.validations = validations;
336
+
337
+ // Merge the fields of the superclass and the new subclass
338
+ if (superFields) {
339
+ fields = superFields.items.concat(fields);
340
+ }
341
+
342
+ fieldsMixedCollection.on({
343
+ add: onFieldAddReplace,
344
+ replace: onFieldAddReplace
345
+ });
346
+
347
+ for (i = 0, ln = fields.length; i < ln; ++i) {
348
+ fieldsMixedCollection.add(new Ext.data.Field(fields[i]));
349
+ }
350
+ if (!fieldsMixedCollection.get(idProperty)) {
351
+ fieldsMixedCollection.add(new Ext.data.Field(idProperty));
352
+ }
353
+
354
+ // Ensure the Fields are on correct order: Fields with custom convert function last
355
+ fieldConvertSortFn();
356
+ fieldsMixedCollection.on({
357
+ add: fieldConvertSortFn,
358
+ replace: fieldConvertSortFn
359
+ });
360
+
361
+ data.fields = fieldsMixedCollection;
362
+
363
+ if (idgen) {
364
+ data.idgen = Ext.data.IdGenerator.get(idgen);
365
+ }
366
+
367
+ //associations can be specified in the more convenient format (e.g. not inside an 'associations' array).
368
+ //we support that here
369
+ addAssociations(data.belongsTo, 'belongsTo');
370
+ delete data.belongsTo;
371
+ addAssociations(data.hasMany, 'hasMany');
372
+ delete data.hasMany;
373
+ addAssociations(data.hasOne, 'hasOne');
374
+ delete data.hasOne;
375
+
376
+ if (superAssociations) {
377
+ associations = superAssociations.items.concat(associations);
378
+ }
379
+
380
+ for (i = 0, ln = associations.length; i < ln; ++i) {
381
+ dependencies.push('association.' + associations[i].type.toLowerCase());
382
+ }
383
+
384
+ // If we have not been supplied with a Proxy *instance*, then add the proxy type to our dependency list
385
+ if (clsProxy && !clsProxy.isProxy) {
386
+ dependencies.push('proxy.' + (typeof clsProxy === 'string' ? clsProxy : clsProxy.type));
387
+ }
388
+
389
+ Ext.require(dependencies, function() {
390
+ Ext.ModelManager.registerType(name, cls);
391
+
392
+ for (i = 0, ln = associations.length; i < ln; ++i) {
393
+ association = associations[i];
394
+
395
+ Ext.apply(association, {
396
+ ownerModel: name,
397
+ associatedModel: association.model
398
+ });
399
+
400
+ if (Ext.ModelManager.getModel(association.model) === undefined) {
401
+ Ext.ModelManager.registerDeferredAssociation(association);
402
+ } else {
403
+ associationsMixedCollection.add(Ext.data.association.Association.create(association));
404
+ }
405
+ }
406
+
407
+ data.associations = associationsMixedCollection;
408
+
409
+ // onBeforeCreated may get called *asynchronously* if any of those required classes caused
410
+ // an asynchronous script load. This would mean that the class definition object
411
+ // has not been applied to the prototype when the Model definition has returned.
412
+ // The Reader constructor does not attempt to buildExtractors if the fields MixedCollection
413
+ // has not yet been set. The cls.setProxy call triggers a build of extractor methods.
414
+ onBeforeClassCreated.call(me, cls, data, hooks);
415
+
416
+ cls.setProxy(clsProxy);
417
+
418
+ // Fire the onModelDefined template method on ModelManager
419
+ Ext.ModelManager.onModelDefined(cls);
420
+ });
421
+ };
422
+ },
423
+
424
+ inheritableStatics: {
425
+ /**
426
+ * Sets the Proxy to use for this model. Accepts any options that can be accepted by
427
+ * {@link Ext#createByAlias Ext.createByAlias}.
428
+ * @param {String/Object/Ext.data.proxy.Proxy} proxy The proxy
429
+ * @return {Ext.data.proxy.Proxy}
430
+ * @static
431
+ * @inheritable
432
+ */
433
+ setProxy: function(proxy) {
434
+ //make sure we have an Ext.data.proxy.Proxy object
435
+ if (!proxy.isProxy) {
436
+ if (typeof proxy == "string") {
437
+ proxy = {
438
+ type: proxy
439
+ };
440
+ }
441
+ proxy = Ext.createByAlias("proxy." + proxy.type, proxy);
442
+ }
443
+ proxy.setModel(this);
444
+ this.proxy = this.prototype.proxy = proxy;
445
+
446
+ return proxy;
447
+ },
448
+
449
+ /**
450
+ * Returns the configured Proxy for this Model
451
+ * @return {Ext.data.proxy.Proxy} The proxy
452
+ * @static
453
+ * @inheritable
454
+ */
455
+ getProxy: function() {
456
+ return this.proxy;
457
+ },
458
+
459
+ /**
460
+ * Apply a new set of field and/or property definitions to the existing model. This will replace any existing
461
+ * fields, including fields inherited from superclasses. Mainly for reconfiguring the
462
+ * model based on changes in meta data (called from Reader's onMetaChange method).
463
+ * @static
464
+ * @inheritable
465
+ */
466
+ setFields: function(fields, idProperty, clientIdProperty) {
467
+ var me = this,
468
+ proto = me.prototype,
469
+ prototypeFields = proto.fields,
470
+ len = fields ? fields.length : 0,
471
+ i = 0;
472
+
473
+
474
+ if (idProperty) {
475
+ proto.idProperty = idProperty;
476
+ }
477
+ if (clientIdProperty) {
478
+ proto.clientIdProperty = clientIdProperty;
479
+ }
480
+
481
+ if (prototypeFields) {
482
+ prototypeFields.clear();
483
+ }
484
+ else {
485
+ prototypeFields = me.prototype.fields = new Ext.util.MixedCollection(false, function(field) {
486
+ return field.name;
487
+ });
488
+ }
489
+
490
+ for (; i < len; i++) {
491
+ prototypeFields.add(new Ext.data.Field(fields[i]));
492
+ }
493
+ if (!prototypeFields.get(proto.idProperty)) {
494
+ prototypeFields.add(new Ext.data.Field(proto.idProperty));
495
+ }
496
+
497
+ me.fields = prototypeFields;
498
+
499
+ return prototypeFields;
500
+ },
501
+
502
+ /**
503
+ * Returns an Array of {@link Ext.data.Field Field} definitions which define this Model's structure
504
+ *
505
+ * Fields are sorted upon Model class definition. Fields with custom {@link Ext.data.Field#convert convert} functions
506
+ * are moved to *after* fields with no convert functions. This is so that convert functions which rely on existing
507
+ * field values will be able to read those field values.
508
+ *
509
+ * @return {Ext.data.Field[]} The defined Fields for this Model.
510
+ *
511
+ */
512
+ getFields: function() {
513
+ return this.prototype.fields.items;
514
+ },
515
+
516
+ /**
517
+ * Asynchronously loads a model instance by id. Sample usage:
518
+ *
519
+ * Ext.define('MyApp.User', {
520
+ * extend: 'Ext.data.Model',
521
+ * fields: [
522
+ * {name: 'id', type: 'int'},
523
+ * {name: 'name', type: 'string'}
524
+ * ]
525
+ * });
526
+ *
527
+ * MyApp.User.load(10, {
528
+ * scope: this,
529
+ * failure: function(record, operation) {
530
+ * //do something if the load failed
531
+ * },
532
+ * success: function(record, operation) {
533
+ * //do something if the load succeeded
534
+ * },
535
+ * callback: function(record, operation) {
536
+ * //do something whether the load succeeded or failed
537
+ * }
538
+ * });
539
+ *
540
+ * @param {Number/String} id The id of the model to load
541
+ * @param {Object} config (optional) config object containing success, failure and callback functions, plus
542
+ * optional scope
543
+ * @static
544
+ * @inheritable
545
+ */
546
+ load: function(id, config) {
547
+ config = Ext.apply({}, config);
548
+ config = Ext.applyIf(config, {
549
+ action: 'read',
550
+ id : id
551
+ });
552
+
553
+ var operation = new Ext.data.Operation(config),
554
+ scope = config.scope || this,
555
+ record = null,
556
+ callback;
557
+
558
+ callback = function(operation) {
559
+ if (operation.wasSuccessful()) {
560
+ record = operation.getRecords()[0];
561
+ Ext.callback(config.success, scope, [record, operation]);
562
+ } else {
563
+ Ext.callback(config.failure, scope, [record, operation]);
564
+ }
565
+ Ext.callback(config.callback, scope, [record, operation]);
566
+ };
567
+
568
+ this.proxy.read(operation, callback, this);
569
+ }
570
+ },
571
+
572
+ statics: {
573
+ PREFIX : 'ext-record',
574
+ AUTO_ID: 1,
575
+ EDIT : 'edit',
576
+ REJECT : 'reject',
577
+ COMMIT : 'commit',
578
+
579
+ /**
580
+ * Generates a sequential id. This method is typically called when a record is {@link Ext#create
581
+ * create}d and {@link #constructor no id has been specified}. The id will automatically be assigned to the
582
+ * record. The returned id takes the form: {PREFIX}-{AUTO_ID}.
583
+ *
584
+ * - **PREFIX** : String - Ext.data.Model.PREFIX (defaults to 'ext-record')
585
+ * - **AUTO_ID** : String - Ext.data.Model.AUTO_ID (defaults to 1 initially)
586
+ *
587
+ * @param {Ext.data.Model} rec The record being created. The record does not exist, it's a {@link #phantom}.
588
+ * @return {String} auto-generated string id, `"ext-record-i++"`;
589
+ * @static
590
+ */
591
+ id: function(rec) {
592
+ var id = [this.PREFIX, '-', this.AUTO_ID++].join('');
593
+ rec.phantom = true;
594
+ rec.internalId = id;
595
+ return id;
596
+ }
597
+ },
598
+
599
+ /**
600
+ * @cfg {String/Object} idgen
601
+ * The id generator to use for this model. The default id generator does not generate
602
+ * values for the {@link #idProperty}.
603
+ *
604
+ * This can be overridden at the model level to provide a custom generator for a model.
605
+ * The simplest form of this would be:
606
+ *
607
+ * Ext.define('MyApp.data.MyModel', {
608
+ * extend: 'Ext.data.Model',
609
+ * requires: ['Ext.data.SequentialIdGenerator'],
610
+ * idgen: 'sequential',
611
+ * ...
612
+ * });
613
+ *
614
+ * The above would generate {@link Ext.data.SequentialIdGenerator sequential} id's such
615
+ * as 1, 2, 3 etc..
616
+ *
617
+ * Another useful id generator is {@link Ext.data.UuidGenerator}:
618
+ *
619
+ * Ext.define('MyApp.data.MyModel', {
620
+ * extend: 'Ext.data.Model',
621
+ * requires: ['Ext.data.UuidGenerator'],
622
+ * idgen: 'uuid',
623
+ * ...
624
+ * });
625
+ *
626
+ * An id generation can also be further configured:
627
+ *
628
+ * Ext.define('MyApp.data.MyModel', {
629
+ * extend: 'Ext.data.Model',
630
+ * idgen: {
631
+ * type: 'sequential',
632
+ * seed: 1000,
633
+ * prefix: 'ID_'
634
+ * }
635
+ * });
636
+ *
637
+ * The above would generate id's such as ID_1000, ID_1001, ID_1002 etc..
638
+ *
639
+ * If multiple models share an id space, a single generator can be shared:
640
+ *
641
+ * Ext.define('MyApp.data.MyModelX', {
642
+ * extend: 'Ext.data.Model',
643
+ * idgen: {
644
+ * type: 'sequential',
645
+ * id: 'xy'
646
+ * }
647
+ * });
648
+ *
649
+ * Ext.define('MyApp.data.MyModelY', {
650
+ * extend: 'Ext.data.Model',
651
+ * idgen: {
652
+ * type: 'sequential',
653
+ * id: 'xy'
654
+ * }
655
+ * });
656
+ *
657
+ * For more complex, shared id generators, a custom generator is the best approach.
658
+ * See {@link Ext.data.IdGenerator} for details on creating custom id generators.
659
+ *
660
+ * @markdown
661
+ */
662
+ idgen: {
663
+ isGenerator: true,
664
+ type: 'default',
665
+
666
+ generate: function () {
667
+ return null;
668
+ },
669
+ getRecId: function (rec) {
670
+ return rec.modelName + '-' + rec.internalId;
671
+ }
672
+ },
673
+
674
+ /**
675
+ * @property {Boolean} editing
676
+ * Internal flag used to track whether or not the model instance is currently being edited.
677
+ * @readonly
678
+ */
679
+ editing : false,
680
+
681
+ /**
682
+ * @property {Boolean} dirty
683
+ * True if this Record has been modified.
684
+ * @readonly
685
+ */
686
+ dirty : false,
687
+
688
+ /**
689
+ * @cfg {String} persistenceProperty
690
+ * The name of the property on this Persistable object that its data is saved to. Defaults to 'data'
691
+ * (i.e: all persistable data resides in `this.data`.)
692
+ */
693
+ persistenceProperty: 'data',
694
+
695
+ evented: false,
696
+
697
+ /**
698
+ * @property {Boolean} isModel
699
+ * `true` in this class to identify an object as an instantiated Model, or subclass thereof.
700
+ */
701
+ isModel: true,
702
+
703
+ /**
704
+ * @property {Boolean} phantom
705
+ * True when the record does not yet exist in a server-side database (see {@link #setDirty}).
706
+ * Any record which has a real database pk set as its id property is NOT a phantom -- it's real.
707
+ */
708
+ phantom : false,
709
+
710
+ /**
711
+ * @cfg {String} idProperty
712
+ * The name of the field treated as this Model's unique id. Defaults to 'id'.
713
+ */
714
+ idProperty: 'id',
715
+
716
+ /**
717
+ * @cfg {String} [clientIdProperty]
718
+ * The name of a property that is used for submitting this Model's unique client-side identifier
719
+ * to the server when multiple phantom records are saved as part of the same {@link Ext.data.Operation Operation}.
720
+ * In such a case, the server response should include the client id for each record
721
+ * so that the server response data can be used to update the client-side records if necessary.
722
+ * This property cannot have the same name as any of this Model's fields.
723
+ */
724
+ clientIdProperty: null,
725
+
726
+ /**
727
+ * @cfg {String} defaultProxyType
728
+ * The string type of the default Model Proxy. Defaults to 'ajax'.
729
+ */
730
+ defaultProxyType: 'ajax',
731
+
732
+ // Fields config and property
733
+ /**
734
+ * @cfg {Object[]/String[]} fields
735
+ * The fields for this model. This is an Array of **{@link Ext.data.Field Field}** definition objects. A Field
736
+ * definition may simply be the *name* of the Field, but a Field encapsulates {@link Ext.data.Field#type data type},
737
+ * {@link Ext.data.Field#convert custom conversion} of raw data, and a {@link Ext.data.Field#mapping mapping}
738
+ * property to specify by name of index, how to extract a field's value from a raw data object, so it is best practice
739
+ * to specify a full set of {@link Ext.data.Field Field} config objects.
740
+ */
741
+ /**
742
+ * @property {Ext.util.MixedCollection} fields
743
+ * A {@link Ext.util.MixedCollection Collection} of the fields defined for this Model (including fields defined in superclasses)
744
+ *
745
+ * This is a collection of {@link Ext.data.Field} instances, each of which encapsulates information that the field was configured with.
746
+ * By default, you can specify a field as simply a String, representing the *name* of the field, but a Field encapsulates
747
+ * {@link Ext.data.Field#type data type}, {@link Ext.data.Field#convert custom conversion} of raw data, and a {@link Ext.data.Field#mapping mapping}
748
+ * property to specify by name of index, how to extract a field's value from a raw data object.
749
+ */
750
+
751
+ /**
752
+ * @cfg {Object[]} validations
753
+ * An array of {@link Ext.data.validations validations} for this model.
754
+ */
755
+
756
+ // Associations configs and properties
757
+ /**
758
+ * @cfg {Object[]} associations
759
+ * An array of {@link Ext.data.Association associations} for this model.
760
+ */
761
+ /**
762
+ * @cfg {String/Object/String[]/Object[]} hasMany
763
+ * One or more {@link Ext.data.HasManyAssociation HasMany associations} for this model.
764
+ */
765
+ /**
766
+ * @cfg {String/Object/String[]/Object[]} belongsTo
767
+ * One or more {@link Ext.data.BelongsToAssociation BelongsTo associations} for this model.
768
+ */
769
+ /**
770
+ * @cfg {String/Object/Ext.data.proxy.Proxy} proxy
771
+ * The {@link Ext.data.proxy.Proxy proxy} to use for this model.
772
+ */
773
+
774
+ /**
775
+ * @event idchanged
776
+ * Fired when this model's id changes
777
+ * @param {Ext.data.Model} this
778
+ * @param {Number/String} oldId The old id
779
+ * @param {Number/String} newId The new id
780
+ */
781
+
782
+ // id, raw and convertedData not documented intentionally, meant to be used internally.
783
+ constructor: function(data, id, raw, convertedData) {
784
+ data = data || {};
785
+
786
+ var me = this,
787
+ fields,
788
+ length,
789
+ field,
790
+ name,
791
+ value,
792
+ newId,
793
+ persistenceProperty,
794
+ i;
795
+
796
+
797
+ /**
798
+ * @property {Number/String} internalId
799
+ * An internal unique ID for each Model instance, used to identify Models that don't have an ID yet
800
+ * @private
801
+ */
802
+ me.internalId = (id || id === 0) ? id : Ext.data.Model.id(me);
803
+
804
+ /**
805
+ * @property {Object} raw The raw data used to create this model if created via a reader.
806
+ */
807
+ me.raw = raw;
808
+
809
+ if (!me.data) {
810
+ me.data = {};
811
+ }
812
+
813
+ /**
814
+ * @property {Object} modified Key: value pairs of all fields whose values have changed
815
+ */
816
+ me.modified = {};
817
+
818
+ // Deal with spelling error in previous releases
819
+ if (me.persistanceProperty) {
820
+ //<debug>
821
+ if (Ext.isDefined(Ext.global.console)) {
822
+ Ext.global.console.warn('Ext.data.Model: persistanceProperty has been deprecated. Use persistenceProperty instead.');
823
+ }
824
+ //</debug>
825
+ me.persistenceProperty = me.persistanceProperty;
826
+ }
827
+
828
+ me[me.persistenceProperty] = convertedData || {};
829
+
830
+ me.mixins.observable.constructor.call(me);
831
+
832
+ if (!convertedData) {
833
+ //add default field values if present
834
+ fields = me.fields.items;
835
+ length = fields.length;
836
+ i = 0;
837
+ persistenceProperty = me[me.persistenceProperty];
838
+
839
+ if (Ext.isArray(data)) {
840
+ for (; i < length; i++) {
841
+ field = fields[i];
842
+ name = field.name;
843
+ value = data[i];
844
+
845
+ if (value === undefined) {
846
+ value = field.defaultValue;
847
+ }
848
+ // Have to map array data so the values get assigned to the named fields
849
+ // rather than getting set as the field names with undefined values.
850
+ if (field.convert) {
851
+ value = field.convert(value, me);
852
+ }
853
+ // On instance construction, do not create data properties based on undefined input properties
854
+ if (value !== undefined) {
855
+ persistenceProperty[name] = value;
856
+ }
857
+ }
858
+
859
+ } else {
860
+ for (; i < length; i++) {
861
+ field = fields[i];
862
+ name = field.name;
863
+ value = data[name];
864
+ if (value === undefined) {
865
+ value = field.defaultValue;
866
+ }
867
+ if (field.convert) {
868
+ value = field.convert(value, me);
869
+ }
870
+ // On instance construction, do not create data properties based on undefined input properties
871
+ if (value !== undefined) {
872
+ persistenceProperty[name] = value;
873
+ }
874
+ }
875
+ }
876
+ }
877
+
878
+ /**
879
+ * @property {Ext.data.Store[]} stores
880
+ * The {@link Ext.data.Store Stores} to which this instance is bound.
881
+ */
882
+ me.stores = [];
883
+
884
+ if (me.getId()) {
885
+ me.phantom = false;
886
+ } else if (me.phantom) {
887
+ newId = me.idgen.generate();
888
+ if (newId !== null) {
889
+ me.setId(newId);
890
+ }
891
+ }
892
+
893
+ // clear any dirty/modified since we're initializing
894
+ me.dirty = false;
895
+ me.modified = {};
896
+
897
+ if (typeof me.init == 'function') {
898
+ me.init();
899
+ }
900
+
901
+ me.id = me.idgen.getRecId(me);
902
+ },
903
+
904
+ /**
905
+ * Returns the value of the given field
906
+ * @param {String} fieldName The field to fetch the value for
907
+ * @return {Object} The value
908
+ */
909
+ get: function(field) {
910
+ return this[this.persistenceProperty][field];
911
+ },
912
+
913
+ // This object is used whenever the set() method is called and given a string as the
914
+ // first argument. This approach saves memory (and GC costs) since we could be called
915
+ // a lot.
916
+ _singleProp: {},
917
+
918
+ /**
919
+ * Sets the given field to the given value, marks the instance as dirty
920
+ * @param {String/Object} fieldName The field to set, or an object containing key/value pairs
921
+ * @param {Object} newValue The value to set
922
+ * @return {String[]} The array of modified field names or null if nothing was modified.
923
+ */
924
+ set: function (fieldName, newValue) {
925
+ var me = this,
926
+ data = me[me.persistenceProperty],
927
+ fields = me.fields,
928
+ modified = me.modified,
929
+ single = (typeof fieldName == 'string'),
930
+ currentValue, field, idChanged, key, modifiedFieldNames, name, oldId,
931
+ newId, value, values;
932
+
933
+ if (single) {
934
+ values = me._singleProp;
935
+ values[fieldName] = newValue;
936
+ } else {
937
+ values = fieldName;
938
+ }
939
+
940
+ for (name in values) {
941
+ if (values.hasOwnProperty(name)) {
942
+ value = values[name];
943
+
944
+ if (fields && (field = fields.get(name)) && field.convert) {
945
+ value = field.convert(value, me);
946
+ }
947
+
948
+ currentValue = data[name];
949
+ if (me.isEqual(currentValue, value)) {
950
+ continue; // new value is the same, so no change...
951
+ }
952
+
953
+ data[name] = value;
954
+ (modifiedFieldNames || (modifiedFieldNames = [])).push(name);
955
+
956
+ if (field && field.persist) {
957
+ if (modified.hasOwnProperty(name)) {
958
+ if (me.isEqual(modified[name], value)) {
959
+ // The original value in me.modified equals the new value, so
960
+ // the field is no longer modified:
961
+ delete modified[name];
962
+
963
+ // We might have removed the last modified field, so check to
964
+ // see if there are any modified fields remaining and correct
965
+ // me.dirty:
966
+ me.dirty = false;
967
+ for (key in modified) {
968
+ if (modified.hasOwnProperty(key)){
969
+ me.dirty = true;
970
+ break;
971
+ }
972
+ }
973
+ }
974
+ } else {
975
+ me.dirty = true;
976
+ modified[name] = currentValue;
977
+ }
978
+ }
979
+
980
+ if (name == me.idProperty) {
981
+ idChanged = true;
982
+ oldId = currentValue;
983
+ newId = value;
984
+ }
985
+ }
986
+ }
987
+
988
+ if (single) {
989
+ // cleanup our reused object for next time... important to do this before
990
+ // we fire any events or call anyone else (like afterEdit)!
991
+ delete values[fieldName];
992
+ }
993
+
994
+ if (idChanged) {
995
+ me.fireEvent('idchanged', me, oldId, newId);
996
+ }
997
+
998
+ if (!me.editing && modifiedFieldNames) {
999
+ me.afterEdit(modifiedFieldNames);
1000
+ }
1001
+
1002
+ return modifiedFieldNames || null;
1003
+ },
1004
+
1005
+ /**
1006
+ * @private
1007
+ * Copies data from the passed record into this record. If the passed record is undefined, does nothing.
1008
+ *
1009
+ * If this is a phantom record (represented only in the client, with no corresponding database entry), and
1010
+ * the source record is not a phantom, then this record acquires the id of the source record.
1011
+ *
1012
+ * @param {Ext.data.Model} sourceRecord The record to copy data from.
1013
+ */
1014
+ copyFrom: function(sourceRecord) {
1015
+ if (sourceRecord) {
1016
+
1017
+ var me = this,
1018
+ fields = me.fields.items,
1019
+ fieldCount = fields.length,
1020
+ field, i = 0,
1021
+ myData = me[me.persistenceProperty],
1022
+ sourceData = sourceRecord[sourceRecord.persistenceProperty],
1023
+ value;
1024
+
1025
+ for (; i < fieldCount; i++) {
1026
+ field = fields[i];
1027
+
1028
+ // Do not use setters.
1029
+ // Copy returned values in directly from the data object.
1030
+ // Converters have already been called because new Records
1031
+ // have been created to copy from.
1032
+ // This is a direct record-to-record value copy operation.
1033
+ value = sourceData[field.name];
1034
+ if (value !== undefined) {
1035
+ myData[field.name] = value;
1036
+ }
1037
+ }
1038
+
1039
+ // If this is a phantom record being updated from a concrete record, copy the ID in.
1040
+ if (me.phantom && !sourceRecord.phantom) {
1041
+ me.setId(sourceRecord.getId());
1042
+ }
1043
+ }
1044
+ },
1045
+
1046
+ /**
1047
+ * Checks if two values are equal, taking into account certain
1048
+ * special factors, for example dates.
1049
+ * @private
1050
+ * @param {Object} a The first value
1051
+ * @param {Object} b The second value
1052
+ * @return {Boolean} True if the values are equal
1053
+ */
1054
+ isEqual: function(a, b){
1055
+ if (Ext.isDate(a) && Ext.isDate(b)) {
1056
+ return Ext.Date.isEqual(a, b);
1057
+ }
1058
+ return a === b;
1059
+ },
1060
+
1061
+ /**
1062
+ * Begins an edit. While in edit mode, no events (e.g.. the `update` event) are relayed to the containing store.
1063
+ * When an edit has begun, it must be followed by either {@link #endEdit} or {@link #cancelEdit}.
1064
+ */
1065
+ beginEdit : function(){
1066
+ var me = this;
1067
+ if (!me.editing) {
1068
+ me.editing = true;
1069
+ me.dirtySave = me.dirty;
1070
+ me.dataSave = Ext.apply({}, me[me.persistenceProperty]);
1071
+ me.modifiedSave = Ext.apply({}, me.modified);
1072
+ }
1073
+ },
1074
+
1075
+ /**
1076
+ * Cancels all changes made in the current edit operation.
1077
+ */
1078
+ cancelEdit : function(){
1079
+ var me = this;
1080
+ if (me.editing) {
1081
+ me.editing = false;
1082
+ // reset the modified state, nothing changed since the edit began
1083
+ me.modified = me.modifiedSave;
1084
+ me[me.persistenceProperty] = me.dataSave;
1085
+ me.dirty = me.dirtySave;
1086
+ delete me.modifiedSave;
1087
+ delete me.dataSave;
1088
+ delete me.dirtySave;
1089
+ }
1090
+ },
1091
+
1092
+ /**
1093
+ * Ends an edit. If any data was modified, the containing store is notified (ie, the store's `update` event will
1094
+ * fire).
1095
+ * @param {Boolean} silent True to not notify the store of the change
1096
+ * @param {String[]} modifiedFieldNames Array of field names changed during edit.
1097
+ */
1098
+ endEdit : function(silent, modifiedFieldNames){
1099
+ var me = this,
1100
+ changed;
1101
+ if (me.editing) {
1102
+ me.editing = false;
1103
+ if(!modifiedFieldNames) {
1104
+ modifiedFieldNames = me.getModifiedFieldNames();
1105
+ }
1106
+ changed = me.dirty || modifiedFieldNames.length > 0;
1107
+ delete me.modifiedSave;
1108
+ delete me.dataSave;
1109
+ delete me.dirtySave;
1110
+ if (changed && silent !== true) {
1111
+ me.afterEdit(modifiedFieldNames);
1112
+ }
1113
+ }
1114
+ },
1115
+
1116
+ /**
1117
+ * Gets the names of all the fields that were modified during an edit
1118
+ * @private
1119
+ * @return {String[]} An array of modified field names
1120
+ */
1121
+ getModifiedFieldNames: function(){
1122
+ var me = this,
1123
+ saved = me.dataSave,
1124
+ data = me[me.persistenceProperty],
1125
+ modified = [],
1126
+ key;
1127
+
1128
+ for (key in data) {
1129
+ if (data.hasOwnProperty(key)) {
1130
+ if (!me.isEqual(data[key], saved[key])) {
1131
+ modified.push(key);
1132
+ }
1133
+ }
1134
+ }
1135
+ return modified;
1136
+ },
1137
+
1138
+ /**
1139
+ * Gets a hash of only the fields that have been modified since this Model was created or commited.
1140
+ * @return {Object}
1141
+ */
1142
+ getChanges : function(){
1143
+ var modified = this.modified,
1144
+ changes = {},
1145
+ field;
1146
+
1147
+ for (field in modified) {
1148
+ if (modified.hasOwnProperty(field)){
1149
+ changes[field] = this.get(field);
1150
+ }
1151
+ }
1152
+
1153
+ return changes;
1154
+ },
1155
+
1156
+ /**
1157
+ * Returns true if the passed field name has been `{@link #modified}` since the load or last commit.
1158
+ * @param {String} fieldName {@link Ext.data.Field#name}
1159
+ * @return {Boolean}
1160
+ */
1161
+ isModified : function(fieldName) {
1162
+ return this.modified.hasOwnProperty(fieldName);
1163
+ },
1164
+
1165
+ /**
1166
+ * Marks this **Record** as `{@link #dirty}`. This method is used interally when adding `{@link #phantom}` records
1167
+ * to a {@link Ext.data.proxy.Server#writer writer enabled store}.
1168
+ *
1169
+ * Marking a record `{@link #dirty}` causes the phantom to be returned by {@link Ext.data.Store#getUpdatedRecords}
1170
+ * where it will have a create action composed for it during {@link Ext.data.Model#save model save} operations.
1171
+ */
1172
+ setDirty : function() {
1173
+ var me = this,
1174
+ fields = me.fields.items,
1175
+ fLen = fields.length,
1176
+ field, name, f;
1177
+
1178
+ me.dirty = true;
1179
+
1180
+ for (f = 0; f < fLen; f++) {
1181
+ field = fields[f];
1182
+
1183
+ if (field.persist) {
1184
+ name = field.name;
1185
+ me.modified[name] = me.get(name);
1186
+ }
1187
+ }
1188
+ },
1189
+
1190
+ //<debug>
1191
+ markDirty : function() {
1192
+ if (Ext.isDefined(Ext.global.console)) {
1193
+ Ext.global.console.warn('Ext.data.Model: markDirty has been deprecated. Use setDirty instead.');
1194
+ }
1195
+ return this.setDirty.apply(this, arguments);
1196
+ },
1197
+ //</debug>
1198
+
1199
+ /**
1200
+ * Usually called by the {@link Ext.data.Store} to which this model instance has been {@link #join joined}. Rejects
1201
+ * all changes made to the model instance since either creation, or the last commit operation. Modified fields are
1202
+ * reverted to their original values.
1203
+ *
1204
+ * Developers should subscribe to the {@link Ext.data.Store#update} event to have their code notified of reject
1205
+ * operations.
1206
+ *
1207
+ * @param {Boolean} silent (optional) True to skip notification of the owning store of the change.
1208
+ * Defaults to false.
1209
+ */
1210
+ reject : function(silent) {
1211
+ var me = this,
1212
+ modified = me.modified,
1213
+ field;
1214
+
1215
+ for (field in modified) {
1216
+ if (modified.hasOwnProperty(field)) {
1217
+ if (typeof modified[field] != "function") {
1218
+ me[me.persistenceProperty][field] = modified[field];
1219
+ }
1220
+ }
1221
+ }
1222
+
1223
+ me.dirty = false;
1224
+ me.editing = false;
1225
+ me.modified = {};
1226
+
1227
+ if (silent !== true) {
1228
+ me.afterReject();
1229
+ }
1230
+ },
1231
+
1232
+ /**
1233
+ * Usually called by the {@link Ext.data.Store} which owns the model instance. Commits all changes made to the
1234
+ * instance since either creation or the last commit operation.
1235
+ *
1236
+ * Developers should subscribe to the {@link Ext.data.Store#update} event to have their code notified of commit
1237
+ * operations.
1238
+ *
1239
+ * @param {Boolean} silent (optional) True to skip notification of the owning store of the change.
1240
+ * Defaults to false.
1241
+ */
1242
+ commit : function(silent) {
1243
+ var me = this;
1244
+
1245
+ me.phantom = me.dirty = me.editing = false;
1246
+ me.modified = {};
1247
+
1248
+ if (silent !== true) {
1249
+ me.afterCommit();
1250
+ }
1251
+ },
1252
+
1253
+ /**
1254
+ * Creates a copy (clone) of this Model instance.
1255
+ *
1256
+ * @param {String} [id] A new id, defaults to the id of the instance being copied.
1257
+ * See `{@link Ext.data.Model#id id}`. To generate a phantom instance with a new id use:
1258
+ *
1259
+ * var rec = record.copy(); // clone the record
1260
+ * Ext.data.Model.id(rec); // automatically generate a unique sequential id
1261
+ *
1262
+ * @return {Ext.data.Model}
1263
+ */
1264
+ copy : function(newId) {
1265
+ var me = this;
1266
+
1267
+ return new me.self(Ext.apply({}, me[me.persistenceProperty]), newId);
1268
+ },
1269
+
1270
+ /**
1271
+ * Sets the Proxy to use for this model. Accepts any options that can be accepted by
1272
+ * {@link Ext#createByAlias Ext.createByAlias}.
1273
+ *
1274
+ * @param {String/Object/Ext.data.proxy.Proxy} proxy The proxy
1275
+ * @return {Ext.data.proxy.Proxy}
1276
+ */
1277
+ setProxy: function(proxy) {
1278
+ //make sure we have an Ext.data.proxy.Proxy object
1279
+ if (!proxy.isProxy) {
1280
+ if (typeof proxy === "string") {
1281
+ proxy = {
1282
+ type: proxy
1283
+ };
1284
+ }
1285
+ proxy = Ext.createByAlias("proxy." + proxy.type, proxy);
1286
+ }
1287
+ proxy.setModel(this.self);
1288
+ this.proxy = proxy;
1289
+
1290
+ return proxy;
1291
+ },
1292
+
1293
+ /**
1294
+ * Returns the configured Proxy for this Model.
1295
+ * @return {Ext.data.proxy.Proxy} The proxy
1296
+ */
1297
+ getProxy: function() {
1298
+ return this.proxy;
1299
+ },
1300
+
1301
+ /**
1302
+ * Validates the current data against all of its configured {@link #validations}.
1303
+ * @return {Ext.data.Errors} The errors object
1304
+ */
1305
+ validate: function() {
1306
+ var errors = new Ext.data.Errors(),
1307
+ validations = this.validations,
1308
+ validators = Ext.data.validations,
1309
+ length, validation, field, valid, type, i;
1310
+
1311
+ if (validations) {
1312
+ length = validations.length;
1313
+
1314
+ for (i = 0; i < length; i++) {
1315
+ validation = validations[i];
1316
+ field = validation.field || validation.name;
1317
+ type = validation.type;
1318
+ valid = validators[type](validation, this.get(field));
1319
+
1320
+ if (!valid) {
1321
+ errors.add({
1322
+ field : field,
1323
+ message: validation.message || validators[type + 'Message']
1324
+ });
1325
+ }
1326
+ }
1327
+ }
1328
+
1329
+ return errors;
1330
+ },
1331
+
1332
+ /**
1333
+ * Checks if the model is valid. See {@link #validate}.
1334
+ * @return {Boolean} True if the model is valid.
1335
+ */
1336
+ isValid: function(){
1337
+ return this.validate().isValid();
1338
+ },
1339
+
1340
+ /**
1341
+ * Saves the model instance using the configured proxy.
1342
+ * @param {Object} options Options to pass to the proxy. Config object for {@link Ext.data.Operation}.
1343
+ * @return {Ext.data.Model} The Model instance
1344
+ */
1345
+ save: function(options) {
1346
+ options = Ext.apply({}, options);
1347
+
1348
+ var me = this,
1349
+ action = me.phantom ? 'create' : 'update',
1350
+ scope = options.scope || me,
1351
+ stores = me.stores,
1352
+ i = 0,
1353
+ storeCount,
1354
+ store,
1355
+ args,
1356
+ operation,
1357
+ callback;
1358
+
1359
+ Ext.apply(options, {
1360
+ records: [me],
1361
+ action : action
1362
+ });
1363
+
1364
+ operation = new Ext.data.Operation(options);
1365
+
1366
+ callback = function(operation) {
1367
+ args = [me, operation];
1368
+ if (operation.wasSuccessful()) {
1369
+ for(storeCount = stores.length; i < storeCount; i++) {
1370
+ store = stores[i];
1371
+ store.fireEvent('write', store, operation);
1372
+ store.fireEvent('datachanged', store);
1373
+ // Not firing refresh here, since it's a single record
1374
+ }
1375
+ Ext.callback(options.success, scope, args);
1376
+ } else {
1377
+ Ext.callback(options.failure, scope, args);
1378
+ }
1379
+
1380
+ Ext.callback(options.callback, scope, args);
1381
+ };
1382
+
1383
+ me.getProxy()[action](operation, callback, me);
1384
+
1385
+ return me;
1386
+ },
1387
+
1388
+ /**
1389
+ * Destroys the model using the configured proxy.
1390
+ * @param {Object} options Options to pass to the proxy. Config object for {@link Ext.data.Operation}.
1391
+ * @return {Ext.data.Model} The Model instance
1392
+ */
1393
+ destroy: function(options){
1394
+ options = Ext.apply({}, options);
1395
+
1396
+ var me = this,
1397
+ scope = options.scope || me,
1398
+ stores = me.stores,
1399
+ i = 0,
1400
+ storeCount,
1401
+ store,
1402
+ args,
1403
+ operation,
1404
+ callback;
1405
+
1406
+ Ext.apply(options, {
1407
+ records: [me],
1408
+ action : 'destroy'
1409
+ });
1410
+
1411
+ operation = new Ext.data.Operation(options);
1412
+ callback = function(operation) {
1413
+ args = [me, operation];
1414
+ if (operation.wasSuccessful()) {
1415
+ for(storeCount = stores.length; i < storeCount; i++) {
1416
+ store = stores[i];
1417
+ store.fireEvent('write', store, operation);
1418
+ store.fireEvent('datachanged', store);
1419
+ // Not firing refresh here, since it's a single record
1420
+ }
1421
+ me.clearListeners();
1422
+ Ext.callback(options.success, scope, args);
1423
+ } else {
1424
+ Ext.callback(options.failure, scope, args);
1425
+ }
1426
+ Ext.callback(options.callback, scope, args);
1427
+ };
1428
+
1429
+ me.getProxy().destroy(operation, callback, me);
1430
+ return me;
1431
+ },
1432
+
1433
+ /**
1434
+ * Returns the unique ID allocated to this model instance as defined by {@link #idProperty}.
1435
+ * @return {Number/String} The id
1436
+ */
1437
+ getId: function() {
1438
+ return this.get(this.idProperty);
1439
+ },
1440
+
1441
+ /**
1442
+ * @private
1443
+ */
1444
+ getObservableId: function() {
1445
+ return this.id;
1446
+ },
1447
+
1448
+ /**
1449
+ * Sets the model instance's id field to the given id.
1450
+ * @param {Number/String} id The new id
1451
+ */
1452
+ setId: function(id) {
1453
+ this.set(this.idProperty, id);
1454
+ this.phantom = !(id || id === 0);
1455
+ },
1456
+
1457
+ /**
1458
+ * Tells this model instance that it has been added to a store.
1459
+ * @param {Ext.data.Store} store The store to which this model has been added.
1460
+ */
1461
+ join : function(store) {
1462
+ Ext.Array.include(this.stores, store);
1463
+
1464
+ /**
1465
+ * @property {Ext.data.Store} store
1466
+ * The {@link Ext.data.Store Store} to which this instance belongs. NOTE: If this
1467
+ * instance is bound to multiple stores, this property will reference only the
1468
+ * first. To examine all the stores, use the {@link #stores} property instead.
1469
+ */
1470
+ this.store = this.stores[0]; // compat w/all releases ever
1471
+ },
1472
+
1473
+ /**
1474
+ * Tells this model instance that it has been removed from the store.
1475
+ * @param {Ext.data.Store} store The store from which this model has been removed.
1476
+ */
1477
+ unjoin: function(store) {
1478
+ Ext.Array.remove(this.stores, store);
1479
+ this.store = this.stores[0] || null; // compat w/all releases ever
1480
+ },
1481
+
1482
+ /**
1483
+ * @private
1484
+ * If this Model instance has been {@link #join joined} to a {@link Ext.data.Store store}, the store's
1485
+ * afterEdit method is called
1486
+ * @param {String[]} modifiedFieldNames Array of field names changed during edit.
1487
+ */
1488
+ afterEdit : function(modifiedFieldNames) {
1489
+ this.callStore('afterEdit', modifiedFieldNames);
1490
+ },
1491
+
1492
+ /**
1493
+ * @private
1494
+ * If this Model instance has been {@link #join joined} to a {@link Ext.data.Store store}, the store's
1495
+ * afterReject method is called
1496
+ */
1497
+ afterReject : function() {
1498
+ this.callStore("afterReject");
1499
+ },
1500
+
1501
+ /**
1502
+ * @private
1503
+ * If this Model instance has been {@link #join joined} to a {@link Ext.data.Store store}, the store's
1504
+ * afterCommit method is called
1505
+ */
1506
+ afterCommit: function() {
1507
+ this.callStore('afterCommit');
1508
+ },
1509
+
1510
+ /**
1511
+ * @private
1512
+ * Helper function used by afterEdit, afterReject and afterCommit. Calls the given method on the
1513
+ * {@link Ext.data.Store store} that this instance has {@link #join joined}, if any. The store function
1514
+ * will always be called with the model instance as its single argument. If this model is joined to
1515
+ * a Ext.data.NodeStore, then this method calls the given method on the NodeStore and the associated Ext.data.TreeStore
1516
+ * @param {String} fn The function to call on the store
1517
+ */
1518
+ callStore: function(fn) {
1519
+ var args = Ext.Array.clone(arguments),
1520
+ stores = this.stores,
1521
+ i = 0,
1522
+ len = stores.length,
1523
+ store, treeStore;
1524
+
1525
+ args[0] = this;
1526
+ for (; i < len; ++i) {
1527
+ store = stores[i];
1528
+ if (store && typeof store[fn] == "function") {
1529
+ store[fn].apply(store, args);
1530
+ }
1531
+ // if the record is bound to a NodeStore call the TreeStore's method as well
1532
+ treeStore = store.treeStore;
1533
+ if (treeStore && typeof treeStore[fn] == "function") {
1534
+ treeStore[fn].apply(treeStore, args);
1535
+ }
1536
+ }
1537
+ },
1538
+
1539
+ /**
1540
+ * Gets all values for each field in this model and returns an object
1541
+ * containing the current data.
1542
+ * @param {Boolean} includeAssociated True to also include associated data. Defaults to false.
1543
+ * @return {Object} An object hash containing all the values in this model
1544
+ */
1545
+ getData: function(includeAssociated){
1546
+ var me = this,
1547
+ fields = me.fields.items,
1548
+ fLen = fields.length,
1549
+ data = {},
1550
+ name, f;
1551
+
1552
+ for (f = 0; f < fLen; f++) {
1553
+ name = fields[f].name;
1554
+ data[name] = me.get(name);
1555
+ }
1556
+
1557
+ if (includeAssociated === true) {
1558
+ Ext.apply(data, me.getAssociatedData());
1559
+ }
1560
+ return data;
1561
+ },
1562
+
1563
+ /**
1564
+ * Gets all of the data from this Models *loaded* associations. It does this recursively - for example if we have a
1565
+ * User which hasMany Orders, and each Order hasMany OrderItems, it will return an object like this:
1566
+ *
1567
+ * {
1568
+ * orders: [
1569
+ * {
1570
+ * id: 123,
1571
+ * status: 'shipped',
1572
+ * orderItems: [
1573
+ * ...
1574
+ * ]
1575
+ * }
1576
+ * ]
1577
+ * }
1578
+ *
1579
+ * @return {Object} The nested data set for the Model's loaded associations
1580
+ */
1581
+ getAssociatedData: function(){
1582
+ return this.prepareAssociatedData({}, 1);
1583
+ },
1584
+
1585
+ /**
1586
+ * @private
1587
+ * This complex-looking method takes a given Model instance and returns an object containing all data from
1588
+ * all of that Model's *loaded* associations. See {@link #getAssociatedData}
1589
+ * @param {Object} seenKeys A hash of all the associations we've already seen
1590
+ * @param {Number} depth The current depth
1591
+ * @return {Object} The nested data set for the Model's loaded associations
1592
+ */
1593
+ prepareAssociatedData: function(seenKeys, depth) {
1594
+ /**
1595
+ * In this method we use a breadth first strategy instead of depth
1596
+ * first. The reason for doing so is that it prevents messy & difficult
1597
+ * issues when figuring out which associations we've already processed
1598
+ * & at what depths.
1599
+ */
1600
+ var me = this,
1601
+ associations = me.associations.items,
1602
+ associationCount = associations.length,
1603
+ associationData = {},
1604
+ // We keep 3 lists at the same index instead of using an array of objects.
1605
+ // The reasoning behind this is that this method gets called a lot
1606
+ // So we want to minimize the amount of objects we create for GC.
1607
+ toRead = [],
1608
+ toReadKey = [],
1609
+ toReadIndex = [],
1610
+ associatedStore, associatedRecords, associatedRecord, o, index, result, seenDepth,
1611
+ associationId, associatedRecordCount, association, i, j, type, name;
1612
+
1613
+ for (i = 0; i < associationCount; i++) {
1614
+ association = associations[i];
1615
+ associationId = association.associationId;
1616
+
1617
+ seenDepth = seenKeys[associationId];
1618
+ if (seenDepth && seenDepth !== depth) {
1619
+ continue;
1620
+ }
1621
+ seenKeys[associationId] = depth;
1622
+
1623
+ type = association.type;
1624
+ name = association.name;
1625
+ if (type == 'hasMany') {
1626
+ //this is the hasMany store filled with the associated data
1627
+ associatedStore = me[association.storeName];
1628
+
1629
+ //we will use this to contain each associated record's data
1630
+ associationData[name] = [];
1631
+
1632
+ //if it's loaded, put it into the association data
1633
+ if (associatedStore && associatedStore.getCount() > 0) {
1634
+ associatedRecords = associatedStore.data.items;
1635
+ associatedRecordCount = associatedRecords.length;
1636
+
1637
+ //now we're finally iterating over the records in the association. Get
1638
+ // all the records so we can process them
1639
+ for (j = 0; j < associatedRecordCount; j++) {
1640
+ associatedRecord = associatedRecords[j];
1641
+ associationData[name][j] = associatedRecord.getData();
1642
+ toRead.push(associatedRecord);
1643
+ toReadKey.push(name);
1644
+ toReadIndex.push(j);
1645
+ }
1646
+ }
1647
+ } else if (type == 'belongsTo' || type == 'hasOne') {
1648
+ associatedRecord = me[association.instanceName];
1649
+ // If we have a record, put it onto our list
1650
+ if (associatedRecord !== undefined) {
1651
+ associationData[name] = associatedRecord.getData();
1652
+ toRead.push(associatedRecord);
1653
+ toReadKey.push(name);
1654
+ toReadIndex.push(-1);
1655
+ }
1656
+ }
1657
+ }
1658
+
1659
+ for (i = 0, associatedRecordCount = toRead.length; i < associatedRecordCount; ++i) {
1660
+ associatedRecord = toRead[i];
1661
+ o = associationData[toReadKey[i]];
1662
+ index = toReadIndex[i];
1663
+ result = associatedRecord.prepareAssociatedData(seenKeys, depth + 1);
1664
+ if (index === -1) {
1665
+ Ext.apply(o, result);
1666
+ } else {
1667
+ Ext.apply(o[index], result);
1668
+ }
1669
+ }
1670
+
1671
+ return associationData;
1672
+ }
1673
+ });