sproutit-sproutcore 1.0.20090721145236 → 1.0.20090721145251

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 (933) hide show
  1. data/Rakefile +189 -54
  2. data/VERSION.yml +5 -0
  3. data/frameworks/sproutcore/Buildfile +64 -0
  4. data/frameworks/sproutcore/HISTORY +682 -0
  5. data/frameworks/sproutcore/README +23 -0
  6. data/frameworks/sproutcore/apps/docs/core.js +27 -0
  7. data/frameworks/sproutcore/apps/docs/english.lproj/loading.rhtml +9 -0
  8. data/frameworks/sproutcore/apps/docs/english.lproj/main_page.js +22 -0
  9. data/frameworks/sproutcore/apps/docs/english.lproj/strings.js +15 -0
  10. data/frameworks/sproutcore/apps/docs/main.js +30 -0
  11. data/frameworks/sproutcore/apps/tests/controllers/detail.js +16 -0
  12. data/frameworks/sproutcore/apps/tests/controllers/source.js +29 -0
  13. data/frameworks/sproutcore/apps/tests/controllers/target.js +26 -0
  14. data/frameworks/sproutcore/apps/tests/controllers/targets.js +86 -0
  15. data/frameworks/sproutcore/apps/tests/controllers/tests.js +33 -0
  16. data/frameworks/sproutcore/apps/tests/core.js +133 -0
  17. data/frameworks/sproutcore/apps/tests/data_source.js +96 -0
  18. data/frameworks/sproutcore/apps/tests/english.lproj/loading.rhtml +9 -0
  19. data/frameworks/sproutcore/apps/tests/english.lproj/main_page.css +39 -0
  20. data/frameworks/sproutcore/apps/tests/english.lproj/main_page.js +232 -0
  21. data/frameworks/sproutcore/apps/tests/english.lproj/strings.js +26 -0
  22. data/frameworks/sproutcore/apps/tests/fixtures/target.js +87 -0
  23. data/frameworks/sproutcore/apps/tests/fixtures/test.js +44 -0
  24. data/frameworks/sproutcore/apps/tests/main.js +28 -0
  25. data/frameworks/sproutcore/apps/tests/models/target.js +92 -0
  26. data/frameworks/sproutcore/apps/tests/models/test.js +48 -0
  27. data/frameworks/sproutcore/apps/tests/states/no_targets.js +26 -0
  28. data/frameworks/sproutcore/apps/tests/states/ready.js +56 -0
  29. data/frameworks/sproutcore/apps/tests/states/ready_detail.js +41 -0
  30. data/frameworks/sproutcore/apps/tests/states/ready_empty.js +48 -0
  31. data/frameworks/sproutcore/apps/tests/states/ready_list.js +41 -0
  32. data/frameworks/sproutcore/apps/tests/states/ready_loading.js +44 -0
  33. data/frameworks/sproutcore/apps/tests/states/ready_no_tests.js +31 -0
  34. data/frameworks/sproutcore/apps/tests/states/start.js +39 -0
  35. data/frameworks/sproutcore/apps/tests/tests/controllers/detail.js +15 -0
  36. data/frameworks/sproutcore/apps/tests/tests/controllers/source.js +15 -0
  37. data/frameworks/sproutcore/apps/tests/tests/controllers/target.js +15 -0
  38. data/frameworks/sproutcore/apps/tests/tests/controllers/targets.js +15 -0
  39. data/frameworks/sproutcore/apps/tests/tests/controllers/tests.js +15 -0
  40. data/frameworks/sproutcore/apps/tests/tests/models/target.js +15 -0
  41. data/frameworks/sproutcore/apps/tests/tests/models/test.js +15 -0
  42. data/frameworks/sproutcore/apps/tests/tests/views/offset_checkbox.js +15 -0
  43. data/frameworks/sproutcore/apps/tests/views/offset_checkbox.js +26 -0
  44. data/frameworks/sproutcore/apps/welcome/core.js +23 -0
  45. data/frameworks/sproutcore/apps/welcome/english.lproj/loading.rhtml +8 -0
  46. data/frameworks/sproutcore/apps/welcome/english.lproj/main_page.js +43 -0
  47. data/frameworks/sproutcore/apps/welcome/english.lproj/strings.js +15 -0
  48. data/frameworks/sproutcore/apps/welcome/main.js +36 -0
  49. data/frameworks/sproutcore/design/Record State Table.numbers +0 -0
  50. data/frameworks/sproutcore/frameworks/datastore/core.js +14 -0
  51. data/frameworks/sproutcore/frameworks/datastore/data_sources/cascade.js +113 -0
  52. data/frameworks/sproutcore/frameworks/datastore/data_sources/data_source.js +273 -0
  53. data/frameworks/sproutcore/frameworks/datastore/data_sources/fixtures.js +311 -0
  54. data/frameworks/sproutcore/frameworks/datastore/data_sources/fixtures_with_queries.js +238 -0
  55. data/frameworks/sproutcore/frameworks/datastore/debug/json.js +71 -0
  56. data/frameworks/sproutcore/frameworks/datastore/debug/standard_setup.js +96 -0
  57. data/frameworks/sproutcore/frameworks/datastore/fixtures/author_fixtures.js +2503 -0
  58. data/frameworks/sproutcore/frameworks/datastore/fixtures/sample.js +17 -0
  59. data/frameworks/sproutcore/frameworks/datastore/models/fetched_attribute.js +92 -0
  60. data/frameworks/sproutcore/frameworks/datastore/models/many_attribute.js +54 -0
  61. data/frameworks/sproutcore/frameworks/datastore/models/record.js +561 -0
  62. data/frameworks/sproutcore/frameworks/datastore/models/record_attribute.js +423 -0
  63. data/frameworks/sproutcore/frameworks/datastore/system/many_array.js +158 -0
  64. data/frameworks/sproutcore/frameworks/datastore/system/nested_store.js +488 -0
  65. data/frameworks/sproutcore/frameworks/datastore/system/query.js +979 -0
  66. data/frameworks/sproutcore/frameworks/datastore/system/record_array.js +287 -0
  67. data/frameworks/sproutcore/frameworks/datastore/system/store.js +2007 -0
  68. data/frameworks/sproutcore/frameworks/datastore/tests/data_sources/fixtures.js +121 -0
  69. data/frameworks/sproutcore/frameworks/datastore/tests/integration/contact_model.js +114 -0
  70. data/frameworks/sproutcore/frameworks/datastore/tests/integration/mail_model.js +91 -0
  71. data/frameworks/sproutcore/frameworks/datastore/tests/integration/test_runner_model.js +56 -0
  72. data/frameworks/sproutcore/frameworks/datastore/tests/models/many_attribute.js +94 -0
  73. data/frameworks/sproutcore/frameworks/datastore/tests/models/record/core_methods.js +30 -0
  74. data/frameworks/sproutcore/frameworks/datastore/tests/models/record/destroy.js +73 -0
  75. data/frameworks/sproutcore/frameworks/datastore/tests/models/record/normalize.js +238 -0
  76. data/frameworks/sproutcore/frameworks/datastore/tests/models/record/readAttribute.js +48 -0
  77. data/frameworks/sproutcore/frameworks/datastore/tests/models/record/refresh.js +42 -0
  78. data/frameworks/sproutcore/frameworks/datastore/tests/models/record/storeDidChangeProperties.js +138 -0
  79. data/frameworks/sproutcore/frameworks/datastore/tests/models/record/unknownProperty.js +46 -0
  80. data/frameworks/sproutcore/frameworks/datastore/tests/models/record/writeAttribute.js +71 -0
  81. data/frameworks/sproutcore/frameworks/datastore/tests/models/record_attribute.js +204 -0
  82. data/frameworks/sproutcore/frameworks/datastore/tests/system/many_array/core_methods.js +178 -0
  83. data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/chain.js +40 -0
  84. data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/commitChanges.js +117 -0
  85. data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/commitChangesFromNestedStore.js +135 -0
  86. data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/dataHashDidChange.js +110 -0
  87. data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/discardChanges.js +99 -0
  88. data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/readDataHash.js +180 -0
  89. data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/readEditableDataHash.js +126 -0
  90. data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/removeDataHash.js +163 -0
  91. data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/writeDataHash.js +166 -0
  92. data/frameworks/sproutcore/frameworks/datastore/tests/system/query/compare_records.js +126 -0
  93. data/frameworks/sproutcore/frameworks/datastore/tests/system/query/evaluation.js +165 -0
  94. data/frameworks/sproutcore/frameworks/datastore/tests/system/query/evaluation_of_records.js +82 -0
  95. data/frameworks/sproutcore/frameworks/datastore/tests/system/query/find_all.js +362 -0
  96. data/frameworks/sproutcore/frameworks/datastore/tests/system/query/parsing.js +170 -0
  97. data/frameworks/sproutcore/frameworks/datastore/tests/system/query/record_type_is.js +43 -0
  98. data/frameworks/sproutcore/frameworks/datastore/tests/system/query/registered_comparisons.js +60 -0
  99. data/frameworks/sproutcore/frameworks/datastore/tests/system/query/registered_query_extensions.js +67 -0
  100. data/frameworks/sproutcore/frameworks/datastore/tests/system/record_array/core_methods.js +164 -0
  101. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/cancelRecord.js +54 -0
  102. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/commitChangesFromNestedStore.js +126 -0
  103. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/commitRecord.js +126 -0
  104. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/core_methods.js +73 -0
  105. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/createRecord.js +72 -0
  106. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/dataHashDidChange.js +78 -0
  107. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/dataSourceCallbacks.js +249 -0
  108. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/destroyRecord.js +106 -0
  109. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/init.js +21 -0
  110. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/pushChanges.js +61 -0
  111. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/readDataHash.js +74 -0
  112. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/readEditableDataHash.js +74 -0
  113. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/recordDidChange.js +74 -0
  114. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/removeDataHash.js +144 -0
  115. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/retrieveRecord.js +137 -0
  116. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/writeDataHash.js +130 -0
  117. data/frameworks/sproutcore/frameworks/debug/core.js +61 -0
  118. data/frameworks/sproutcore/frameworks/deprecated/core.js +59 -0
  119. data/frameworks/sproutcore/frameworks/deprecated/lib/button_views.rb +330 -0
  120. data/frameworks/sproutcore/frameworks/deprecated/lib/collection_view.rb +83 -0
  121. data/frameworks/sproutcore/frameworks/deprecated/lib/core_views.rb +326 -0
  122. data/frameworks/sproutcore/frameworks/deprecated/lib/form_views.rb +253 -0
  123. data/frameworks/sproutcore/frameworks/deprecated/lib/index.rhtml +75 -0
  124. data/frameworks/sproutcore/frameworks/deprecated/lib/menu_views.rb +93 -0
  125. data/frameworks/sproutcore/frameworks/deprecated/server/rails_server.js +80 -0
  126. data/frameworks/sproutcore/frameworks/deprecated/server/rest_server.js +178 -0
  127. data/frameworks/sproutcore/frameworks/deprecated/server/server.js +673 -0
  128. data/frameworks/sproutcore/frameworks/deprecated/system/animator.js +679 -0
  129. data/frameworks/sproutcore/frameworks/deprecated/system/binding.js +36 -0
  130. data/frameworks/sproutcore/frameworks/deprecated/system/browser.js +75 -0
  131. data/frameworks/sproutcore/frameworks/deprecated/system/classic_responder.js +312 -0
  132. data/frameworks/sproutcore/frameworks/deprecated/system/event.js +58 -0
  133. data/frameworks/sproutcore/frameworks/deprecated/system/globals.js +20 -0
  134. data/frameworks/sproutcore/frameworks/deprecated/system/misc.js +58 -0
  135. data/frameworks/sproutcore/frameworks/deprecated/system/node_descriptor.js +72 -0
  136. data/frameworks/sproutcore/frameworks/deprecated/system/object.js +122 -0
  137. data/frameworks/sproutcore/frameworks/deprecated/system/path_module.js +432 -0
  138. data/frameworks/sproutcore/frameworks/deprecated/system/string.js +107 -0
  139. data/frameworks/sproutcore/frameworks/deprecated/tests/application/application.rhtml +125 -0
  140. data/frameworks/sproutcore/frameworks/deprecated/tests/views/classic_view/clippingFrame.rhtml +401 -0
  141. data/frameworks/sproutcore/frameworks/deprecated/tests/views/classic_view/frame.rhtml +357 -0
  142. data/frameworks/sproutcore/frameworks/deprecated/tests/views/classic_view/isVisibleInWindow.rhtml +147 -0
  143. data/frameworks/sproutcore/frameworks/deprecated/tests/views/collection/base.rhtml +298 -0
  144. data/frameworks/sproutcore/frameworks/deprecated/tests/views/collection/incremental_rendering.rhtml +260 -0
  145. data/frameworks/sproutcore/frameworks/deprecated/tests/views/collection/source_list_rendering.rhtml +143 -0
  146. data/frameworks/sproutcore/frameworks/deprecated/tests/views/popup_button.rhtml +128 -0
  147. data/frameworks/sproutcore/frameworks/deprecated/tests/views/text_field.rhtml +37 -0
  148. data/frameworks/sproutcore/frameworks/deprecated/views/collection.js +24 -0
  149. data/frameworks/sproutcore/frameworks/designer/coders/design.js +29 -0
  150. data/frameworks/sproutcore/frameworks/designer/coders/localization.js +27 -0
  151. data/frameworks/sproutcore/frameworks/designer/coders/object.js +347 -0
  152. data/frameworks/sproutcore/frameworks/designer/controllers/page_design.js +102 -0
  153. data/frameworks/sproutcore/frameworks/designer/css/css_rule.js +22 -0
  154. data/frameworks/sproutcore/frameworks/designer/css/css_style.js +29 -0
  155. data/frameworks/sproutcore/frameworks/designer/css/css_style_sheet.js +201 -0
  156. data/frameworks/sproutcore/frameworks/designer/ext/page.js +86 -0
  157. data/frameworks/sproutcore/frameworks/designer/ext/view.js +38 -0
  158. data/frameworks/sproutcore/frameworks/designer/views/controls/button.js +17 -0
  159. data/frameworks/sproutcore/frameworks/designer/views/designer.js +569 -0
  160. data/frameworks/sproutcore/frameworks/designer/views/label.js +16 -0
  161. data/frameworks/sproutcore/frameworks/designer/views/mixins/button.js +11 -0
  162. data/frameworks/sproutcore/frameworks/designer/views/tab.js +16 -0
  163. data/frameworks/sproutcore/frameworks/desktop/core.js +6 -0
  164. data/frameworks/sproutcore/frameworks/desktop/debug/drag.js +41 -0
  165. data/frameworks/sproutcore/frameworks/desktop/english.lproj/alert.css +56 -0
  166. data/frameworks/sproutcore/frameworks/desktop/english.lproj/debug/a_sample_image.jpg +0 -0
  167. data/frameworks/sproutcore/frameworks/desktop/english.lproj/debug/apple-logo1.jpeg +0 -0
  168. data/frameworks/sproutcore/frameworks/desktop/english.lproj/debug/iframe.html +23 -0
  169. data/frameworks/sproutcore/frameworks/desktop/english.lproj/disclosure.css +71 -0
  170. data/frameworks/sproutcore/frameworks/desktop/english.lproj/drag.css +6 -0
  171. data/frameworks/sproutcore/frameworks/desktop/english.lproj/icons.css +943 -0
  172. data/frameworks/sproutcore/frameworks/desktop/english.lproj/images/icons/mini_222222.png +0 -0
  173. data/frameworks/sproutcore/frameworks/desktop/english.lproj/images/icons/mini_454545.png +0 -0
  174. data/frameworks/sproutcore/frameworks/desktop/english.lproj/images/icons/mini_888888.png +0 -0
  175. data/frameworks/sproutcore/frameworks/desktop/english.lproj/images/icons/mini_ffffff.png +0 -0
  176. data/frameworks/sproutcore/frameworks/desktop/english.lproj/images/icons/shared.png +0 -0
  177. data/frameworks/sproutcore/frameworks/desktop/english.lproj/images/indicator.gif +0 -0
  178. data/frameworks/sproutcore/frameworks/desktop/english.lproj/images/panels/sprite-x.png +0 -0
  179. data/frameworks/sproutcore/frameworks/desktop/english.lproj/images/panels/sprite-y.png +0 -0
  180. data/frameworks/sproutcore/frameworks/desktop/english.lproj/images/sc-theme-sprite.png +0 -0
  181. data/frameworks/sproutcore/frameworks/desktop/english.lproj/images/standard_fade/000000.png +0 -0
  182. data/frameworks/sproutcore/frameworks/desktop/english.lproj/images/standard_fade/ffffff.png +0 -0
  183. data/frameworks/sproutcore/frameworks/desktop/english.lproj/images/sticky-note.png +0 -0
  184. data/frameworks/sproutcore/frameworks/desktop/english.lproj/list_item.css +209 -0
  185. data/frameworks/sproutcore/frameworks/desktop/english.lproj/menu_item_view.css +100 -0
  186. data/frameworks/sproutcore/frameworks/desktop/english.lproj/modal.css +5 -0
  187. data/frameworks/sproutcore/frameworks/desktop/english.lproj/panel.css +95 -0
  188. data/frameworks/sproutcore/frameworks/desktop/english.lproj/picker.css +39 -0
  189. data/frameworks/sproutcore/frameworks/desktop/english.lproj/progress.css +31 -0
  190. data/frameworks/sproutcore/frameworks/desktop/english.lproj/radio.css +10 -0
  191. data/frameworks/sproutcore/frameworks/desktop/english.lproj/scroller.css +26 -0
  192. data/frameworks/sproutcore/frameworks/desktop/english.lproj/segmented.css +141 -0
  193. data/frameworks/sproutcore/frameworks/desktop/english.lproj/separator.css +19 -0
  194. data/frameworks/sproutcore/frameworks/desktop/english.lproj/slider.css +62 -0
  195. data/frameworks/sproutcore/frameworks/desktop/english.lproj/split.css +70 -0
  196. data/frameworks/sproutcore/frameworks/desktop/english.lproj/split_divider.css +9 -0
  197. data/frameworks/sproutcore/frameworks/desktop/english.lproj/strings.js +14 -0
  198. data/frameworks/sproutcore/frameworks/desktop/english.lproj/tab.css +12 -0
  199. data/frameworks/sproutcore/frameworks/desktop/english.lproj/toolbar.css +6 -0
  200. data/frameworks/sproutcore/frameworks/desktop/mixins/border.js +53 -0
  201. data/frameworks/sproutcore/frameworks/desktop/mixins/collection_group.js +22 -0
  202. data/frameworks/sproutcore/frameworks/desktop/mixins/collection_row_delegate.js +61 -0
  203. data/frameworks/sproutcore/frameworks/desktop/mixins/collection_view_delegate.js +283 -0
  204. data/frameworks/sproutcore/frameworks/desktop/mixins/scrollable.js +247 -0
  205. data/frameworks/sproutcore/frameworks/desktop/panes/alert.js +408 -0
  206. data/frameworks/sproutcore/frameworks/desktop/panes/menu.js +651 -0
  207. data/frameworks/sproutcore/frameworks/desktop/panes/modal.js +68 -0
  208. data/frameworks/sproutcore/frameworks/desktop/panes/palette.js +63 -0
  209. data/frameworks/sproutcore/frameworks/desktop/panes/panel.js +184 -0
  210. data/frameworks/sproutcore/frameworks/desktop/panes/picker.js +400 -0
  211. data/frameworks/sproutcore/frameworks/desktop/panes/sheet.js +46 -0
  212. data/frameworks/sproutcore/frameworks/desktop/protocols/drag_data_source.js +39 -0
  213. data/frameworks/sproutcore/frameworks/desktop/protocols/drag_source.js +81 -0
  214. data/frameworks/sproutcore/frameworks/desktop/protocols/drop_target.js +175 -0
  215. data/frameworks/sproutcore/frameworks/desktop/protocols/responder.js +280 -0
  216. data/frameworks/sproutcore/frameworks/desktop/system/drag.js +827 -0
  217. data/frameworks/sproutcore/frameworks/desktop/system/key_bindings.js +40 -0
  218. data/frameworks/sproutcore/frameworks/desktop/system/root_responder.js +641 -0
  219. data/frameworks/sproutcore/frameworks/desktop/system/undo_manager.js +187 -0
  220. data/frameworks/sproutcore/frameworks/desktop/tests/integration/dialog.js +43 -0
  221. data/frameworks/sproutcore/frameworks/desktop/tests/panes/alert/methods.js +10 -0
  222. data/frameworks/sproutcore/frameworks/desktop/tests/panes/alert/ui.js +152 -0
  223. data/frameworks/sproutcore/frameworks/desktop/tests/panes/menu/methods.js +55 -0
  224. data/frameworks/sproutcore/frameworks/desktop/tests/panes/menu/ui.js +59 -0
  225. data/frameworks/sproutcore/frameworks/desktop/tests/panes/palette/methods.js +10 -0
  226. data/frameworks/sproutcore/frameworks/desktop/tests/panes/palette/ui.js +35 -0
  227. data/frameworks/sproutcore/frameworks/desktop/tests/panes/panel/methods.js +10 -0
  228. data/frameworks/sproutcore/frameworks/desktop/tests/panes/panel/ui.js +40 -0
  229. data/frameworks/sproutcore/frameworks/desktop/tests/panes/picker/methods.js +10 -0
  230. data/frameworks/sproutcore/frameworks/desktop/tests/panes/picker/ui.js +84 -0
  231. data/frameworks/sproutcore/frameworks/desktop/tests/panes/sheet/methods.js +10 -0
  232. data/frameworks/sproutcore/frameworks/desktop/tests/panes/sheet/ui.js +38 -0
  233. data/frameworks/sproutcore/frameworks/desktop/tests/views/button/methods.js +45 -0
  234. data/frameworks/sproutcore/frameworks/desktop/tests/views/button/ui.js +159 -0
  235. data/frameworks/sproutcore/frameworks/desktop/tests/views/checkbox/methods.js +144 -0
  236. data/frameworks/sproutcore/frameworks/desktop/tests/views/checkbox/ui.js +99 -0
  237. data/frameworks/sproutcore/frameworks/desktop/tests/views/collection/content.js +249 -0
  238. data/frameworks/sproutcore/frameworks/desktop/tests/views/collection/deleteSelection.js +82 -0
  239. data/frameworks/sproutcore/frameworks/desktop/tests/views/collection/deselect.js +199 -0
  240. data/frameworks/sproutcore/frameworks/desktop/tests/views/collection/itemViewForContentIndex.js +288 -0
  241. data/frameworks/sproutcore/frameworks/desktop/tests/views/collection/layerIdFor.js +65 -0
  242. data/frameworks/sproutcore/frameworks/desktop/tests/views/collection/length.js +88 -0
  243. data/frameworks/sproutcore/frameworks/desktop/tests/views/collection/mouse.js +165 -0
  244. data/frameworks/sproutcore/frameworks/desktop/tests/views/collection/nowShowing.js +121 -0
  245. data/frameworks/sproutcore/frameworks/desktop/tests/views/collection/reload.js +177 -0
  246. data/frameworks/sproutcore/frameworks/desktop/tests/views/collection/select.js +240 -0
  247. data/frameworks/sproutcore/frameworks/desktop/tests/views/collection/selectNextItem.js +191 -0
  248. data/frameworks/sproutcore/frameworks/desktop/tests/views/collection/selectPreviousItem.js +197 -0
  249. data/frameworks/sproutcore/frameworks/desktop/tests/views/collection/selection.js +141 -0
  250. data/frameworks/sproutcore/frameworks/desktop/tests/views/collection/ui_diagram.js +182 -0
  251. data/frameworks/sproutcore/frameworks/desktop/tests/views/disclosure/methods.js +10 -0
  252. data/frameworks/sproutcore/frameworks/desktop/tests/views/disclosure/ui.js +64 -0
  253. data/frameworks/sproutcore/frameworks/desktop/tests/views/grid/methods.js +10 -0
  254. data/frameworks/sproutcore/frameworks/desktop/tests/views/grid/ui.js +10 -0
  255. data/frameworks/sproutcore/frameworks/desktop/tests/views/list/rowDelegate.js +183 -0
  256. data/frameworks/sproutcore/frameworks/desktop/tests/views/list/rowHeightForContentIndex.js +133 -0
  257. data/frameworks/sproutcore/frameworks/desktop/tests/views/list/rowOffsetForContentIndex.js +132 -0
  258. data/frameworks/sproutcore/frameworks/desktop/tests/views/list/ui_outline.js +56 -0
  259. data/frameworks/sproutcore/frameworks/desktop/tests/views/list/ui_row_heights.js +167 -0
  260. data/frameworks/sproutcore/frameworks/desktop/tests/views/list/ui_simple.js +127 -0
  261. data/frameworks/sproutcore/frameworks/desktop/tests/views/list_item.js +284 -0
  262. data/frameworks/sproutcore/frameworks/desktop/tests/views/menu_item/methods.js +10 -0
  263. data/frameworks/sproutcore/frameworks/desktop/tests/views/menu_item/ui.js +44 -0
  264. data/frameworks/sproutcore/frameworks/desktop/tests/views/progress/methods.js +128 -0
  265. data/frameworks/sproutcore/frameworks/desktop/tests/views/progress/ui.js +240 -0
  266. data/frameworks/sproutcore/frameworks/desktop/tests/views/radio/methods.js +113 -0
  267. data/frameworks/sproutcore/frameworks/desktop/tests/views/radio/ui.js +202 -0
  268. data/frameworks/sproutcore/frameworks/desktop/tests/views/scroll/methods.js +139 -0
  269. data/frameworks/sproutcore/frameworks/desktop/tests/views/scroll/ui.js +111 -0
  270. data/frameworks/sproutcore/frameworks/desktop/tests/views/scroller/methods.js +102 -0
  271. data/frameworks/sproutcore/frameworks/desktop/tests/views/scroller/ui.js +70 -0
  272. data/frameworks/sproutcore/frameworks/desktop/tests/views/segmented/methods.js +95 -0
  273. data/frameworks/sproutcore/frameworks/desktop/tests/views/segmented/ui.js +222 -0
  274. data/frameworks/sproutcore/frameworks/desktop/tests/views/select_field/methods.js +81 -0
  275. data/frameworks/sproutcore/frameworks/desktop/tests/views/select_field/ui.js +100 -0
  276. data/frameworks/sproutcore/frameworks/desktop/tests/views/separator.js +37 -0
  277. data/frameworks/sproutcore/frameworks/desktop/tests/views/source_list/methods.js +10 -0
  278. data/frameworks/sproutcore/frameworks/desktop/tests/views/source_list/ui.js +10 -0
  279. data/frameworks/sproutcore/frameworks/desktop/tests/views/split/methods.js +50 -0
  280. data/frameworks/sproutcore/frameworks/desktop/tests/views/split/ui.js +52 -0
  281. data/frameworks/sproutcore/frameworks/desktop/tests/views/stacked/ui_comments.js +231 -0
  282. data/frameworks/sproutcore/frameworks/desktop/tests/views/tab/methods.js +54 -0
  283. data/frameworks/sproutcore/frameworks/desktop/tests/views/tab/ui.js +88 -0
  284. data/frameworks/sproutcore/frameworks/desktop/tests/views/web/methods.js +10 -0
  285. data/frameworks/sproutcore/frameworks/desktop/tests/views/web/ui.js +110 -0
  286. data/frameworks/sproutcore/frameworks/desktop/views/button.js +331 -0
  287. data/frameworks/sproutcore/frameworks/desktop/views/checkbox.js +105 -0
  288. data/frameworks/sproutcore/frameworks/desktop/views/collection.js +2757 -0
  289. data/frameworks/sproutcore/frameworks/desktop/views/disclosure.js +44 -0
  290. data/frameworks/sproutcore/frameworks/desktop/views/form.js +594 -0
  291. data/frameworks/sproutcore/frameworks/desktop/views/grid.js +201 -0
  292. data/frameworks/sproutcore/frameworks/desktop/views/list.js +540 -0
  293. data/frameworks/sproutcore/frameworks/desktop/views/list_item.js +660 -0
  294. data/frameworks/sproutcore/frameworks/desktop/views/menu_item.js +587 -0
  295. data/frameworks/sproutcore/frameworks/desktop/views/popup_button.js +68 -0
  296. data/frameworks/sproutcore/frameworks/desktop/views/progress.js +207 -0
  297. data/frameworks/sproutcore/frameworks/desktop/views/radio.js +332 -0
  298. data/frameworks/sproutcore/frameworks/desktop/views/scene.js +204 -0
  299. data/frameworks/sproutcore/frameworks/desktop/views/scroll.js +690 -0
  300. data/frameworks/sproutcore/frameworks/desktop/views/scroller.js +226 -0
  301. data/frameworks/sproutcore/frameworks/desktop/views/segmented.js +525 -0
  302. data/frameworks/sproutcore/frameworks/desktop/views/select_field.js +331 -0
  303. data/frameworks/sproutcore/frameworks/desktop/views/separator.js +37 -0
  304. data/frameworks/sproutcore/frameworks/desktop/views/slider.js +180 -0
  305. data/frameworks/sproutcore/frameworks/desktop/views/source_list.js +47 -0
  306. data/frameworks/sproutcore/frameworks/desktop/views/source_list_group.js +169 -0
  307. data/frameworks/sproutcore/frameworks/desktop/views/split.js +677 -0
  308. data/frameworks/sproutcore/frameworks/desktop/views/split_divider.js +55 -0
  309. data/frameworks/sproutcore/frameworks/desktop/views/stacked.js +101 -0
  310. data/frameworks/sproutcore/frameworks/desktop/views/tab.js +191 -0
  311. data/frameworks/sproutcore/frameworks/desktop/views/thumb.js +49 -0
  312. data/frameworks/sproutcore/frameworks/desktop/views/toolbar.js +49 -0
  313. data/frameworks/sproutcore/frameworks/desktop/views/web.js +86 -0
  314. data/frameworks/sproutcore/frameworks/foundation/TESTING +46 -0
  315. data/frameworks/sproutcore/frameworks/foundation/controllers/array.js +509 -0
  316. data/frameworks/sproutcore/frameworks/foundation/controllers/controller.js +45 -0
  317. data/frameworks/sproutcore/frameworks/foundation/controllers/object.js +323 -0
  318. data/frameworks/sproutcore/frameworks/foundation/controllers/tree.js +109 -0
  319. data/frameworks/sproutcore/frameworks/foundation/core.js +136 -0
  320. data/frameworks/sproutcore/frameworks/foundation/debug/control_test_pane.js +194 -0
  321. data/frameworks/sproutcore/frameworks/foundation/english.lproj/blank.gif +0 -0
  322. data/frameworks/sproutcore/frameworks/foundation/english.lproj/bootstrap.rhtml +68 -0
  323. data/frameworks/sproutcore/frameworks/foundation/english.lproj/button_view.css +55 -0
  324. data/frameworks/sproutcore/frameworks/foundation/english.lproj/core.css +221 -0
  325. data/frameworks/sproutcore/frameworks/foundation/english.lproj/debug/control-test-pane.css +9 -0
  326. data/frameworks/sproutcore/frameworks/foundation/english.lproj/images/sproutcore-logo.png +0 -0
  327. data/frameworks/sproutcore/frameworks/foundation/english.lproj/label.css +30 -0
  328. data/frameworks/sproutcore/frameworks/foundation/english.lproj/static_layout.css +5 -0
  329. data/frameworks/sproutcore/frameworks/foundation/english.lproj/strings.js +15 -0
  330. data/frameworks/sproutcore/frameworks/foundation/english.lproj/text_field.css +45 -0
  331. data/frameworks/sproutcore/frameworks/foundation/english.lproj/view.css +45 -0
  332. data/frameworks/sproutcore/frameworks/foundation/ext/object.js +81 -0
  333. data/frameworks/sproutcore/frameworks/foundation/ext/run_loop.js +158 -0
  334. data/frameworks/sproutcore/frameworks/foundation/fixtures/file_exists.json +1 -0
  335. data/frameworks/sproutcore/frameworks/foundation/license.js +19 -0
  336. data/frameworks/sproutcore/frameworks/foundation/mixins/button.js +299 -0
  337. data/frameworks/sproutcore/frameworks/foundation/mixins/collection_content.js +171 -0
  338. data/frameworks/sproutcore/frameworks/foundation/mixins/content_display.js +88 -0
  339. data/frameworks/sproutcore/frameworks/foundation/mixins/control.js +352 -0
  340. data/frameworks/sproutcore/frameworks/foundation/mixins/editable.js +146 -0
  341. data/frameworks/sproutcore/frameworks/foundation/mixins/inline_text_field.js +462 -0
  342. data/frameworks/sproutcore/frameworks/foundation/mixins/selection_support.js +232 -0
  343. data/frameworks/sproutcore/frameworks/foundation/mixins/static_layout.js +132 -0
  344. data/frameworks/sproutcore/frameworks/foundation/mixins/string.js +251 -0
  345. data/frameworks/sproutcore/frameworks/foundation/mixins/tree_item_content.js +159 -0
  346. data/frameworks/sproutcore/frameworks/foundation/mixins/validatable.js +176 -0
  347. data/frameworks/sproutcore/frameworks/foundation/panes/main.js +47 -0
  348. data/frameworks/sproutcore/frameworks/foundation/panes/pane.js +584 -0
  349. data/frameworks/sproutcore/frameworks/foundation/private/tree_item_observer.js +887 -0
  350. data/frameworks/sproutcore/frameworks/foundation/protocols/inline_editor_delegate.js +84 -0
  351. data/frameworks/sproutcore/frameworks/foundation/system/application.js +36 -0
  352. data/frameworks/sproutcore/frameworks/foundation/system/benchmark.js +492 -0
  353. data/frameworks/sproutcore/frameworks/foundation/system/browser.js +64 -0
  354. data/frameworks/sproutcore/frameworks/foundation/system/builder.js +210 -0
  355. data/frameworks/sproutcore/frameworks/foundation/system/core_query.js +2015 -0
  356. data/frameworks/sproutcore/frameworks/foundation/system/cursor.js +129 -0
  357. data/frameworks/sproutcore/frameworks/foundation/system/datetime.js +729 -0
  358. data/frameworks/sproutcore/frameworks/foundation/system/error.js +93 -0
  359. data/frameworks/sproutcore/frameworks/foundation/system/event.js +853 -0
  360. data/frameworks/sproutcore/frameworks/foundation/system/image_cache.js +433 -0
  361. data/frameworks/sproutcore/frameworks/foundation/system/json.js +440 -0
  362. data/frameworks/sproutcore/frameworks/foundation/system/locale.js +288 -0
  363. data/frameworks/sproutcore/frameworks/foundation/system/page.js +106 -0
  364. data/frameworks/sproutcore/frameworks/foundation/system/ready.js +195 -0
  365. data/frameworks/sproutcore/frameworks/foundation/system/render_context.js +904 -0
  366. data/frameworks/sproutcore/frameworks/foundation/system/request.js +380 -0
  367. data/frameworks/sproutcore/frameworks/foundation/system/responder.js +120 -0
  368. data/frameworks/sproutcore/frameworks/foundation/system/responder_context.js +243 -0
  369. data/frameworks/sproutcore/frameworks/foundation/system/root_responder.js +391 -0
  370. data/frameworks/sproutcore/frameworks/foundation/system/routes.js +487 -0
  371. data/frameworks/sproutcore/frameworks/foundation/system/time.js +478 -0
  372. data/frameworks/sproutcore/frameworks/foundation/system/timer.js +549 -0
  373. data/frameworks/sproutcore/frameworks/foundation/system/user_defaults.js +165 -0
  374. data/frameworks/sproutcore/frameworks/foundation/system/utils.js +425 -0
  375. data/frameworks/sproutcore/frameworks/foundation/tests/controllers/array/array_case.js +182 -0
  376. data/frameworks/sproutcore/frameworks/foundation/tests/controllers/array/enum_case.js +193 -0
  377. data/frameworks/sproutcore/frameworks/foundation/tests/controllers/array/null_case.js +64 -0
  378. data/frameworks/sproutcore/frameworks/foundation/tests/controllers/array/single_case.js +136 -0
  379. data/frameworks/sproutcore/frameworks/foundation/tests/controllers/object/empty_case.js +82 -0
  380. data/frameworks/sproutcore/frameworks/foundation/tests/controllers/object/multiple_case.js +111 -0
  381. data/frameworks/sproutcore/frameworks/foundation/tests/controllers/object/single_case.js +193 -0
  382. data/frameworks/sproutcore/frameworks/foundation/tests/controllers/object/single_enumerable_case.js +179 -0
  383. data/frameworks/sproutcore/frameworks/foundation/tests/controllers/tree/outline_case.js +108 -0
  384. data/frameworks/sproutcore/frameworks/foundation/tests/debug/control_test_pane/methods.js +10 -0
  385. data/frameworks/sproutcore/frameworks/foundation/tests/debug/control_test_pane/ui.js +113 -0
  386. data/frameworks/sproutcore/frameworks/foundation/tests/integration/creating_views.js +113 -0
  387. data/frameworks/sproutcore/frameworks/foundation/tests/mixins/button/content.js +195 -0
  388. data/frameworks/sproutcore/frameworks/foundation/tests/mixins/button/displayProperties.js +89 -0
  389. data/frameworks/sproutcore/frameworks/foundation/tests/mixins/button/keyEquivalents.js +35 -0
  390. data/frameworks/sproutcore/frameworks/foundation/tests/mixins/control/content.js +168 -0
  391. data/frameworks/sproutcore/frameworks/foundation/tests/mixins/control/displayProperties.js +89 -0
  392. data/frameworks/sproutcore/frameworks/foundation/tests/mixins/staticLayout.js +128 -0
  393. data/frameworks/sproutcore/frameworks/foundation/tests/mixins/string.js +17 -0
  394. data/frameworks/sproutcore/frameworks/foundation/tests/private/tree_item_observer/flat_case.js +325 -0
  395. data/frameworks/sproutcore/frameworks/foundation/tests/private/tree_item_observer/group_case.js +718 -0
  396. data/frameworks/sproutcore/frameworks/foundation/tests/private/tree_item_observer/outline_case.js +484 -0
  397. data/frameworks/sproutcore/frameworks/foundation/tests/system/builder.js +42 -0
  398. data/frameworks/sproutcore/frameworks/foundation/tests/system/core_query/jquery_core.js +1323 -0
  399. data/frameworks/sproutcore/frameworks/foundation/tests/system/core_query/jquery_dimensions.js +387 -0
  400. data/frameworks/sproutcore/frameworks/foundation/tests/system/core_query/jquery_selector.js +405 -0
  401. data/frameworks/sproutcore/frameworks/foundation/tests/system/core_query/setClass.js +49 -0
  402. data/frameworks/sproutcore/frameworks/foundation/tests/system/core_query/within.js +66 -0
  403. data/frameworks/sproutcore/frameworks/foundation/tests/system/datetime.js +151 -0
  404. data/frameworks/sproutcore/frameworks/foundation/tests/system/error.js +41 -0
  405. data/frameworks/sproutcore/frameworks/foundation/tests/system/json.js +14 -0
  406. data/frameworks/sproutcore/frameworks/foundation/tests/system/locale.js +128 -0
  407. data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/begin.js +47 -0
  408. data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/element.js +44 -0
  409. data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/end.js +119 -0
  410. data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/get.js +51 -0
  411. data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/helpers_attr.js +50 -0
  412. data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/helpers_basic.js +28 -0
  413. data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/helpers_className.js +179 -0
  414. data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/helpers_style.js +100 -0
  415. data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/init.js +55 -0
  416. data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/join.js +28 -0
  417. data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/push_text.js +74 -0
  418. data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/tag.js +45 -0
  419. data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/update.js +205 -0
  420. data/frameworks/sproutcore/frameworks/foundation/tests/system/request.js +127 -0
  421. data/frameworks/sproutcore/frameworks/foundation/tests/system/root_responder/makeKeyPane.js +124 -0
  422. data/frameworks/sproutcore/frameworks/foundation/tests/system/root_responder/makeMainPane.js +68 -0
  423. data/frameworks/sproutcore/frameworks/foundation/tests/system/root_responder/root_responder.js +101 -0
  424. data/frameworks/sproutcore/frameworks/foundation/tests/system/root_responder/targetForAction.js +238 -0
  425. data/frameworks/sproutcore/frameworks/foundation/tests/system/routes.js +33 -0
  426. data/frameworks/sproutcore/frameworks/foundation/tests/system/timer/invalidate.js +38 -0
  427. data/frameworks/sproutcore/frameworks/foundation/tests/system/timer/invokeLater.js +201 -0
  428. data/frameworks/sproutcore/frameworks/foundation/tests/system/timer/isPaused.js +71 -0
  429. data/frameworks/sproutcore/frameworks/foundation/tests/system/timer/performAction.js +67 -0
  430. data/frameworks/sproutcore/frameworks/foundation/tests/system/timer/schedule.js +170 -0
  431. data/frameworks/sproutcore/frameworks/foundation/tests/system/user_defaults.js +27 -0
  432. data/frameworks/sproutcore/frameworks/foundation/tests/system/utils/normalizeURL.js +18 -0
  433. data/frameworks/sproutcore/frameworks/foundation/tests/system/utils/range.js +62 -0
  434. data/frameworks/sproutcore/frameworks/foundation/tests/validators/credit_card.js +35 -0
  435. data/frameworks/sproutcore/frameworks/foundation/tests/validators/date.js +23 -0
  436. data/frameworks/sproutcore/frameworks/foundation/tests/validators/number.js +47 -0
  437. data/frameworks/sproutcore/frameworks/foundation/tests/validators/password.js +13 -0
  438. data/frameworks/sproutcore/frameworks/foundation/tests/views/container/methods.js +10 -0
  439. data/frameworks/sproutcore/frameworks/foundation/tests/views/container/ui.js +83 -0
  440. data/frameworks/sproutcore/frameworks/foundation/tests/views/image/ui.js +39 -0
  441. data/frameworks/sproutcore/frameworks/foundation/tests/views/label/ui.js +148 -0
  442. data/frameworks/sproutcore/frameworks/foundation/tests/views/main_pane.js +31 -0
  443. data/frameworks/sproutcore/frameworks/foundation/tests/views/pane/append_remove.js +89 -0
  444. data/frameworks/sproutcore/frameworks/foundation/tests/views/pane/firstResponder.js +148 -0
  445. data/frameworks/sproutcore/frameworks/foundation/tests/views/pane/keyPane.js +133 -0
  446. data/frameworks/sproutcore/frameworks/foundation/tests/views/pane/sendEvent.js +165 -0
  447. data/frameworks/sproutcore/frameworks/foundation/tests/views/text_field/methods.js +76 -0
  448. data/frameworks/sproutcore/frameworks/foundation/tests/views/text_field/ui.js +250 -0
  449. data/frameworks/sproutcore/frameworks/foundation/tests/views/view/clippingFrame.js +133 -0
  450. data/frameworks/sproutcore/frameworks/foundation/tests/views/view/convertFrames.js +246 -0
  451. data/frameworks/sproutcore/frameworks/foundation/tests/views/view/createChildViews.js +122 -0
  452. data/frameworks/sproutcore/frameworks/foundation/tests/views/view/createLayer.js +97 -0
  453. data/frameworks/sproutcore/frameworks/foundation/tests/views/view/destroyLayer.js +85 -0
  454. data/frameworks/sproutcore/frameworks/foundation/tests/views/view/findLayerInParentLayer.js +52 -0
  455. data/frameworks/sproutcore/frameworks/foundation/tests/views/view/init.js +50 -0
  456. data/frameworks/sproutcore/frameworks/foundation/tests/views/view/insertBefore.js +200 -0
  457. data/frameworks/sproutcore/frameworks/foundation/tests/views/view/isVisible.js +51 -0
  458. data/frameworks/sproutcore/frameworks/foundation/tests/views/view/isVisibleInWindow.js +113 -0
  459. data/frameworks/sproutcore/frameworks/foundation/tests/views/view/layer.js +150 -0
  460. data/frameworks/sproutcore/frameworks/foundation/tests/views/view/layoutChildViews.js +162 -0
  461. data/frameworks/sproutcore/frameworks/foundation/tests/views/view/layoutDidChange.js +127 -0
  462. data/frameworks/sproutcore/frameworks/foundation/tests/views/view/layoutStyle.js +328 -0
  463. data/frameworks/sproutcore/frameworks/foundation/tests/views/view/parentViewDidChange.js +67 -0
  464. data/frameworks/sproutcore/frameworks/foundation/tests/views/view/prepareContext.js +166 -0
  465. data/frameworks/sproutcore/frameworks/foundation/tests/views/view/removeChild.js +189 -0
  466. data/frameworks/sproutcore/frameworks/foundation/tests/views/view/render.js +83 -0
  467. data/frameworks/sproutcore/frameworks/foundation/tests/views/view/replaceChild.js +29 -0
  468. data/frameworks/sproutcore/frameworks/foundation/tests/views/view/updateLayer.js +146 -0
  469. data/frameworks/sproutcore/frameworks/foundation/tests/views/view/updateLayerLocation.js +194 -0
  470. data/frameworks/sproutcore/frameworks/foundation/tests/views/view/viewDidResize.js +185 -0
  471. data/frameworks/sproutcore/frameworks/foundation/validators/credit_card.js +125 -0
  472. data/frameworks/sproutcore/frameworks/foundation/validators/date.js +52 -0
  473. data/frameworks/sproutcore/frameworks/foundation/validators/email.js +45 -0
  474. data/frameworks/sproutcore/frameworks/foundation/validators/not_empty.js +33 -0
  475. data/frameworks/sproutcore/frameworks/foundation/validators/number.js +82 -0
  476. data/frameworks/sproutcore/frameworks/foundation/validators/password.js +86 -0
  477. data/frameworks/sproutcore/frameworks/foundation/validators/validator.js +311 -0
  478. data/frameworks/sproutcore/frameworks/foundation/views/container.js +136 -0
  479. data/frameworks/sproutcore/frameworks/foundation/views/field.js +287 -0
  480. data/frameworks/sproutcore/frameworks/foundation/views/image.js +161 -0
  481. data/frameworks/sproutcore/frameworks/foundation/views/label.js +271 -0
  482. data/frameworks/sproutcore/frameworks/foundation/views/text_field.js +257 -0
  483. data/frameworks/sproutcore/frameworks/foundation/views/view.js +2405 -0
  484. data/frameworks/sproutcore/frameworks/mobile/english.lproj/core.css +12 -0
  485. data/frameworks/sproutcore/frameworks/mobile/lib/index.rhtml +126 -0
  486. data/frameworks/sproutcore/frameworks/mobile/system/root_responder.js +109 -0
  487. data/frameworks/sproutcore/frameworks/mobile/tests/views/button/ui.js +9 -0
  488. data/frameworks/sproutcore/frameworks/mobile/views/button.js +190 -0
  489. data/frameworks/sproutcore/frameworks/runtime/README +12 -0
  490. data/frameworks/sproutcore/frameworks/runtime/core.js +856 -0
  491. data/frameworks/sproutcore/frameworks/runtime/debug/test_suites/array/base.js +238 -0
  492. data/frameworks/sproutcore/frameworks/runtime/debug/test_suites/array/indexOf.js +33 -0
  493. data/frameworks/sproutcore/frameworks/runtime/debug/test_suites/array/insertAt.js +121 -0
  494. data/frameworks/sproutcore/frameworks/runtime/debug/test_suites/array/objectAt.js +34 -0
  495. data/frameworks/sproutcore/frameworks/runtime/debug/test_suites/array/popObject.js +50 -0
  496. data/frameworks/sproutcore/frameworks/runtime/debug/test_suites/array/pushObject.js +46 -0
  497. data/frameworks/sproutcore/frameworks/runtime/debug/test_suites/array/rangeObserver.js +371 -0
  498. data/frameworks/sproutcore/frameworks/runtime/debug/test_suites/array/removeAt.js +100 -0
  499. data/frameworks/sproutcore/frameworks/runtime/debug/test_suites/array/removeObject.js +49 -0
  500. data/frameworks/sproutcore/frameworks/runtime/debug/test_suites/array/replace.js +94 -0
  501. data/frameworks/sproutcore/frameworks/runtime/debug/test_suites/array/shiftObject.js +50 -0
  502. data/frameworks/sproutcore/frameworks/runtime/debug/test_suites/array/unshiftObject.js +47 -0
  503. data/frameworks/sproutcore/frameworks/runtime/license.js +28 -0
  504. data/frameworks/sproutcore/frameworks/runtime/mixins/array.js +613 -0
  505. data/frameworks/sproutcore/frameworks/runtime/mixins/copyable.js +64 -0
  506. data/frameworks/sproutcore/frameworks/runtime/mixins/delegate_support.js +108 -0
  507. data/frameworks/sproutcore/frameworks/runtime/mixins/enumerable.js +1258 -0
  508. data/frameworks/sproutcore/frameworks/runtime/mixins/freezable.js +104 -0
  509. data/frameworks/sproutcore/frameworks/runtime/mixins/observable.js +1305 -0
  510. data/frameworks/sproutcore/frameworks/runtime/private/chain_observer.js +141 -0
  511. data/frameworks/sproutcore/frameworks/runtime/private/observer_queue.js +148 -0
  512. data/frameworks/sproutcore/frameworks/runtime/private/observer_set.js +152 -0
  513. data/frameworks/sproutcore/frameworks/runtime/protocols/observable_protocol.js +40 -0
  514. data/frameworks/sproutcore/frameworks/runtime/protocols/sparse_array_delegate.js +131 -0
  515. data/frameworks/sproutcore/frameworks/runtime/system/binding.js +915 -0
  516. data/frameworks/sproutcore/frameworks/runtime/system/enumerator.js +107 -0
  517. data/frameworks/sproutcore/frameworks/runtime/system/index_set.js +1166 -0
  518. data/frameworks/sproutcore/frameworks/runtime/system/object.js +801 -0
  519. data/frameworks/sproutcore/frameworks/runtime/system/range_observer.js +265 -0
  520. data/frameworks/sproutcore/frameworks/runtime/system/run_loop.js +241 -0
  521. data/frameworks/sproutcore/frameworks/runtime/system/selection_set.js +649 -0
  522. data/frameworks/sproutcore/frameworks/runtime/system/set.js +375 -0
  523. data/frameworks/sproutcore/frameworks/runtime/system/sparse_array.js +295 -0
  524. data/frameworks/sproutcore/frameworks/runtime/tests/core/IsEqual.js +56 -0
  525. data/frameworks/sproutcore/frameworks/runtime/tests/core/beget.js +23 -0
  526. data/frameworks/sproutcore/frameworks/runtime/tests/core/clone.js +66 -0
  527. data/frameworks/sproutcore/frameworks/runtime/tests/core/compare.js +44 -0
  528. data/frameworks/sproutcore/frameworks/runtime/tests/core/console.js +16 -0
  529. data/frameworks/sproutcore/frameworks/runtime/tests/core/guidFor.js +147 -0
  530. data/frameworks/sproutcore/frameworks/runtime/tests/core/isArray.js +25 -0
  531. data/frameworks/sproutcore/frameworks/runtime/tests/core/itemType.js +38 -0
  532. data/frameworks/sproutcore/frameworks/runtime/tests/core/keys.js +20 -0
  533. data/frameworks/sproutcore/frameworks/runtime/tests/core/makeArray.js +30 -0
  534. data/frameworks/sproutcore/frameworks/runtime/tests/core/objectForPropertyPath.js +19 -0
  535. data/frameworks/sproutcore/frameworks/runtime/tests/core/tupleForPropertyPath.js +37 -0
  536. data/frameworks/sproutcore/frameworks/runtime/tests/mixins/array.js +57 -0
  537. data/frameworks/sproutcore/frameworks/runtime/tests/mixins/enumerable.js +611 -0
  538. data/frameworks/sproutcore/frameworks/runtime/tests/mixins/observable/observable.js +587 -0
  539. data/frameworks/sproutcore/frameworks/runtime/tests/mixins/observable/propertyChanges.js +132 -0
  540. data/frameworks/sproutcore/frameworks/runtime/tests/mixins/observable/registerDependentKeys.js +79 -0
  541. data/frameworks/sproutcore/frameworks/runtime/tests/mixins/propertyChanges.js +80 -0
  542. data/frameworks/sproutcore/frameworks/runtime/tests/private/observer_queue/isObservingSuspended.js +55 -0
  543. data/frameworks/sproutcore/frameworks/runtime/tests/system/binding.js +265 -0
  544. data/frameworks/sproutcore/frameworks/runtime/tests/system/index_set/add.js +195 -0
  545. data/frameworks/sproutcore/frameworks/runtime/tests/system/index_set/clone.js +43 -0
  546. data/frameworks/sproutcore/frameworks/runtime/tests/system/index_set/contains.js +74 -0
  547. data/frameworks/sproutcore/frameworks/runtime/tests/system/index_set/create.js +42 -0
  548. data/frameworks/sproutcore/frameworks/runtime/tests/system/index_set/indexAfter.js +38 -0
  549. data/frameworks/sproutcore/frameworks/runtime/tests/system/index_set/indexBefore.js +38 -0
  550. data/frameworks/sproutcore/frameworks/runtime/tests/system/index_set/intersects.js +74 -0
  551. data/frameworks/sproutcore/frameworks/runtime/tests/system/index_set/max.js +40 -0
  552. data/frameworks/sproutcore/frameworks/runtime/tests/system/index_set/min.js +40 -0
  553. data/frameworks/sproutcore/frameworks/runtime/tests/system/index_set/rangeStartForIndex.js +36 -0
  554. data/frameworks/sproutcore/frameworks/runtime/tests/system/index_set/remove.js +189 -0
  555. data/frameworks/sproutcore/frameworks/runtime/tests/system/index_set/without.js +89 -0
  556. data/frameworks/sproutcore/frameworks/runtime/tests/system/object/base.js +135 -0
  557. data/frameworks/sproutcore/frameworks/runtime/tests/system/object/bindings.js +339 -0
  558. data/frameworks/sproutcore/frameworks/runtime/tests/system/range_observer/create.js +59 -0
  559. data/frameworks/sproutcore/frameworks/runtime/tests/system/range_observer/destroy.js +75 -0
  560. data/frameworks/sproutcore/frameworks/runtime/tests/system/range_observer/objectPropertyDidChange.js +117 -0
  561. data/frameworks/sproutcore/frameworks/runtime/tests/system/range_observer/rangeDidChange.js +110 -0
  562. data/frameworks/sproutcore/frameworks/runtime/tests/system/range_observer/update.js +65 -0
  563. data/frameworks/sproutcore/frameworks/runtime/tests/system/run_loop.js +120 -0
  564. data/frameworks/sproutcore/frameworks/runtime/tests/system/selection_set/add.js +92 -0
  565. data/frameworks/sproutcore/frameworks/runtime/tests/system/selection_set/copy.js +17 -0
  566. data/frameworks/sproutcore/frameworks/runtime/tests/system/selection_set/indexSetForSource.js +85 -0
  567. data/frameworks/sproutcore/frameworks/runtime/tests/system/selection_set/isEqual.js +60 -0
  568. data/frameworks/sproutcore/frameworks/runtime/tests/system/selection_set/remove.js +87 -0
  569. data/frameworks/sproutcore/frameworks/runtime/tests/system/set.js +292 -0
  570. data/frameworks/sproutcore/frameworks/runtime/tests/system/sparse_array.js +122 -0
  571. data/frameworks/sproutcore/frameworks/testing/core.js +196 -0
  572. data/frameworks/sproutcore/frameworks/testing/english.lproj/additions.css +8 -0
  573. data/frameworks/sproutcore/frameworks/testing/english.lproj/runner.css +126 -0
  574. data/frameworks/sproutcore/frameworks/testing/english.lproj/testsuite.css +131 -0
  575. data/frameworks/sproutcore/frameworks/testing/extras.js +17 -0
  576. data/frameworks/sproutcore/frameworks/testing/jquery.js +3559 -0
  577. data/frameworks/sproutcore/frameworks/testing/qunit.js +827 -0
  578. data/frameworks/sproutcore/frameworks/testing/system/dump.js +205 -0
  579. data/frameworks/sproutcore/frameworks/testing/system/equiv.js +201 -0
  580. data/frameworks/sproutcore/frameworks/testing/system/plan.js +691 -0
  581. data/frameworks/sproutcore/frameworks/testing/system/runner.js +209 -0
  582. data/frameworks/sproutcore/frameworks/testing/system/suite.js +228 -0
  583. data/frameworks/sproutcore/frameworks/testing/utils.js +62 -0
  584. data/frameworks/sproutcore/lib/index.rhtml +121 -0
  585. data/frameworks/sproutcore/license.js +28 -0
  586. data/frameworks/sproutcore/themes/empty_theme/tests/mini_icons.rhtml +69 -0
  587. data/frameworks/sproutcore/themes/iphone_theme/english.lproj/button.css +41 -0
  588. data/frameworks/sproutcore/themes/iphone_theme/english.lproj/core.css +8 -0
  589. data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/backButton.png +0 -0
  590. data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/blueButton.png +0 -0
  591. data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/cancel.png +0 -0
  592. data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/grayButton.png +0 -0
  593. data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/leftButton.png +0 -0
  594. data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/listArrow.png +0 -0
  595. data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/listArrowSel.png +0 -0
  596. data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/listGroup.png +0 -0
  597. data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/loading.gif +0 -0
  598. data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/pinstripes.png +0 -0
  599. data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/rightButton.png +0 -0
  600. data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/selection.png +0 -0
  601. data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/thumb.png +0 -0
  602. data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/toggle.png +0 -0
  603. data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/toggleOn.png +0 -0
  604. data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/toolButton.png +0 -0
  605. data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/toolbar.png +0 -0
  606. data/frameworks/sproutcore/themes/iphone_theme/english.lproj/images/whiteButton.png +0 -0
  607. data/frameworks/sproutcore/themes/iphone_theme/english.lproj/strings.js +15 -0
  608. data/frameworks/sproutcore/themes/standard_theme/english.lproj/button.css +331 -0
  609. data/frameworks/sproutcore/themes/standard_theme/english.lproj/checkbox.css +91 -0
  610. data/frameworks/sproutcore/themes/standard_theme/english.lproj/collection.css +134 -0
  611. data/frameworks/sproutcore/themes/standard_theme/english.lproj/core.css +60 -0
  612. data/frameworks/sproutcore/themes/standard_theme/english.lproj/disclosure.css +55 -0
  613. data/frameworks/sproutcore/themes/standard_theme/english.lproj/images/sc-theme-repeat-x.png +0 -0
  614. data/frameworks/sproutcore/themes/standard_theme/english.lproj/images/sc-theme-sprite.png +0 -0
  615. data/frameworks/sproutcore/themes/standard_theme/english.lproj/images/sc-theme-ysprite.png +0 -0
  616. data/frameworks/sproutcore/themes/standard_theme/english.lproj/images/sc-toolbar-view.png +0 -0
  617. data/frameworks/sproutcore/themes/standard_theme/english.lproj/label.css +11 -0
  618. data/frameworks/sproutcore/themes/standard_theme/english.lproj/list_item.css +30 -0
  619. data/frameworks/sproutcore/themes/standard_theme/english.lproj/pane.css +8 -0
  620. data/frameworks/sproutcore/themes/standard_theme/english.lproj/panels/background-fat.jpg +0 -0
  621. data/frameworks/sproutcore/themes/standard_theme/english.lproj/panels/background-thin.jpg +0 -0
  622. data/frameworks/sproutcore/themes/standard_theme/english.lproj/panels/bottom-edge.png +0 -0
  623. data/frameworks/sproutcore/themes/standard_theme/english.lproj/panels/bottom-left-corner.png +0 -0
  624. data/frameworks/sproutcore/themes/standard_theme/english.lproj/panels/bottom-right-corner.png +0 -0
  625. data/frameworks/sproutcore/themes/standard_theme/english.lproj/panels/left-edge.png +0 -0
  626. data/frameworks/sproutcore/themes/standard_theme/english.lproj/panels/overlay.png +0 -0
  627. data/frameworks/sproutcore/themes/standard_theme/english.lproj/panels/right-edge.png +0 -0
  628. data/frameworks/sproutcore/themes/standard_theme/english.lproj/panels/top-edge.png +0 -0
  629. data/frameworks/sproutcore/themes/standard_theme/english.lproj/panels/top-left-corner.png +0 -0
  630. data/frameworks/sproutcore/themes/standard_theme/english.lproj/panels/top-right-corner.png +0 -0
  631. data/frameworks/sproutcore/themes/standard_theme/english.lproj/progress.css +26 -0
  632. data/frameworks/sproutcore/themes/standard_theme/english.lproj/radio.css +122 -0
  633. data/frameworks/sproutcore/themes/standard_theme/english.lproj/segmented.css +279 -0
  634. data/frameworks/sproutcore/themes/standard_theme/english.lproj/slider.css +94 -0
  635. data/frameworks/sproutcore/themes/standard_theme/english.lproj/split_view.css +27 -0
  636. data/frameworks/sproutcore/themes/standard_theme/english.lproj/tab.css +18 -0
  637. data/frameworks/sproutcore/themes/standard_theme/english.lproj/text_field.css +10 -0
  638. data/frameworks/sproutcore/themes/standard_theme/english.lproj/toolbar.css +7 -0
  639. data/lib/sproutcore.rb +9 -1
  640. data/lib/sproutcore/tools/build.rb +1 -1
  641. data/lib/thor/CHANGELOG.rdoc +52 -0
  642. data/lib/thor/LICENSE +20 -0
  643. data/lib/thor/README.markdown +76 -0
  644. data/lib/thor/Rakefile +6 -0
  645. data/lib/thor/Thorfile +45 -0
  646. data/lib/thor/bin/rake2thor +83 -0
  647. data/lib/thor/bin/thor +7 -0
  648. data/lib/thor/lib/thor.rb +170 -0
  649. data/lib/thor/lib/thor/error.rb +3 -0
  650. data/lib/thor/lib/thor/options.rb +267 -0
  651. data/lib/thor/lib/thor/ordered_hash.rb +64 -0
  652. data/lib/thor/lib/thor/runner.rb +305 -0
  653. data/lib/thor/lib/thor/task.rb +83 -0
  654. data/lib/thor/lib/thor/task_hash.rb +22 -0
  655. data/lib/thor/lib/thor/tasks.rb +77 -0
  656. data/lib/thor/lib/thor/tasks/package.rb +18 -0
  657. data/lib/thor/lib/thor/util.rb +75 -0
  658. data/lib/thor/script/destroy +14 -0
  659. data/lib/thor/script/generate +14 -0
  660. data/lib/thor/task.thor +15 -0
  661. metadata +664 -351
  662. data/VERSION +0 -1
  663. data/spec/buildtasks/build/copy_spec.rb +0 -60
  664. data/spec/buildtasks/build/spec_helper.rb +0 -36
  665. data/spec/buildtasks/manifest/catalog_spec.rb +0 -48
  666. data/spec/buildtasks/manifest/hide_buildfiles_spec.rb +0 -125
  667. data/spec/buildtasks/manifest/localize_spec.rb +0 -97
  668. data/spec/buildtasks/manifest/prepare_build_tasks/combine_spec.rb +0 -246
  669. data/spec/buildtasks/manifest/prepare_build_tasks/css_spec.rb +0 -87
  670. data/spec/buildtasks/manifest/prepare_build_tasks/html_spec.rb +0 -175
  671. data/spec/buildtasks/manifest/prepare_build_tasks/javascript_spec.rb +0 -65
  672. data/spec/buildtasks/manifest/prepare_build_tasks/minify_spec.rb +0 -70
  673. data/spec/buildtasks/manifest/prepare_build_tasks/packed_spec.rb +0 -152
  674. data/spec/buildtasks/manifest/prepare_build_tasks/sass_spec.rb +0 -98
  675. data/spec/buildtasks/manifest/prepare_build_tasks/strings_spec.rb +0 -64
  676. data/spec/buildtasks/manifest/prepare_build_tasks/tests_spec.rb +0 -163
  677. data/spec/buildtasks/manifest/prepare_spec.rb +0 -43
  678. data/spec/buildtasks/manifest/spec_helper.rb +0 -35
  679. data/spec/buildtasks/target_spec.rb +0 -214
  680. data/spec/fixtures/builder_tests/Buildfile +0 -15
  681. data/spec/fixtures/builder_tests/apps/combine_test/a.js +0 -1
  682. data/spec/fixtures/builder_tests/apps/combine_test/b.js +0 -1
  683. data/spec/fixtures/builder_tests/apps/combine_test/c.js +0 -1
  684. data/spec/fixtures/builder_tests/apps/combine_test/english.lproj/a.css +0 -1
  685. data/spec/fixtures/builder_tests/apps/combine_test/english.lproj/b.css +0 -1
  686. data/spec/fixtures/builder_tests/apps/combine_test/english.lproj/c.css +0 -1
  687. data/spec/fixtures/builder_tests/apps/html_test/english.lproj/bar1_sample.rhtml +0 -2
  688. data/spec/fixtures/builder_tests/apps/html_test/english.lproj/erb_sample.html.erb +0 -1
  689. data/spec/fixtures/builder_tests/apps/html_test/english.lproj/icons/image.png +0 -0
  690. data/spec/fixtures/builder_tests/apps/html_test/english.lproj/image.jpg +0 -0
  691. data/spec/fixtures/builder_tests/apps/html_test/english.lproj/rhtml_sample.rhtml +0 -1
  692. data/spec/fixtures/builder_tests/apps/html_test/english.lproj/strings.js +0 -4
  693. data/spec/fixtures/builder_tests/apps/html_test/english.lproj/style.css +0 -0
  694. data/spec/fixtures/builder_tests/apps/html_test/french.lproj/french-icons/fr.png +0 -0
  695. data/spec/fixtures/builder_tests/apps/html_test/french.lproj/strings.js +0 -4
  696. data/spec/fixtures/builder_tests/apps/html_test/lib/layout_template.rhtml +0 -1
  697. data/spec/fixtures/builder_tests/apps/html_test/scripts.js +0 -0
  698. data/spec/fixtures/builder_tests/apps/javascript_test/sc_static.js +0 -15
  699. data/spec/fixtures/builder_tests/apps/javascript_test/sc_super.js +0 -4
  700. data/spec/fixtures/builder_tests/apps/javascript_test/strings.js +0 -7
  701. data/spec/fixtures/builder_tests/apps/sass_test/sample.sass +0 -3
  702. data/spec/fixtures/builder_tests/apps/strings_test/lproj/strings.js +0 -8
  703. data/spec/fixtures/builder_tests/apps/stylesheet_test/build_directives.css +0 -9
  704. data/spec/fixtures/builder_tests/apps/stylesheet_test/sc_static.css +0 -12
  705. data/spec/fixtures/builder_tests/apps/test_test/lib/alt_layout.rhtml +0 -1
  706. data/spec/fixtures/builder_tests/apps/test_test/lib/test_layout.rhtml +0 -3
  707. data/spec/fixtures/builder_tests/apps/test_test/tests/qunit_test.js +0 -1
  708. data/spec/fixtures/builder_tests/apps/test_test/tests/qunit_test2.js +0 -1
  709. data/spec/fixtures/builder_tests/apps/test_test/tests/rhtml_test.rhtml +0 -4
  710. data/spec/fixtures/builder_tests/frameworks/debug/core.js +0 -0
  711. data/spec/fixtures/builder_tests/frameworks/debug/english.lproj/dummy.css +0 -0
  712. data/spec/fixtures/builder_tests/frameworks/qunit/core.js +0 -0
  713. data/spec/fixtures/builder_tests/frameworks/qunit/english.lproj/dummy.css +0 -0
  714. data/spec/fixtures/builder_tests/frameworks/req_target_1/english.lproj/req_style_1.css +0 -0
  715. data/spec/fixtures/builder_tests/frameworks/req_target_1/english.lproj/strings.js +0 -4
  716. data/spec/fixtures/builder_tests/frameworks/req_target_1/english.lproj/test.rhtml +0 -1
  717. data/spec/fixtures/builder_tests/frameworks/req_target_1/req_js_1.js +0 -0
  718. data/spec/fixtures/builder_tests/frameworks/req_target_2/english.lproj/req_style_2.css +0 -0
  719. data/spec/fixtures/builder_tests/frameworks/req_target_2/english.lproj/test.rhtml +0 -1
  720. data/spec/fixtures/builder_tests/frameworks/req_target_2/javascript.js +0 -1
  721. data/spec/fixtures/builder_tests/frameworks/req_target_2/lib/alt_layout.rhtml +0 -0
  722. data/spec/fixtures/builder_tests/frameworks/req_target_2/req_js_2.js +0 -0
  723. data/spec/fixtures/builder_tests/themes/sample_theme/Buildfile +0 -1
  724. data/spec/fixtures/buildfiles/basic/Buildfile +0 -16
  725. data/spec/fixtures/buildfiles/basic/task_module.rake +0 -6
  726. data/spec/fixtures/buildfiles/installed/Buildfile +0 -7
  727. data/spec/fixtures/buildfiles/installed/Buildfile2 +0 -5
  728. data/spec/fixtures/buildfiles/project_test/Buildfile +0 -4
  729. data/spec/fixtures/buildfiles/project_test/not_project/Buildfile +0 -2
  730. data/spec/fixtures/buildfiles/project_test/not_project/child/PLACEHOLDER +0 -0
  731. data/spec/fixtures/entry_for_project/Buildfile +0 -1
  732. data/spec/fixtures/entry_for_project/apps/test_app/entry.txt +0 -0
  733. data/spec/fixtures/entry_for_project/apps/test_app/frameworks/nested/PLACEHOLDER +0 -0
  734. data/spec/fixtures/entry_for_project/frameworks/shared/PLACEHOLDER +0 -0
  735. data/spec/fixtures/find_targets/custom/Buildfile +0 -8
  736. data/spec/fixtures/find_targets/custom/bars/bar1/bars/bar1/PLACEHOLDER +0 -0
  737. data/spec/fixtures/find_targets/custom/bars/bar1/bars/bar2/PLACEHOLDER +0 -0
  738. data/spec/fixtures/find_targets/custom/bars/bar1/foos/foo1/PLACEHOLDER +0 -0
  739. data/spec/fixtures/find_targets/custom/bars/bar1/foos/foo2/PLACEHOLDER +0 -0
  740. data/spec/fixtures/find_targets/custom/foos/custom_foos/Buildfile +0 -5
  741. data/spec/fixtures/find_targets/custom/foos/custom_foos/custom_foodir/foo1/PLACEHOLDER +0 -0
  742. data/spec/fixtures/find_targets/custom/foos/custom_foos/custom_foodir/foo2/PLACEHOLDER +0 -0
  743. data/spec/fixtures/find_targets/custom/foos/custom_foos/foos/not_foo1/PLACEHOLDER +0 -0
  744. data/spec/fixtures/find_targets/custom/foos/foo1/bars/bar1/PLACEHOLDER +0 -0
  745. data/spec/fixtures/find_targets/custom/foos/foo1/bars/bar2/PLACEHOLDER +0 -0
  746. data/spec/fixtures/find_targets/nested/Buildfile +0 -8
  747. data/spec/fixtures/find_targets/nested/apps/app1/Buildfile +0 -1
  748. data/spec/fixtures/find_targets/nested/apps/app1/apps/nested_app/PLACEHOLDER +0 -0
  749. data/spec/fixtures/find_targets/standard/Apps/app1/frameworks/framework1/PLACEHOLDER +0 -0
  750. data/spec/fixtures/find_targets/standard/Apps/app1/frameworks/framework2/PLACEHOLDER +0 -0
  751. data/spec/fixtures/find_targets/standard/clients/client1/PLACEHOLDER +0 -0
  752. data/spec/fixtures/find_targets/standard/frameworks/framework1/frameworks/framework1/PLACEHOLDER +0 -0
  753. data/spec/fixtures/find_targets/standard/frameworks/framework2/PLACEHOLDER +0 -0
  754. data/spec/fixtures/find_targets/standard/themes/theme1/PLACEHOLDER +0 -0
  755. data/spec/fixtures/find_targets/standard/themes/theme2/PLACEHOLDER +0 -0
  756. data/spec/fixtures/languages/apps/caps_long_names/English.lproj/PLACEHOLDER +0 -0
  757. data/spec/fixtures/languages/apps/caps_long_names/FreNCH.lproj/PLACEHOLDER +0 -0
  758. data/spec/fixtures/languages/apps/caps_long_names/UnknOWN.lproj/PLACEHOLDER +0 -0
  759. data/spec/fixtures/languages/apps/long_names/english.lproj/PLACEHOLDER +0 -0
  760. data/spec/fixtures/languages/apps/long_names/french.lproj/PLACEHOLDER +0 -0
  761. data/spec/fixtures/languages/apps/long_names/german.lproj/PLACEHOLDER +0 -0
  762. data/spec/fixtures/languages/apps/long_names/italian.lproj/PLACEHOLDER +0 -0
  763. data/spec/fixtures/languages/apps/long_names/japanese.lproj/PLACEHOLDER +0 -0
  764. data/spec/fixtures/languages/apps/long_names/spanish.lproj/PLACEHOLDER +0 -0
  765. data/spec/fixtures/languages/apps/long_names/unknown.lproj/PLACEHOLDER +0 -0
  766. data/spec/fixtures/languages/apps/no_names/PLACEHOLDER +0 -0
  767. data/spec/fixtures/languages/apps/short_names/de.lproj/PLACEHOLDER +0 -0
  768. data/spec/fixtures/languages/apps/short_names/en-CA.lproj/PLACEHOLDER +0 -0
  769. data/spec/fixtures/languages/apps/short_names/en-GB.lproj/PLACEHOLDER +0 -0
  770. data/spec/fixtures/languages/apps/short_names/en-US.lproj/PLACEHOLDER +0 -0
  771. data/spec/fixtures/languages/apps/short_names/en.lproj/PLACEHOLDER +0 -0
  772. data/spec/fixtures/languages/apps/short_names/es.lproj/PLACEHOLDER +0 -0
  773. data/spec/fixtures/languages/apps/short_names/foo.lproj/PLACEHOLDER +0 -0
  774. data/spec/fixtures/languages/apps/short_names/fr.lproj/PLACEHOLDER +0 -0
  775. data/spec/fixtures/languages/apps/short_names/it.lproj/PLACEHOLDER +0 -0
  776. data/spec/fixtures/languages/apps/short_names/ja.lproj/PLACEHOLDER +0 -0
  777. data/spec/fixtures/ordered_entries/apps/no_requires/1.js +0 -1
  778. data/spec/fixtures/ordered_entries/apps/no_requires/B.js +0 -1
  779. data/spec/fixtures/ordered_entries/apps/no_requires/a.js +0 -1
  780. data/spec/fixtures/ordered_entries/apps/no_requires/a/a.js +0 -1
  781. data/spec/fixtures/ordered_entries/apps/no_requires/a/b.js +0 -1
  782. data/spec/fixtures/ordered_entries/apps/no_requires/b/a.js +0 -1
  783. data/spec/fixtures/ordered_entries/apps/no_requires/c.js +0 -1
  784. data/spec/fixtures/ordered_entries/apps/no_requires/core.js +0 -1
  785. data/spec/fixtures/ordered_entries/apps/no_requires/english.lproj/B.css +0 -0
  786. data/spec/fixtures/ordered_entries/apps/no_requires/english.lproj/a.css +0 -0
  787. data/spec/fixtures/ordered_entries/apps/no_requires/english.lproj/a/a.css +0 -0
  788. data/spec/fixtures/ordered_entries/apps/no_requires/english.lproj/a/b.css +0 -0
  789. data/spec/fixtures/ordered_entries/apps/no_requires/english.lproj/b/a.css +0 -0
  790. data/spec/fixtures/ordered_entries/apps/no_requires/english.lproj/c.css +0 -0
  791. data/spec/fixtures/ordered_entries/apps/no_requires/lproj/strings.js +0 -1
  792. data/spec/fixtures/ordered_entries/apps/no_requires/utils.js +0 -1
  793. data/spec/fixtures/ordered_entries/apps/with_requires/a.js +0 -2
  794. data/spec/fixtures/ordered_entries/apps/with_requires/b.js +0 -3
  795. data/spec/fixtures/ordered_entries/apps/with_requires/c.js +0 -2
  796. data/spec/fixtures/ordered_entries/apps/with_requires/english.lproj/a.css +0 -2
  797. data/spec/fixtures/ordered_entries/apps/with_requires/english.lproj/b.css +0 -2
  798. data/spec/fixtures/ordered_entries/apps/with_requires/english.lproj/c.css +0 -2
  799. data/spec/fixtures/ordered_entries/apps/with_requires/english.lproj/d.js +0 -1
  800. data/spec/fixtures/real_world/Buildfile +0 -12
  801. data/spec/fixtures/real_world/apps/account/README +0 -1
  802. data/spec/fixtures/real_world/apps/calendar/README +0 -1
  803. data/spec/fixtures/real_world/apps/contacts/README_BEFORE_EDITING +0 -1
  804. data/spec/fixtures/real_world/apps/files/README +0 -1
  805. data/spec/fixtures/real_world/apps/mail/README +0 -1
  806. data/spec/fixtures/real_world/apps/mobile_photos/README +0 -1
  807. data/spec/fixtures/real_world/apps/photos/README +0 -1
  808. data/spec/fixtures/real_world/apps/uploader/README +0 -1
  809. data/spec/fixtures/real_world/frameworks/core_files/PLACEHOLDER +0 -0
  810. data/spec/fixtures/real_world/frameworks/core_photos/PLACEHOLDER +0 -0
  811. data/spec/fixtures/real_world/frameworks/shared/PLACEHOLDER +0 -0
  812. data/spec/fixtures/real_world/frameworks/sproutcore/Buildfile +0 -26
  813. data/spec/fixtures/real_world/frameworks/sproutcore/README +0 -1
  814. data/spec/fixtures/real_world/frameworks/sproutcore/apps/docs/PLACEHOLDER +0 -0
  815. data/spec/fixtures/real_world/frameworks/sproutcore/apps/test_runner/PLACEHOLDER +0 -0
  816. data/spec/fixtures/real_world/frameworks/sproutcore/core.js +0 -0
  817. data/spec/fixtures/real_world/frameworks/sproutcore/debug/debug-resource.html +0 -0
  818. data/spec/fixtures/real_world/frameworks/sproutcore/debug/sample_debug.js +0 -0
  819. data/spec/fixtures/real_world/frameworks/sproutcore/demo2.js +0 -0
  820. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/debug/sample_debug-loc.js +0 -0
  821. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/demo.css +0 -4
  822. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/demo.html +0 -1
  823. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/demo2.sass +0 -0
  824. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/file_extension_test.haml +0 -0
  825. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/file_extension_test.html.erb +0 -1
  826. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/file_extension_test.rhtml +0 -0
  827. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/fixtures/sample_fixtures-loc.js +0 -0
  828. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/has_require.css +0 -4
  829. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/no_require.css +0 -1
  830. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/no_sc_resource.rhtml +0 -1
  831. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/protocols/sample-loc.js +0 -0
  832. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/sc_resource.css +0 -6
  833. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/sc_resource.rhtml +0 -3
  834. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/strings.js +0 -1
  835. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/tests/sample-loc.js +0 -0
  836. data/spec/fixtures/real_world/frameworks/sproutcore/fixtures/sample-json-fixture.json +0 -1
  837. data/spec/fixtures/real_world/frameworks/sproutcore/fixtures/sample_fixtures.js +0 -0
  838. data/spec/fixtures/real_world/frameworks/sproutcore/frameworks/application/PLACEHOLDER +0 -0
  839. data/spec/fixtures/real_world/frameworks/sproutcore/frameworks/costello/core.js +0 -0
  840. data/spec/fixtures/real_world/frameworks/sproutcore/frameworks/data_store/PLACEHOLDER +0 -0
  841. data/spec/fixtures/real_world/frameworks/sproutcore/frameworks/debug/PLACEHOLDER +0 -0
  842. data/spec/fixtures/real_world/frameworks/sproutcore/frameworks/desktop/PLACEHOLDER +0 -0
  843. data/spec/fixtures/real_world/frameworks/sproutcore/frameworks/empty_theme/PLACEHOLDER +0 -0
  844. data/spec/fixtures/real_world/frameworks/sproutcore/frameworks/foundation/PLACEHOLDER +0 -0
  845. data/spec/fixtures/real_world/frameworks/sproutcore/frameworks/mobile/PLACEHOLDER +0 -0
  846. data/spec/fixtures/real_world/frameworks/sproutcore/frameworks/qunit/PLACEHOLDER +0 -0
  847. data/spec/fixtures/real_world/frameworks/sproutcore/frameworks/uploader/PLACEHOLDER +0 -0
  848. data/spec/fixtures/real_world/frameworks/sproutcore/french.lproj/french-resource.js +0 -0
  849. data/spec/fixtures/real_world/frameworks/sproutcore/french.lproj/strings.js +0 -1
  850. data/spec/fixtures/real_world/frameworks/sproutcore/german.lproj/german-resource.js +0 -0
  851. data/spec/fixtures/real_world/frameworks/sproutcore/german.lproj/strings.js +0 -0
  852. data/spec/fixtures/real_world/frameworks/sproutcore/has_require.js +0 -4
  853. data/spec/fixtures/real_world/frameworks/sproutcore/lib/index.html +0 -1
  854. data/spec/fixtures/real_world/frameworks/sproutcore/no_require.js +0 -1
  855. data/spec/fixtures/real_world/frameworks/sproutcore/protocols/sample.js +0 -0
  856. data/spec/fixtures/real_world/frameworks/sproutcore/sc_resource.js +0 -6
  857. data/spec/fixtures/real_world/frameworks/sproutcore/tests/nested/sample1.js +0 -0
  858. data/spec/fixtures/real_world/frameworks/sproutcore/tests/nested/sample2.js +0 -0
  859. data/spec/fixtures/real_world/frameworks/sproutcore/tests/sample.js +0 -0
  860. data/spec/fixtures/real_world/frameworks/sproutcore/tests/sample.rhtml +0 -1
  861. data/spec/fixtures/real_world/frameworks/sproutcore/themes/standard_theme/README +0 -0
  862. data/spec/fixtures/real_world/frameworks/sproutcore/views/view.js +0 -1
  863. data/spec/fixtures/real_world/generators/sample_custom/Buildfile +0 -0
  864. data/spec/fixtures/recursive_project/Buildfile +0 -8
  865. data/spec/fixtures/recursive_project/frameworks/sproutcore/frameworks/costello/PLACEHOLDER +0 -0
  866. data/spec/lib/builders/combine_spec.rb +0 -67
  867. data/spec/lib/builders/html_spec.rb +0 -577
  868. data/spec/lib/builders/javascript_spec.rb +0 -81
  869. data/spec/lib/builders/sass_spec.rb +0 -43
  870. data/spec/lib/builders/spec_helper.rb +0 -30
  871. data/spec/lib/builders/strings_spec.rb +0 -52
  872. data/spec/lib/builders/stylesheet_spec.rb +0 -63
  873. data/spec/lib/builders/test_index_spec.rb +0 -44
  874. data/spec/lib/builders/test_spec.rb +0 -135
  875. data/spec/lib/buildfile/config_for_spec.rb +0 -81
  876. data/spec/lib/buildfile/define_spec.rb +0 -59
  877. data/spec/lib/buildfile/dup_spec.rb +0 -65
  878. data/spec/lib/buildfile/invoke_spec.rb +0 -130
  879. data/spec/lib/buildfile/load_spec.rb +0 -49
  880. data/spec/lib/buildfile/task/dup_spec.rb +0 -55
  881. data/spec/lib/buildfile/task_defined_spec.rb +0 -17
  882. data/spec/lib/buildfile_commands/build_task_spec.rb +0 -19
  883. data/spec/lib/buildfile_commands/config_spec.rb +0 -97
  884. data/spec/lib/buildfile_commands/import_spec.rb +0 -17
  885. data/spec/lib/buildfile_commands/namespace_spec.rb +0 -18
  886. data/spec/lib/buildfile_commands/proxies_spec.rb +0 -38
  887. data/spec/lib/buildfile_commands/replace_task_spec.rb +0 -29
  888. data/spec/lib/buildfile_commands/task_spec.rb +0 -36
  889. data/spec/lib/helpers/packing_optimizer/optimize_spec.rb +0 -26
  890. data/spec/lib/models/hash_struct/deep_clone_spec.rb +0 -27
  891. data/spec/lib/models/hash_struct/has_options_spec.rb +0 -32
  892. data/spec/lib/models/hash_struct/hash_spec.rb +0 -64
  893. data/spec/lib/models/hash_struct/merge_spec.rb +0 -26
  894. data/spec/lib/models/hash_struct/method_missing.rb +0 -41
  895. data/spec/lib/models/manifest/add_entry_spec.rb +0 -36
  896. data/spec/lib/models/manifest/add_transform_spec.rb +0 -90
  897. data/spec/lib/models/manifest/build_spec.rb +0 -78
  898. data/spec/lib/models/manifest/entry_for_spec.rb +0 -94
  899. data/spec/lib/models/manifest/find_entry.rb +0 -84
  900. data/spec/lib/models/manifest/prepare_spec.rb +0 -62
  901. data/spec/lib/models/manifest_entry/cacheable_url_spec.rb +0 -31
  902. data/spec/lib/models/manifest_entry/prepare_spec.rb +0 -54
  903. data/spec/lib/models/project/add_target_spec.rb +0 -44
  904. data/spec/lib/models/project/buildfile_spec.rb +0 -35
  905. data/spec/lib/models/project/find_targets_for_spec.rb +0 -77
  906. data/spec/lib/models/project/load_nearest_project_spec.rb +0 -23
  907. data/spec/lib/models/project/target_for_spec.rb +0 -33
  908. data/spec/lib/models/project/targets_spec.rb +0 -62
  909. data/spec/lib/models/target/compute_build_number_spec.rb +0 -125
  910. data/spec/lib/models/target/config_spec.rb +0 -30
  911. data/spec/lib/models/target/expand_required_targets_spec.rb +0 -48
  912. data/spec/lib/models/target/installed_languages_spec.rb +0 -47
  913. data/spec/lib/models/target/lproj_for_spec.rb +0 -38
  914. data/spec/lib/models/target/manifest_for_spec.rb +0 -42
  915. data/spec/lib/models/target/parent_target_spec.rb +0 -21
  916. data/spec/lib/models/target/prepare_spec.rb +0 -53
  917. data/spec/lib/models/target/required_targets_spec.rb +0 -119
  918. data/spec/lib/models/target/target_for_spec.rb +0 -56
  919. data/spec/lib/tools/build_number_spec.rb +0 -28
  920. data/spec/lib/tools/gen_spec.rb +0 -207
  921. data/spec/lib/tools/tools_spec.rb +0 -78
  922. data/spec/spec_helper.rb +0 -138
  923. data/sproutcore-abbot.gemspec +0 -640
  924. data/vendor/jsdoc/templates/jsdoc/allclasses.tmpl +0 -17
  925. data/vendor/jsdoc/templates/jsdoc/allfiles.tmpl +0 -56
  926. data/vendor/jsdoc/templates/jsdoc/class.tmpl +0 -487
  927. data/vendor/jsdoc/templates/jsdoc/index.tmpl +0 -38
  928. data/vendor/jsdoc/templates/jsdoc/symbol.tmpl +0 -35
  929. data/vendor/jsdoc/templates/sproutcore/allclasses.tmpl +0 -0
  930. data/vendor/jsdoc/templates/sproutcore/allfiles.tmpl +0 -56
  931. data/vendor/jsdoc/templates/sproutcore/class.tmpl +0 -674
  932. data/vendor/jsdoc/templates/sproutcore/index.tmpl +0 -55
  933. data/vendor/jsdoc/templates/sproutcore/symbol.tmpl +0 -35
@@ -0,0 +1,287 @@
1
+ // ==========================================================================
2
+ // Project: SproutCore - JavaScript Application Framework
3
+ // Copyright: ©2006-2009 Sprout Systems, Inc. and contributors.
4
+ // Portions ©2008-2009 Apple, Inc. All rights reserved.
5
+ // License: Licened under MIT license (see license.js)
6
+ // ==========================================================================
7
+
8
+ /**
9
+ @class
10
+
11
+ A RecordArray wraps an array of storeKeys, converting them into materialized
12
+ record objects from the owner store on demand. A Record Array instance is
13
+ usually returned when you call SC.Store#findAll() or SC.Store#recordsFor().
14
+
15
+ @extends SC.Object
16
+ @extends SC.Enumerable
17
+ @extends SC.Array
18
+ @since SproutCore 1.0
19
+ */
20
+
21
+ SC.RecordArray = SC.Object.extend(SC.Enumerable, SC.Array,
22
+ /** @scope SC.RecordArray.prototype */ {
23
+
24
+ /**
25
+ The store that owns this record array. All record arrays must have a
26
+ store to function properly.
27
+
28
+ @property {SC.Store}
29
+ */
30
+ store: null,
31
+
32
+ /**
33
+ SC.Array object that will provide the store keys for the array. The
34
+ record array will register itself as an observer for this array.
35
+
36
+ @property {SC.Array}
37
+ */
38
+ storeKeys: null,
39
+
40
+ /**
41
+ SC.Query object that is set if record array is based on a query.
42
+ Whenever the store keys content change, the SC.Query will be
43
+ reapplied so that only matching storeKeys are set on the record
44
+ array.
45
+
46
+ @property {SC.Query}
47
+ */
48
+ queryKey: null,
49
+
50
+ /**
51
+ The current load state of the RecordArray. If the storeKeys has a state
52
+ property, then this property will return that value. Otherwise it returns
53
+ SC.Record.READY.
54
+ */
55
+ state: function() {
56
+ var storeKeys = this.get('storeKeys'),
57
+ ret = (storeKeys && !SC.none(storeKeys.state)) ? storeKeys.get('state') : null;
58
+ return ret ? ret : SC.Record.READY;
59
+ }.property().cacheable(),
60
+
61
+ /** @private
62
+ Cache of records returned from objectAt() so they don't need to
63
+ be unneccesarily materialized.
64
+
65
+ @property {SC.Query}
66
+ */
67
+ _records: null,
68
+
69
+ // ..........................................................
70
+ // ARRAY PRIMITIVES
71
+ //
72
+
73
+ /**
74
+ Returned length is a pass-through to the storeKeys array.
75
+ */
76
+ length: function() {
77
+ var storeKeys = this.get('storeKeys');
78
+ return storeKeys ? storeKeys.get('length') : 0;
79
+ }.property('storeKeys').cacheable(),
80
+
81
+ /**
82
+ Looks up the store key in the store keys array and materializes a
83
+ records.
84
+
85
+ @param {Number} idx index of the object
86
+ @return {SC.Record} materialized record
87
+ */
88
+ objectAt: function(idx) {
89
+ var recs = this._records,
90
+ storeKeys = this.get('storeKeys'),
91
+ store = this.get('store'),
92
+ storeKey, ret ;
93
+
94
+ if (!storeKeys || !store) return undefined; // nothing to do
95
+ if (recs && (ret=recs[idx])) return ret ; // cached
96
+
97
+ // not in cache, materialize
98
+ if (!recs) this._records = recs = [] ; // create cache
99
+ storeKey = storeKeys.objectAt(idx);
100
+
101
+ if (storeKey) {
102
+ // if record is not loaded already, then ask the data source to
103
+ // retrieve it
104
+ if (store.readStatus(storeKey) === SC.Record.EMPTY) {
105
+ store.retrieveRecord(null, null, storeKey);
106
+ }
107
+ recs[idx] = ret = store.materializeRecord(storeKey);
108
+ }
109
+ return ret ;
110
+ },
111
+
112
+ /**
113
+ Pass through to the underlying array. The passed in objects must be
114
+ records, which can be converted to storeKeys.
115
+
116
+ @param {Number} idx start index
117
+ @param {Number} amt end index
118
+ @param {SC.RecordArray} recs to replace with records
119
+ @return {SC.RecordArray} 'this' after replace
120
+ */
121
+ replace: function(idx, amt, recs) {
122
+ var storeKeys = this.get('storeKeys'),
123
+ len = recs ? (recs.get ? recs.get('length') : recs.length) : 0,
124
+ i, keys;
125
+
126
+ if (!storeKeys) throw "storeKeys required";
127
+
128
+ // map to store keys
129
+ keys = [] ;
130
+ for(i=0;i<len;i++) keys[i] = recs.objectAt(i).get('storeKey');
131
+
132
+ // pass along - if allowed, this should trigger the content observer
133
+ storeKeys.replace(idx, amt, keys);
134
+ return this;
135
+ },
136
+
137
+ /**
138
+ Called to refresh the query that is attached to this record array.
139
+ This will force the query to evaluated again against the store.
140
+ */
141
+ refreshQuery: function() {
142
+ var query = this.get('queryKey');
143
+
144
+ if(query) {
145
+ var recordType = query.get('recordType');
146
+ var storeKeys = this.get('store').storeKeysFor(recordType);
147
+
148
+ var recordTypes = SC.Set.create();
149
+ recordTypes.push(recordType);
150
+
151
+ // clear existing storeKeys, start over by applying all storekeys for
152
+ // this recordType
153
+ this.storeKeys = [];
154
+ this.applyQuery(storeKeys, recordTypes);
155
+ }
156
+
157
+ },
158
+
159
+ /**
160
+ Apply the SC.Query again. This is invoked when new records are loaded
161
+ or changed in the store (or directly on the array with .replace() ) and
162
+ and when we need to refresh all SC.Query 'based' record arrays accordingly.
163
+
164
+ @param {Array} storeKeys to evaluate against the query
165
+ @param {SC.Set} recordTypes set of record types that changed
166
+ @param {Boolean} notify to send length notifyPropertyChange()
167
+ */
168
+ applyQuery: function(changedStoreKeys, recordTypes, notify) {
169
+ var newStoreKeys = this.get('storeKeys'), inChangedStoreKeys,
170
+ inMatchingStoreKeys, idx, len, storeKey, queryKey = this.get('queryKey'),
171
+ store = this.get('store');
172
+
173
+ // first check if these changes include any of the record types
174
+ if(recordTypes && queryKey.recordType && !recordTypes.contains(queryKey.recordType)) return;
175
+
176
+ var matchingStoreKeys = SC.Query.containsStoreKeys(queryKey,
177
+ changedStoreKeys, store);
178
+
179
+ // Will iterate through all changed store keys and make sure they:
180
+ // 1. Are added if they are new AND match the query
181
+ // 2. Are removed if they exist and do NOT match the query
182
+ for(idx=0,len=changedStoreKeys.length;idx<len;idx++) {
183
+ storeKey = changedStoreKeys[idx];
184
+ inMatchingStoreKeys = (matchingStoreKeys &&
185
+ matchingStoreKeys.indexOf(storeKey)!==-1) ? YES: NO;
186
+ var inRecArray = this.storeKeys.indexOf(storeKey)!==-1 ? YES : NO;
187
+
188
+ if(inMatchingStoreKeys && !inRecArray) {
189
+ newStoreKeys.push(storeKey);
190
+ }
191
+ else if(!inMatchingStoreKeys && inRecArray) {
192
+ newStoreKeys.removeObject(storeKey);
193
+ }
194
+
195
+ }
196
+
197
+ SC.Query.orderStoreKeys(newStoreKeys, queryKey, store);
198
+ // clear cache
199
+ this._records = null;
200
+
201
+ this.storeKeys = newStoreKeys.addObserver('[]', this, this._storeKeysContentDidChange);
202
+ if(notify) this.notifyPropertyChange('length');
203
+ },
204
+
205
+ /**
206
+ Will call findAll() on the store, which allows for chaining findAll
207
+ statements. Note that chaining findAll() will not notify the data
208
+ source (only the initial findAll will).
209
+
210
+ @param {SC.Query} queryKey a SC.Query object
211
+ @returns {SC.RecordArray}
212
+ */
213
+
214
+ findAll: function(queryKey) {
215
+ return this.get('store').findAll(queryKey, null, this);
216
+ },
217
+
218
+ // ..........................................................
219
+ // INTERNAL SUPPORT
220
+ //
221
+
222
+ /** @private
223
+ Invoked whenever the storeKeys array changes. Observes changes.
224
+ */
225
+ _storeKeysDidChange: function() {
226
+
227
+ var storeKeys = this.get('storeKeys');
228
+
229
+ var prev = this._prevStoreKeys,
230
+ f = this._storeKeysContentDidChange,
231
+ fs = this._storeKeysStateDidChange;
232
+
233
+ if (storeKeys === prev) return this; // nothing to do
234
+
235
+ if (prev) {
236
+ prev.removeObserver('[]', this, f);
237
+ prev.removeObserver('state', this, fs);
238
+ }
239
+
240
+ this._prevStoreKeys = storeKeys;
241
+
242
+ if (storeKeys) {
243
+ storeKeys.addObserver('[]', this, f);
244
+ storeKeys.addObserver('state', this, fs);
245
+ }
246
+
247
+ var rev = (storeKeys) ? storeKeys.propertyRevision : -1 ;
248
+ this._storeKeysContentDidChange(storeKeys, '[]', storeKeys, rev);
249
+
250
+ }.observes('storeKeys'),
251
+
252
+ /** @private
253
+ Invoked whenever the state property of the storeKeys change.
254
+ */
255
+ _storeKeysStateDidChange: function() {
256
+ this.notifyPropertyChange('state');
257
+ },
258
+
259
+ /** @private
260
+ Invoked whenever the content of the storeKeys array changes. This will
261
+ dump any cached record lookup and then notify that the enumerable content
262
+ has changed.
263
+ */
264
+ _storeKeysContentDidChange: function(target, key, value, rev) {
265
+ this._records = null ; // clear cache
266
+ // if this record array is based on a queryKey reapply the
267
+ // the query before setting the storeKeys to ensure it always conforms
268
+
269
+ if(SC.instanceOf(this.queryKey, SC.Query)) {
270
+ this.storeKeys = SC.Query.containsStoreKeys(this.queryKey, value, this.store);
271
+ this.notifyPropertyChange('length');
272
+ }
273
+
274
+ this.beginPropertyChanges()
275
+ .notifyPropertyChange('length')
276
+ .enumerableContentDidChange()
277
+ .endPropertyChanges();
278
+ },
279
+
280
+ init: function() {
281
+ sc_super();
282
+ this._storeKeysDidChange();
283
+ }
284
+
285
+
286
+ });
287
+
@@ -0,0 +1,2007 @@
1
+ // ==========================================================================
2
+ // Project: SproutCore - JavaScript Application Framework
3
+ // Copyright: ©2006-2009 Sprout Systems, Inc. and contributors.
4
+ // Portions ©2008-2009 Apple, Inc. All rights reserved.
5
+ // License: Licened under MIT license (see license.js)
6
+ // ==========================================================================
7
+
8
+ sc_require('models/record');
9
+
10
+ /**
11
+ @class
12
+
13
+
14
+ The Store is where you can find all of your dataHashes. Stores can be
15
+ chained for editing purposes and committed back one chain level at a time
16
+ all the way back to a persistent data source.
17
+
18
+ Every application you create should generally have its own store objects.
19
+ Once you create the store, you will rarely need to work with the store
20
+ directly except to retrieve records and collections.
21
+
22
+ Internally, the store will keep track of changes to your json data hashes
23
+ and manage syncing those changes with your data source. A data source may
24
+ be a server, local storage, or any other persistent code.
25
+
26
+ @extends SC.Object
27
+ @since SproutCore 1.0
28
+ */
29
+ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
30
+
31
+ /**
32
+ An array of all the chained stores that current rely on the receiver
33
+ store.
34
+
35
+ @property {Array}
36
+ */
37
+ nestedStores: null,
38
+
39
+ /**
40
+ The data source is the persistent storage that will provide data to the
41
+ store and save changes. You normally will set your data source when you
42
+ first create your store in your application.
43
+ */
44
+ dataSource: null,
45
+
46
+ /**
47
+ This type of store is not nested.
48
+ */
49
+ isNested: NO,
50
+
51
+ /**
52
+ This type of store is not nested.
53
+ */
54
+ commitRecordsAutomatically: NO,
55
+
56
+ // ..........................................................
57
+ // DATA SOURCE SUPPORT
58
+ //
59
+
60
+ /**
61
+ Convenience method. Sets the current data source to the passed property.
62
+ This will also set the store property on the dataSource to the receiver.
63
+
64
+ If you are using this from the core.js method of your app, you may need to
65
+ just pass a string naming your data source class. If this is the case,
66
+ then your data source will be instantiated the first time it is requested.
67
+
68
+ @param {SC.DataSource|String} dataSource the data source
69
+ @returns {SC.Store} receiver
70
+ */
71
+ from: function(dataSource) {
72
+ this.set('dataSource', dataSource);
73
+ return this ;
74
+ },
75
+
76
+ // lazily convert data source to real object
77
+ _getDataSource: function() {
78
+ var ret = this.get('dataSource');
79
+ if (typeof ret === SC.T_STRING) {
80
+ ret = SC.objectForPropertyPath(ret);
81
+ if (ret) ret = ret.create();
82
+ if (ret) this.set('dataSource', ret);
83
+ }
84
+ return ret;
85
+ },
86
+
87
+ /**
88
+ Convenience method. Creates a CascadeDataSource with the passed
89
+ data source arguments and sets the CascadeDataSource as the data source
90
+ for the receiver.
91
+
92
+ @param {SC.DataSource...} dataSource one or more data source arguments
93
+ @returns {SC.Store} reciever
94
+ */
95
+ cascade: function(dataSource) {
96
+ var dataSources = SC.A(arguments) ;
97
+ dataSource = SC.CascadeDataSource.create({
98
+ dataSources: dataSources
99
+ });
100
+ return this.from(dataSource);
101
+ },
102
+
103
+ // ..........................................................
104
+ // STORE CHAINING
105
+ //
106
+
107
+ /**
108
+ Returns a new nested store instance that can be used to buffer changes
109
+ until you are ready to commit them. When you are ready to commit your
110
+ changes, call commitChanges() or destroyChanges() and then destroy() when
111
+ you are finished with the chained store altogether.
112
+
113
+ {{{
114
+ store = MyApp.store.chain();
115
+ .. edit edit edit
116
+ store.commitChanges().destroy();
117
+ }}}
118
+
119
+ @param {Hash} attrs optional attributes to set on new store
120
+ @returns {SC.NestedStore} new nested store chained to receiver
121
+ */
122
+ chain: function(attrs) {
123
+ if (!attrs) attrs = {};
124
+ attrs.parentStore = this;
125
+
126
+ var ret = SC.NestedStore.create(attrs),
127
+ nested = this.nestedStores;
128
+
129
+ if (!nested) nested = this.nestedStores = [];
130
+ nested.push(ret);
131
+ return ret ;
132
+ },
133
+
134
+ /** @private
135
+
136
+ Called by a nested store just before it is destroyed so that the parent
137
+ can remove the store from its list of nested stores.
138
+
139
+ @returns {SC.Store} receiver
140
+ */
141
+ willDestroyNestedStore: function(nestedStore) {
142
+ if (this.nestedStores) {
143
+ this.nestedStores.removeObject(nestedStore);
144
+ }
145
+ return this ;
146
+ },
147
+
148
+ /**
149
+ Used to determine if a nested store belongs directly or indirectly to the
150
+ receiver.
151
+
152
+ @param {SC.Store} store store instance
153
+ @returns {Boolean} YES if belongs
154
+ */
155
+ hasNestedStore: function(store) {
156
+ while(store && (store !== this)) store = store.get('parentStore');
157
+ return store === this ;
158
+ },
159
+
160
+ // ..........................................................
161
+ // SHARED DATA STRUCTURES
162
+ //
163
+
164
+ /** @private
165
+ JSON data hashes indexed by store key.
166
+
167
+ *IMPORTANT: Property is not observable*
168
+
169
+ Shared by a store and its child stores until you make edits to it.
170
+
171
+ @property {Hash}
172
+ */
173
+ dataHashes: null,
174
+
175
+ /** @private
176
+ The current status of a data hash indexed by store key.
177
+
178
+ *IMPORTANT: Property is not observable*
179
+
180
+ Shared by a store and its child stores until you make edits to it.
181
+
182
+ @property {Hash}
183
+ */
184
+ statuses: null,
185
+
186
+ /** @private
187
+ This array contains the revisions for the attributes indexed by the
188
+ storeKey.
189
+
190
+ *IMPORTANT: Property is not observable*
191
+
192
+ Revisions are used to keep track of when an attribute hash has been
193
+ changed. A store shares the revisions data with its parent until it
194
+ starts to make changes to it.
195
+
196
+ @property {Hash}
197
+ */
198
+ revisions: null,
199
+
200
+ /** @private
201
+ Stores three sets of record property changes (storeKeys, statuses
202
+ and recordTypes) which is used when _notifyRecordPropertyChange is
203
+ called. Makes it possible to only execute once at the end of
204
+ the runloop.
205
+
206
+ @property {Hash}
207
+ */
208
+ recordPropertyChanges: {
209
+ storeKeys: [],
210
+ records: [],
211
+ statusOnly: []
212
+ },
213
+
214
+ /**
215
+ Array indicates whether a data hash is possibly in use by an external
216
+ record for editing. If a data hash is editable then it may be modified
217
+ at any time and therefore chained stores may need to clone the
218
+ attributes before keeping a copy of them.
219
+
220
+ Note that this is kept as an array because it will be stored as a dense
221
+ array on some browsers, making it faster.
222
+
223
+ @property {Array}
224
+ */
225
+ editables: null,
226
+
227
+ /**
228
+ A set of storeKeys that need to be committed back to the data source. If
229
+ you call commitRecords() without passing any other parameters, the keys
230
+ in this set will be committed instead.
231
+
232
+ @property {Hash}
233
+ */
234
+ changelog: null,
235
+
236
+ /**
237
+ A set of SC.RecordArray that have been returned from findAll with an
238
+ SC.Query. These will all be notified with _notifyRecordArraysWithQuery()
239
+ whenever the store changes.
240
+
241
+ @property {Array}
242
+ */
243
+ recordArraysWithQuery: null,
244
+
245
+ // ..........................................................
246
+ // CORE ATTRIBUTE API
247
+ //
248
+ // The methods in this layer work on data hashes in the store. They do not
249
+ // perform any changes that can impact records. Usually you will not need
250
+ // to use these methods.
251
+
252
+ /**
253
+ Returns the current edit status of a storekey. May be one of EDITABLE or
254
+ LOCKED. Used mostly for unit testing.
255
+
256
+ @param {Number} storeKey the store key
257
+ @returns {Number} edit status
258
+ */
259
+ storeKeyEditState: function(storeKey) {
260
+ var editables = this.editables, locks = this.locks;
261
+ return (editables && editables[storeKey]) ? SC.Store.EDITABLE : SC.Store.LOCKED ;
262
+ },
263
+
264
+ /**
265
+ Returns the data hash for the given storeKey. This will also 'lock'
266
+ the hash so that further edits to the parent store will no
267
+ longer be reflected in this store until you reset.
268
+
269
+ @param {Number} storeKey key to retrieve
270
+ @returns {Hash} data hash or null
271
+ */
272
+ readDataHash: function(storeKey) {
273
+ return this.dataHashes[storeKey];
274
+ },
275
+
276
+ /**
277
+ Returns the data hash for the storeKey, cloned so that you can edit
278
+ the contents of the attributes if you like. This will do the extra work
279
+ to make sure that you only clone the attributes one time.
280
+
281
+ If you use this method to modify data hash, be sure to call
282
+ dataHashDidChange() when you make edits to record the change.
283
+
284
+ @param {Number} storeKey the store key to retrieve
285
+ @returns {Hash} the attributes hash
286
+ */
287
+ readEditableDataHash: function(storeKey) {
288
+ // read the value - if there is no hash just return; nothing to do
289
+ var ret = this.dataHashes[storeKey];
290
+ if (!ret) return ret ; // nothing to do.
291
+
292
+ // clone data hash if not editable
293
+ var editables = this.editables;
294
+ if (!editables) editables = this.editables = [];
295
+ if (!editables[storeKey]) {
296
+ editables[storeKey] = 1 ; // use number to store as dense array
297
+ ret = this.dataHashes[storeKey] = SC.clone(ret);
298
+ }
299
+ return ret;
300
+ },
301
+
302
+ /**
303
+ Replaces the data hash for the storeKey. This will lock the data hash and
304
+ mark them as cloned. This will also call dataHashDidChange() for you.
305
+
306
+ Note that the hash you set here must be a different object from the
307
+ original data hash. Once you make a change here, you must also call
308
+ dataHashDidChange() to register the changes.
309
+
310
+ If the data hash does not yet exist in the store, this method will add it.
311
+ Pass the optional status to edit the status as well.
312
+
313
+ @param {Number} storeKey the store key to write
314
+ @param {Hash} hash the new hash
315
+ @param {String} status the new hash status
316
+ @returns {SC.Store} receiver
317
+ */
318
+ writeDataHash: function(storeKey, hash, status) {
319
+
320
+ // update dataHashes and optionally status.
321
+ if (hash) this.dataHashes[storeKey] = hash;
322
+ if (status) this.statuses[storeKey] = status ;
323
+
324
+ // also note that this hash is now editable
325
+ var editables = this.editables;
326
+ if (!editables) editables = this.editables = [];
327
+ editables[storeKey] = 1 ; // use number for dense array support
328
+
329
+ return this ;
330
+ },
331
+
332
+ /**
333
+ Removes the data hash from the store. This does not imply a deletion of
334
+ the record. You could be simply unloading the record. Eitherway,
335
+ removing the dataHash will be synced back to the parent store but not to
336
+ the server.
337
+
338
+ Note that you can optionally pass a new status to go along with this. If
339
+ you do not pass a status, it will change the status to SC.RECORD_EMPTY
340
+ (assuming you just unloaded the record). If you are deleting the record
341
+ you may set it to SC.Record.DESTROYED_CLEAN.
342
+
343
+ Be sure to also call dataHashDidChange() to register this change.
344
+
345
+ @param {Number} storeKey
346
+ @param {String} status optional new status
347
+ @returns {SC.Store} reciever
348
+ */
349
+ removeDataHash: function(storeKey, status) {
350
+ var rev ;
351
+
352
+ // don't use delete -- that will allow parent dataHash to come through
353
+ this.dataHashes[storeKey] = null;
354
+ this.statuses[storeKey] = status || SC.Record.EMPTY;
355
+ rev = this.revisions[storeKey] = this.revisions[storeKey]; // copy ref
356
+
357
+ // hash is gone and therefore no longer editable
358
+ var editables = this.editables;
359
+ if (editables) editables[storeKey] = 0 ;
360
+
361
+ return this ;
362
+ },
363
+
364
+ /**
365
+ Reads the current status for a storeKey. This will also lock the data
366
+ hash. If no status is found, returns SC.RECORD_EMPTY.
367
+
368
+ @param {Number} storeKey the store key
369
+ @returns {String} status
370
+ */
371
+ readStatus: function(storeKey) {
372
+ // use readDataHash to handle optimistic locking. this could be inlined
373
+ // but for now this minimized copy-and-paste code.
374
+ this.readDataHash(storeKey);
375
+ return this.statuses[storeKey] || SC.Record.EMPTY;
376
+ },
377
+
378
+ /**
379
+ Writes the current status for a storeKey.
380
+
381
+ @param {Number} storeKey the store key
382
+ @param {String} newStatus the new status
383
+ @returns {SC.Store} receiver
384
+ */
385
+ writeStatus: function(storeKey, newStatus) {
386
+ // use writeDataHash for now to handle optimistic lock. maximize code
387
+ // reuse.
388
+ return this.writeDataHash(storeKey, null, newStatus);
389
+ },
390
+
391
+ /**
392
+ Call this method whenever you modify some editable data hash to register
393
+ with the Store that the attribute values have actually changed. This will
394
+ do the book-keeping necessary to track the change across stores including
395
+ managing locks.
396
+
397
+ @param {Number|Array} storeKeys one or more store keys that changed
398
+ @param {Number} rev optional new revision number. normally leave null
399
+ @param {Boolean} statusOnly (optional) YES if only status changed
400
+ @returns {SC.Store} receiver
401
+ */
402
+ dataHashDidChange: function(storeKeys, rev, statusOnly) {
403
+
404
+ // update the revision for storeKey. Use generateStoreKey() because that
405
+ // gaurantees a universally (to this store hierarchy anyway) unique
406
+ // key value.
407
+ if (!rev) rev = SC.Store.generateStoreKey();
408
+ var isArray, len, idx, storeKey;
409
+
410
+ isArray = SC.typeOf(storeKeys) === SC.T_ARRAY;
411
+ if (isArray) {
412
+ len = storeKeys.length;
413
+ } else {
414
+ len = 1;
415
+ storeKey = storeKeys;
416
+ }
417
+
418
+ SC.RunLoop.begin();
419
+ for(idx=0;idx<len;idx++) {
420
+ if (isArray) storeKey = storeKeys[idx];
421
+ this.revisions[storeKey] = rev;
422
+ this._notifyRecordPropertyChange(storeKey, statusOnly);
423
+ }
424
+
425
+ SC.RunLoop.end();
426
+
427
+ return this ;
428
+ },
429
+
430
+ /** @private
431
+ Will push all changes to a the recordPropertyChanges property
432
+ and execute flushRecordChanges() once at the end of the runloop.
433
+ */
434
+ _notifyRecordPropertyChange: function(storeKey, statusOnly) {
435
+
436
+ var records = this.records, rec, editState;
437
+
438
+ // pass along to nested stores
439
+ var nestedStores = this.get('nestedStores'), len, idx, store, status;
440
+ var K = SC.Store;
441
+ len = nestedStores ? nestedStores.length : 0 ;
442
+ for(idx=0;idx<len;idx++) {
443
+ store = nestedStores[idx];
444
+ status = store.readStatus(storeKey);
445
+ editState = store.storeKeyEditState(storeKey);
446
+
447
+ // when store needs to propagate out changes in the parent store
448
+ // to nested stores
449
+ if(editState!==K.INHERITED && (status & SC.Record.BUSY)) {
450
+ // make sure nested store does not have any changes before resetting
451
+ if(store.get('hasChanges')) throw K.CHAIN_CONFLICT_ERROR;
452
+ store.reset();
453
+ }
454
+
455
+ if(store.storeKeyEditState(storeKey) === K.INHERITED) {
456
+ store._notifyRecordPropertyChange(storeKey, statusOnly);
457
+ }
458
+ }
459
+
460
+ // schedule
461
+ this.recordPropertyChanges.storeKeys.push(storeKey);
462
+
463
+ if (records && (rec=records[storeKey])) {
464
+ this.recordPropertyChanges.records.push(storeKey);
465
+ if(statusOnly) {
466
+ this.recordPropertyChanges.statusOnly.push(storeKey);
467
+ }
468
+ }
469
+
470
+ this._flushRecordChanges();
471
+
472
+ return this;
473
+ },
474
+
475
+ /** @private
476
+ Will notify any record instances of the property change at the end of
477
+ the run loop. Also notifies any inherited record instances as well.
478
+
479
+ Will also notify any record arrays with queries to refresh based on
480
+ the new/changed store keys.
481
+ */
482
+
483
+ _flushRecordChanges: function() {
484
+ var storeKeys = this.recordPropertyChanges.storeKeys,
485
+ statusOnly = this.recordPropertyChanges.statusOnly,
486
+ records = this.recordPropertyChanges.records, rec,
487
+ recordType, recordTypes = SC.Set.create(), status, idx, len, storeKey;
488
+
489
+ for(idx=0,len=storeKeys.length;idx<len;idx++) {
490
+ storeKey = storeKeys[idx];
491
+
492
+ if(records.indexOf(storeKey)!==-1) {
493
+ status = statusOnly.indexOf(storeKey)!==-1 ? YES: NO;
494
+ rec = this.records[storeKey];
495
+ rec.storeDidChangeProperties(status);
496
+ // remove it so we don't trigger this twice
497
+ records.removeObject(storeKey);
498
+ }
499
+
500
+ recordType = SC.Store.recordTypeFor(storeKey);
501
+ if(!recordTypes.contains(recordType)) {
502
+ recordTypes.push(recordType);
503
+ }
504
+
505
+ }
506
+
507
+ this._notifyRecordArraysWithQuery(storeKeys, recordTypes);
508
+
509
+ // reset for next run loop
510
+ this.recordPropertyChanges.storeKeys = [];
511
+ this.recordPropertyChanges.records = [];
512
+ this.recordPropertyChanges.statusOnly = [];
513
+ },
514
+
515
+ /** @private
516
+ Will ask all record arrays that have been returned from findAll
517
+ with an SC.Query to reapply their query with the new storeKeys
518
+
519
+ @param {SC.IndexSet} storeKeys set of storeKeys that changed
520
+ @param {SC.Set} recordTypes
521
+ */
522
+
523
+ _notifyRecordArraysWithQuery: function(storeKeys, recordTypes) {
524
+ var recordArrays = this.recordArraysWithQuery;
525
+ if(!recordArrays) return;
526
+
527
+ for(var idx=0, len=recordArrays.length;idx<len;idx++) {
528
+ var recArray = recordArrays[idx];
529
+ // if this record array still exists, reapply the query
530
+ if(recArray) recArray.applyQuery(storeKeys, recordTypes, YES);
531
+ }
532
+ },
533
+
534
+ /**
535
+ Resets the store content. This will clear all internal data for all
536
+ records, resetting them to an EMPTY state. You generally do not want
537
+ to call this method yourself, though you may override it.
538
+
539
+ @returns {SC.Store} receiver
540
+ */
541
+ reset: function() {
542
+
543
+ // create a new empty data store
544
+ this.dataHashes = {} ;
545
+ this.revisions = {} ;
546
+ this.statuses = {} ;
547
+
548
+ // also reset temporary objects
549
+ this.chainedChanges = this.locks = this.editables = null;
550
+ this.changelog = null ;
551
+
552
+ var records = this.records, storeKey;
553
+ if (records) {
554
+ SC.RunLoop.begin();
555
+ for(storeKey in records) {
556
+ if (!records.hasOwnProperty(storeKey)) continue ;
557
+ this._notifyRecordPropertyChange(storeKey, NO);
558
+ }
559
+ SC.RunLoop.end();
560
+ }
561
+
562
+ this.set('hasChanges', NO);
563
+ },
564
+
565
+ /** @private
566
+ Called by a nested store on a parent store to commit any changes from the
567
+ store. This will copy any changed dataHashes as well as any persistant
568
+ change logs.
569
+
570
+ If the parentStore detects a conflict with the optimistic locking, it will
571
+ raise an exception before it makes any changes. If you pass the
572
+ force flag then this detection phase will be skipped and the changes will
573
+ be applied even if another resource has modified the store in the mean
574
+ time.
575
+
576
+ @param {SC.Store} nestedStore the child store
577
+ @param {Array} changes the array of changed store keys
578
+ @param {Boolean} force
579
+ @returns {SC.Store} receiver
580
+ */
581
+ commitChangesFromNestedStore: function(nestedStore, changes, force) {
582
+ // first, check for optimistic locking problems
583
+ if (!force) this._verifyLockRevisions(changes, nestedStore.locks);
584
+
585
+ // OK, no locking issues. So let's just copy them changes.
586
+ // get local reference to values.
587
+ var len = changes.length, i, storeKey, myDataHashes, myStatuses,
588
+ myEditables, myRevisions, chDataHashes, chStatuses, chRevisions;
589
+
590
+ myRevisions = this.revisions ;
591
+ myDataHashes = this.dataHashes;
592
+ myStatuses = this.statuses;
593
+ myEditables = this.editables ;
594
+
595
+ // setup some arrays if needed
596
+ if (!myEditables) myEditables = this.editables = [] ;
597
+
598
+ chDataHashes = nestedStore.dataHashes;
599
+ chRevisions = nestedStore.revisions ;
600
+ chStatuses = nestedStore.statuses;
601
+
602
+ SC.RunLoop.begin();
603
+ for(i=0;i<len;i++) {
604
+ storeKey = changes[i];
605
+
606
+ // now copy changes
607
+ myDataHashes[storeKey] = chDataHashes[storeKey];
608
+ myStatuses[storeKey] = chStatuses[storeKey];
609
+ myRevisions[storeKey] = chRevisions[storeKey];
610
+
611
+ myEditables[storeKey] = 0 ; // always make dataHash no longer editable
612
+
613
+ this._notifyRecordPropertyChange(storeKey, NO);
614
+ }
615
+ SC.RunLoop.end();
616
+
617
+ // add any records to the changelog for commit handling
618
+ var myChangelog = this.changelog, chChangelog = nestedStore.changelog;
619
+ if (chChangelog) {
620
+ if (!myChangelog) myChangelog = this.changelog = SC.Set.create();
621
+ myChangelog.addEach(chChangelog);
622
+ }
623
+ this.changelog = myChangelog;
624
+
625
+ return this ;
626
+ },
627
+
628
+ /** @private
629
+ Verifies that the passed lock revisions match the current revisions
630
+ in the receiver store. If the lock revisions do not match, then the
631
+ store is in a conflict and an exception will be raised.
632
+
633
+ @param {Array} changes set of changes we are trying to apply
634
+ @param {SC.Set} locks the locks to verify
635
+ @returns {SC.Store} receiver
636
+ */
637
+ _verifyLockRevisions: function(changes, locks) {
638
+ var len = changes.length, revs = this.revisions, i, storeKey, lock, rev ;
639
+ if (locks && revs) {
640
+ for(i=0;i<len;i++) {
641
+ storeKey = changes[i];
642
+ lock = locks[storeKey] || 1;
643
+ rev = revs[storeKey] || 1;
644
+
645
+ // if the save revision for the item does not match the current rev
646
+ // the someone has changed the data hash in this store and we have
647
+ // a conflict.
648
+ if (lock < rev) throw SC.Store.CHAIN_CONFLICT_ERROR;
649
+ }
650
+ }
651
+ return this ;
652
+ },
653
+
654
+ // ..........................................................
655
+ // HIGH-LEVEL RECORD API
656
+ //
657
+
658
+ /**
659
+ Finds a record instance with the specified recordType and id, returning
660
+ the record instance. If no matching record could be found, asks the
661
+ data source to retrieve the record. If the data source cannot retrieve
662
+ the record, returns null.
663
+
664
+ Note that if you try to find a record id that does not exist in memory,
665
+ a dataSource may load it from the server. In this case, this method will
666
+ return a record instance with a status of SC.Record.BUSY_LOADING to indicate
667
+ that it is still fetching the data from the server.
668
+
669
+ You can also pass YES to the isRefresh parameter which will make sure to
670
+ always go back to the data source so that you can go back to refresh the
671
+ record that is currently in the store. In that case, the record will
672
+ get the SC.Record.BUSY_REFRESH status until server has responded and
673
+ store is refreshed.
674
+
675
+ @param {SC.Record|String} recordType the expected record type
676
+ @param {String} id the id to load
677
+ @param {Boolean} isRefresh
678
+ @returns {SC.Record} record instance or null
679
+ */
680
+ find: function(recordType, id, isRefresh) {
681
+ // if recordType is passed as string, find object
682
+ if(SC.typeOf(recordType)===SC.T_STRING) {
683
+ recordType = SC.objectForPropertyPath(recordType);
684
+ }
685
+
686
+ // first attempt to find the record in the local store
687
+ var storeKey = recordType.storeKeyFor(id);
688
+
689
+ if (this.readStatus(storeKey) === SC.Record.EMPTY) {
690
+ storeKey = this.retrieveRecord(recordType, id);
691
+ }
692
+
693
+ // also make sure to reach to the data source to actually
694
+ // retrieveRecord if isRefresh is YES, even if it already exists in store
695
+ if(isRefresh) {
696
+ this.retrieveRecord(recordType, id, null, isRefresh);
697
+ }
698
+
699
+ // now we have the storeKey, materialize the record and return it.
700
+ return storeKey ? this.materializeRecord(storeKey) : null ;
701
+ },
702
+
703
+ /**
704
+ Retrieves records from the persistent store. You should pass in a named
705
+ query that will be understood by one of the persistent stores you have
706
+ configured along with any optional parameters needed by the search.
707
+
708
+ The return value is an SC.RecordArray that may be populated dynamically
709
+ by the server as data becomes available. You can treat this object just
710
+ like any other object that implements SC.Array.
711
+
712
+ h2. Query Keys
713
+
714
+ The kind of fetchKey you pass is generally determined by the type of
715
+ persistent stores you hook up for your application. Most stores, however,
716
+ will accept an SC.Record subclass as the fetchKey. It is up to your data source
717
+ to figure out which storeKeys to return based on the fetchKey. This will return
718
+ a RecordArray matching all instances of that class as is relevant to your
719
+ application, for instance: findAll(MyApp.MyModel)
720
+
721
+ You can also pass an SC.Query object as your fetchKey, for instance:
722
+ var q = SC.Query.create({ recordType: MyApp.MyModel,
723
+ conditions: "firstName = 'John'", orderBy: "lastName ASC"});
724
+ var records = MyApp.store.findAll(q);
725
+
726
+ If an SC.Query is given as fetchKey, the record array created in
727
+ findAll() will automatically update when records are added, changed,
728
+ or removed from the store. When a fetchKey is given, you do not have to
729
+ return anything from the data source as you are from then on delegating
730
+ the responsibility to keep the record array updated to the store.
731
+
732
+ Once you retrieve a RecordArray, you can filter the results even further
733
+ by using the filter() method, which may issue even more specific requests.
734
+
735
+ @param {Object|SC.Query} fetchKey key describing the type of records to
736
+ fetch or a predefined SC.Query object
737
+ @param {Hash} params optional additional parameters to pass along to the
738
+ data source
739
+ @param {SC.RecordArray} recordArray optional if you want to find just
740
+ within a given record array
741
+ @returns {SC.RecordArray} matching set or null if no server handled it
742
+ */
743
+ findAll: function(fetchKey, params, recordArray) {
744
+ var _store = this, source = this._getDataSource(), ret = [], storeKeys,
745
+ sourceRet, cacheKey;
746
+
747
+ if(recordArray) {
748
+ // giving a recordArray will circumvent the data source
749
+ // typically happens when chaining findAll statements
750
+ storeKeys = SC.Query.containsRecords(fetchKey, recordArray, _store);
751
+ }
752
+ else if (source) {
753
+ // call fetch() on the data source.
754
+ sourceRet = source.fetch.call(source, this, fetchKey, params);
755
+ if(SC.typeOf(sourceRet)===SC.T_ARRAY) {
756
+ storeKeys = sourceRet;
757
+ }
758
+ }
759
+
760
+ // if SC.Query returned from data source or no data source was given
761
+ if(!storeKeys && SC.instanceOf(fetchKey, SC.Query)) {
762
+ storeKeys = SC.Query.containsStoreKeys(fetchKey, null, _store);
763
+ }
764
+
765
+ ret = this.recordArrayFromStoreKeys(storeKeys, fetchKey, _store);
766
+ return ret ;
767
+ },
768
+
769
+ /**
770
+ Creates a record array based on passed storeKeys. Will return
771
+ cache if records are already cached, if not store them for reuse.
772
+
773
+ @param {Array} storeKeys added to returned record array
774
+ @param {Object|SC.Query} fetchKey
775
+ @param {SC.Store} _store
776
+ @returns {SC.RecordArray} matching set or null if no server handled it
777
+ */
778
+
779
+ recordArrayFromStoreKeys: function(storeKeys, fetchKey, _store) {
780
+ var ret, isQuery = SC.instanceOf(fetchKey, SC.Query), cacheKey, queryKey;
781
+
782
+ // if an array was provided, see if a wrapper already exists for
783
+ // this store. Otherwise create it
784
+ cacheKey = SC.keyFor('__records__', [SC.guidFor(storeKeys), SC.guidFor(fetchKey)].join('_'));
785
+ ret = this[cacheKey];
786
+ if (!ret) {
787
+ if(isQuery) queryKey = fetchKey;
788
+ ret = SC.RecordArray.create({store: _store, storeKeys: storeKeys, queryKey: queryKey});
789
+
790
+ // store reference to record array if SC.Query so we can notify it
791
+ // when store changes
792
+ if(isQuery) {
793
+ if (!this.recordArraysWithQuery) this.recordArraysWithQuery = [];
794
+ this.recordArraysWithQuery.push(ret);
795
+ }
796
+
797
+ this[cacheKey] = ret ; // save for future reuse.
798
+ }
799
+ return ret;
800
+ },
801
+
802
+ /**
803
+ Array of all records currently in the store with the specified
804
+ type. This method only reflects the actual records loaded into memory and
805
+ therefore is not usually needed at runtime. However you will often use
806
+ this method for testing.
807
+
808
+ @param {SC.Record} recordType the record type
809
+ @returns {SC.Array} array instance - usually SC.RecordArray
810
+ */
811
+ recordsFor: function(recordType) {
812
+ var storeKeys = [],
813
+ storeKeysById = recordType.storeKeysById(),
814
+ id, storeKey, ret;
815
+
816
+ // collect all non-empty store keys
817
+ for(id in storeKeysById) {
818
+ storeKey = storeKeysById[id]; // get the storeKey
819
+ if (this.readStatus(storeKey) !== SC.RECORD_EMPTY) {
820
+ storeKeys.push(storeKey);
821
+ }
822
+ }
823
+
824
+ if (storeKeys.length>0) {
825
+ ret = SC.RecordArray.create({ store: this, storeKeys: storeKeys });
826
+ } else ret = storeKeys; // empty array
827
+ return ret ;
828
+ },
829
+
830
+ _TMP_REC_ATTRS: {},
831
+
832
+ /**
833
+ Given a storeKey, return a materialized record. You will not usually
834
+ call this method yourself. Instead it will used by other methods when
835
+ you find records by id or perform other searches.
836
+
837
+ If a recordType has been mapped to the storeKey, then a record instance
838
+ will be returned even if the data hash has not been requested yet.
839
+
840
+ Each Store instance returns unique record instances for each storeKey.
841
+
842
+ @param {Integer} storeKey The storeKey for the dataHash.
843
+ @returns {SC.Record} Returns a record instance.
844
+ */
845
+ materializeRecord: function(storeKey) {
846
+ var records = this.records, ret, recordType, attrs;
847
+
848
+ // look up in cached records
849
+ if (!records) records = this.records = {}; // load cached records
850
+ ret = records[storeKey];
851
+ if (ret) return ret;
852
+
853
+ // not found -- OK, create one then.
854
+ recordType = SC.Store.recordTypeFor(storeKey);
855
+ if (!recordType) return null; // not recordType registered, nothing to do
856
+
857
+ attrs = this._TMP_REC_ATTRS ;
858
+ attrs.storeKey = storeKey ;
859
+ attrs.store = this ;
860
+ ret = records[storeKey] = recordType.create(attrs);
861
+
862
+ return ret ;
863
+ },
864
+
865
+ // ..........................................................
866
+ // CORE RECORDS API
867
+ //
868
+ // The methods in this section can be used to manipulate records without
869
+ // actually creating record instances.
870
+
871
+ /**
872
+ Creates a new record instance with the passed recordType and dataHash.
873
+ You can also optionally specify an id or else it will be pulled from the
874
+ data hash.
875
+
876
+ Note that the record will not yet be saved back to the server. To save
877
+ a record to the server, call commitChanges() on the store.
878
+
879
+ @param {SC.Record} recordType the record class to use on creation
880
+ @param {Hash} dataHash the JSON attributes to assign to the hash.
881
+ @param {String} id (optional) id to assign to record
882
+
883
+ @returns {SC.Record} Returns the created record
884
+ */
885
+ createRecord: function(recordType, dataHash, id) {
886
+
887
+ var primaryKey, storeKey, status, K = SC.Record, changelog, defaultVal;
888
+
889
+ // First, try to get an id. If no id is passed, look it up in the
890
+ // dataHash.
891
+ if (!id && (primaryKey = recordType.prototype.primaryKey)) {
892
+ id = dataHash[primaryKey];
893
+ // if still no id, check if there is a defaultValue function for
894
+ // the primaryKey attribute and assign that
895
+ defaultVal = recordType.prototype[primaryKey] ? recordType.prototype[primaryKey].defaultValue : null;
896
+ if(!id && SC.typeOf(defaultVal)===SC.T_FUNCTION) {
897
+ id = dataHash[primaryKey] = defaultVal();
898
+ }
899
+ }
900
+
901
+ // Next get the storeKey - base on id if available
902
+ storeKey = id ? recordType.storeKeyFor(id) : SC.Store.generateStoreKey();
903
+
904
+ // now, check the state and do the right thing.
905
+ status = this.readStatus(storeKey);
906
+
907
+ // check state
908
+ // any busy or ready state or destroyed dirty state is not allowed
909
+ if ((status & K.BUSY) ||
910
+ (status & K.READY) ||
911
+ (status == K.DESTROYED_DIRTY)) {
912
+ throw id ? K.RECORD_EXISTS_ERROR : K.BAD_STATE_ERROR;
913
+
914
+ // allow error or destroyed state only with id
915
+ } else if (!id && (status==SC.DESTROYED_CLEAN || status==SC.ERROR)) {
916
+ throw K.BAD_STATE_ERROR;
917
+ }
918
+
919
+ // add dataHash and setup initial status -- also save recordType
920
+ this.writeDataHash(storeKey, (dataHash ? dataHash : {}), K.READY_NEW);
921
+
922
+ SC.Store.replaceRecordTypeFor(storeKey, recordType);
923
+ this.dataHashDidChange(storeKey);
924
+
925
+ // Record is now in a committable state -- add storeKey to changelog
926
+ changelog = this.changelog;
927
+ if (!changelog) changelog = SC.Set.create();
928
+ changelog.add(storeKey);
929
+ this.changelog = changelog;
930
+
931
+ // if commit records is enabled
932
+ if(this.get('commitRecordsAutomatically')){
933
+ this.invokeLast(this.commitRecords);
934
+ }
935
+
936
+ // finally return materialized record
937
+ return this.materializeRecord(storeKey) ;
938
+ },
939
+
940
+ /**
941
+ Creates an array of new records. You must pass an array of dataHashes
942
+ plus a recordType and, optionally, an array of ids. This will create an
943
+ array of record instances with the same record type.
944
+
945
+ If you need to instead create a bunch of records with different data types
946
+ you can instead pass an array of recordTypes, one for each data hash.
947
+
948
+ @param {SC.Record|Array} recordTypes class or array of classes
949
+ @param {Array} dataHashes array of data hashes
950
+ @param {Array} ids (optional) ids to assign to records
951
+ @returns {Array} array of materialized record instances.
952
+ */
953
+ createRecords: function(recordTypes, dataHashes, ids) {
954
+ var ret = [], recordType, id, isArray, len = dataHashes.length, idx ;
955
+ isArray = SC.typeOf(recordTypes) === SC.T_ARRAY;
956
+ if (!isArray) recordType = recordTypes;
957
+ for(idx=0;idx<len;idx++) {
958
+ if (isArray) recordType = recordTypes[idx] || SC.Record;
959
+ id = ids ? ids[idx] : undefined ;
960
+ ret.push(this.createRecord(recordType, dataHashes[idx], id));
961
+ }
962
+ return ret ;
963
+ },
964
+
965
+ /**
966
+ Destroys a record, removing the data hash from the store and adding the
967
+ record to the destroyed changelog. If you try to destroy a record that is
968
+ already destroyed then this method will have no effect. If you destroy a
969
+ record that does not exist or an error then an exception will be raised.
970
+
971
+ @param {SC.Record} recordType the recordType
972
+ @param {String} id the record id
973
+ @param {Number} storeKey (optional) if passed, ignores recordType and id
974
+ @returns {SC.Store} receiver
975
+ */
976
+ destroyRecord: function(recordType, id, storeKey) {
977
+ if (storeKey === undefined) storeKey = recordType.storeKeyFor(id);
978
+ var status = this.readStatus(storeKey), changelog, K = SC.Record;
979
+
980
+ // handle status - ignore if destroying or destroyed
981
+ if ((status === K.BUSY_DESTROYING) || (status & K.DESTROYED)) {
982
+ return this; // nothing to do
983
+
984
+ // error out if empty
985
+ } else if (status == K.EMPTY) {
986
+ throw K.NOT_FOUND_ERROR ;
987
+
988
+ // error out if busy
989
+ } else if (status & K.BUSY) {
990
+ throw K.BUSY_ERROR ;
991
+
992
+ // if new status, destroy but leave in clean state
993
+ } else if (status == K.READY_NEW) {
994
+ status = K.DESTROYED_CLEAN ;
995
+
996
+ // otherwise, destroy in dirty state
997
+ } else status = K.DESTROYED_DIRTY ;
998
+
999
+ // remove the data hash, set new status
1000
+ this.writeStatus(storeKey, status);
1001
+ this.dataHashDidChange(storeKey);
1002
+
1003
+ // add/remove change log
1004
+ changelog = this.changelog;
1005
+ if (!changelog) changelog = this.changelog = SC.Set.create();
1006
+
1007
+ ((status & K.DIRTY) ? changelog.add(storeKey) : changelog.remove(storeKey));
1008
+ this.changelog=changelog;
1009
+
1010
+ // if commit records is enabled
1011
+ if(this.get('commitRecordsAutomatically')){
1012
+ this.invokeLast(this.commitRecords);
1013
+ }
1014
+
1015
+ return this ;
1016
+ },
1017
+
1018
+ /**
1019
+ Destroys a group of records. If you have a set of record ids, destroying
1020
+ them this way can be faster than retrieving each record and destroying
1021
+ it individually.
1022
+
1023
+ You can pass either a single recordType or an array of recordTypes. If
1024
+ you pass a single recordType, then the record type will be used for each
1025
+ record. If you pass an array, then each id must have a matching record
1026
+ type in the array.
1027
+
1028
+ You can optionally pass an array of storeKeys instead of the recordType
1029
+ and ids. In this case the first two parameters will be ignored. This
1030
+ is usually only used by low-level internal methods. You will not usually
1031
+ destroy records this way.
1032
+
1033
+ @param {SC.Record|Array} recordTypes class or array of classes
1034
+ @param {Array} ids ids to destroy
1035
+ @param {Array} storeKeys (optional) store keys to destroy
1036
+ @returns {SC.Store} receiver
1037
+ */
1038
+ destroyRecords: function(recordTypes, ids, storeKeys) {
1039
+ var len, isArray, idx, id, recordType, storeKey;
1040
+ if(storeKeys===undefined){
1041
+ len = ids.length;
1042
+ isArray = SC.typeOf(recordTypes) === SC.T_ARRAY;
1043
+ if (!isArray) recordType = recordTypes;
1044
+ for(idx=0;idx<len;idx++) {
1045
+ if (isArray) recordType = recordTypes[idx] || SC.Record;
1046
+ id = ids ? ids[idx] : undefined ;
1047
+ this.destroyRecord(recordType, id, undefined);
1048
+ }
1049
+ }else{
1050
+ len = storeKeys.length;
1051
+ for(idx=0;idx<len;idx++) {
1052
+ storeKey = storeKeys ? storeKeys[idx] : undefined ;
1053
+ this.destroyRecord(undefined, undefined, storeKey);
1054
+ }
1055
+ }
1056
+ return this ;
1057
+ },
1058
+
1059
+ /**
1060
+ Notes that the data for the given record id has changed. The record will
1061
+ be committed to the server the next time you commit the root store. Only
1062
+ call this method on a record in a READY state of some type.
1063
+
1064
+ @param {SC.Record} recordType the recordType
1065
+ @param {String} id the record id
1066
+ @param {Number} storeKey (optional) if passed, ignores recordType and id
1067
+ @returns {SC.Store} receiver
1068
+ */
1069
+ recordDidChange: function(recordType, id, storeKey) {
1070
+ if (storeKey === undefined) storeKey = recordType.storeKeyFor(id);
1071
+ var status = this.readStatus(storeKey), changelog, K = SC.Record;
1072
+
1073
+ // BUSY_LOADING, BUSY_CREATING, BUSY_COMMITTING, BUSY_REFRESH_CLEAN
1074
+ // BUSY_REFRESH_DIRTY, BUSY_DESTROYING
1075
+ if (status & K.BUSY) {
1076
+ throw K.BUSY_ERROR ;
1077
+
1078
+ // if record is not in ready state, then it is not found.
1079
+ // ERROR, EMPTY, DESTROYED_CLEAN, DESTROYED_DIRTY
1080
+ } else if (!(status & K.READY)) {
1081
+ throw K.NOT_FOUND_ERROR ;
1082
+
1083
+ // otherwise, make new status READY_DIRTY unless new.
1084
+ // K.READY_CLEAN, K.READY_DIRTY, ignore K.READY_NEW
1085
+ } else {
1086
+ if (status != K.READY_NEW) this.writeStatus(storeKey, K.READY_DIRTY);
1087
+ }
1088
+
1089
+ // record data hash change
1090
+ this.dataHashDidChange(storeKey, null);
1091
+ // record in changelog
1092
+ changelog = this.changelog ;
1093
+ if (!changelog) changelog = this.changelog = SC.Set.create() ;
1094
+ changelog.add(storeKey);
1095
+ this.changelog=changelog;
1096
+
1097
+ // if commit records is enabled
1098
+ if(this.get('commitRecordsAutomatically')){
1099
+ this.invokeLast(this.commitRecords);
1100
+ }
1101
+
1102
+ return this ;
1103
+ },
1104
+
1105
+ /**
1106
+ Mark a group of records as dirty. The records will be committed to the
1107
+ server the next time you commit changes on the root store. If you have a
1108
+ set of record ids, marking them dirty this way can be faster than
1109
+ retrieving each record and destroying it individually.
1110
+
1111
+ You can pass either a single recordType or an array of recordTypes. If
1112
+ you pass a single recordType, then the record type will be used for each
1113
+ record. If you pass an array, then each id must have a matching record
1114
+ type in the array.
1115
+
1116
+ You can optionally pass an array of storeKeys instead of the recordType
1117
+ and ids. In this case the first two parameters will be ignored. This
1118
+ is usually only used by low-level internal methods.
1119
+
1120
+ @param {SC.Record|Array} recordTypes class or array of classes
1121
+ @param {Array} ids ids to destroy
1122
+ @param {Array} storeKeys (optional) store keys to destroy
1123
+ @returns {SC.Store} receiver
1124
+ */
1125
+ recordsDidChange: function(recordTypes, ids, storeKeys) {
1126
+ var len, isArray, idx, id, recordType, storeKey;
1127
+ if(storeKeys===undefined){
1128
+ len = ids.length;
1129
+ isArray = SC.typeOf(recordTypes) === SC.T_ARRAY;
1130
+ if (!isArray) recordType = recordTypes;
1131
+ for(idx=0;idx<len;idx++) {
1132
+ if (isArray) recordType = recordTypes[idx] || SC.Record;
1133
+ id = ids ? ids[idx] : undefined ;
1134
+ storeKey = storeKeys ? storeKeys[idx] : undefined ;
1135
+ this.recordDidChange(recordType, id, storeKey);
1136
+ }
1137
+ }else{
1138
+ len = storeKeys.length;
1139
+ for(idx=0;idx<len;idx++) {
1140
+ storeKey = storeKeys ? storeKeys[idx] : undefined ;
1141
+ this.recordDidChange(undefined, undefined, storeKey);
1142
+ }
1143
+ }
1144
+ return this ;
1145
+ },
1146
+
1147
+ /**
1148
+ Retrieves a set of records from the server. If the records has
1149
+ already been loaded in the store, then this method will simply return.
1150
+ Otherwise if your store has a dataSource, this will call the
1151
+ dataSource to retrieve the record. Generally you will not need to
1152
+ call this method yourself. Instead you can just use find().
1153
+
1154
+ This will not actually create a record instance but it will initiate a
1155
+ load of the record from the server. You can subsequently get a record
1156
+ instance itself using materializeRecord()
1157
+
1158
+ @param {SC.Record|Array} recordTypes class or array of classes
1159
+ @param {Array} ids ids to retrieve
1160
+ @param {Array} storeKeys (optional) store keys to retrieve
1161
+ @param {Boolean} isRefresh
1162
+ @returns {Array} storeKeys to be retrieved
1163
+ */
1164
+ retrieveRecords: function(recordTypes, ids, storeKeys, isRefresh) {
1165
+
1166
+ var source = this._getDataSource(),
1167
+ isArray = SC.typeOf(recordTypes) === SC.T_ARRAY,
1168
+ len = (!storeKeys) ? ids.length : storeKeys.length,
1169
+ ret = [],
1170
+ rev = SC.Store.generateStoreKey(),
1171
+ K = SC.Record,
1172
+ recordType, idx, storeKey, status;
1173
+
1174
+ if (!isArray) recordType = recordTypes;
1175
+
1176
+ // if no storeKeys were passed, map recordTypes + ids
1177
+ for(idx=0;idx<len;idx++) {
1178
+
1179
+ // collect store key
1180
+ if (storeKeys) {
1181
+ storeKey = storeKeys[idx];
1182
+ } else {
1183
+ if (isArray) recordType = recordTypes[idx];
1184
+ storeKey = recordType.storeKeyFor(ids[idx]);
1185
+ }
1186
+
1187
+ // collect status and process
1188
+ status = this.readStatus(storeKey);
1189
+
1190
+ // K.EMPTY, K.ERROR, K.DESTROYED_CLEAN - initial retrieval
1191
+ if ((status == K.EMPTY) || (status == K.ERROR) || (status == K.DESTROYED_CLEAN)) {
1192
+ this.writeStatus(storeKey, K.BUSY_LOADING);
1193
+ this.dataHashDidChange(storeKey, rev, YES);
1194
+ ret.push(storeKey);
1195
+
1196
+ // otherwise, ignore record unless isRefresh is YES.
1197
+ } else if (isRefresh) {
1198
+ // K.READY_CLEAN, K.READY_DIRTY, ignore K.READY_NEW
1199
+ if (status & K.READY) {
1200
+ this.writeStatus(storeKey, K.BUSY_REFRESH | (status & 0x03)) ;
1201
+ this.dataHashDidChange(storeKey, rev, YES);
1202
+ ret.push(storeKey);
1203
+
1204
+ // K.BUSY_DESTROYING, K.BUSY_COMMITTING, K.BUSY_CREATING
1205
+ } else if ((status == K.BUSY_DESTROYING) || (status == K.BUSY_CREATING) || (status == K.BUSY_COMMITTING)) {
1206
+ throw K.BUSY_ERROR ;
1207
+
1208
+ // K.DESTROY_DIRTY, bad state...
1209
+ } else if (status == K.DESTROYED_DIRTY) {
1210
+ throw K.BAD_STATE_ERROR ;
1211
+
1212
+ // ignore K.BUSY_LOADING, K.BUSY_REFRESH_CLEAN, K.BUSY_REFRESH_DIRTY
1213
+ }
1214
+ }
1215
+ }
1216
+
1217
+ // now retrieve storekeys from dataSource
1218
+ if (source) {
1219
+ var ok = source.retrieveRecords.call(source, this, ret, ids);
1220
+ if (ok === NO) ret.length = 0; // could not find.
1221
+ }
1222
+ return ret ;
1223
+ },
1224
+
1225
+ _TMP_RETRIEVE_ARRAY: [],
1226
+
1227
+ /**
1228
+ Retrieves a record from the server. If the record has already been loaded
1229
+ in the store, then this method will simply return. Otherwise if your
1230
+ store has a dataSource, this will call the dataSource to retrieve the
1231
+ record. Generally you will not need to call this method yourself.
1232
+ Instead you can just use find().
1233
+
1234
+ This will not actually create a record instance but it will initiate a
1235
+ load of the record from the server. You can subsequently get a record
1236
+ instance itself using materializeRecord()
1237
+
1238
+ @param {SC.Record} recordType class
1239
+ @param {String} id id to retrieve
1240
+ @param {Number} storeKey (optional) store key
1241
+ @param {Boolean} isRefresh
1242
+ @returns {Number} storeKey that was retrieved
1243
+ */
1244
+ retrieveRecord: function(recordType, id, storeKey, isRefresh) {
1245
+ var array = this._TMP_RETRIEVE_ARRAY,
1246
+ ret;
1247
+
1248
+ if (storeKey) {
1249
+ array[0] = storeKey;
1250
+ storeKey = array;
1251
+ id = null ;
1252
+ } else {
1253
+ array[0] = id;
1254
+ id = array;
1255
+ }
1256
+
1257
+ ret = this.retrieveRecords(recordType, id, storeKey, isRefresh);
1258
+ array.length = 0 ;
1259
+ return ret[0];
1260
+ },
1261
+
1262
+ /**
1263
+ Refreshes a record from the server. If the record has already been loaded
1264
+ in the store, then this method will request a refresh from the dataSource.
1265
+ Otherwise it will attempt to retrieve the record.
1266
+
1267
+ @param {String} id to id of the record to load
1268
+ @param {SC.Record} recordType the expected record type
1269
+ @param {Number} storeKey (optional) optional store key
1270
+ @returns {Boolean} YES if the retrieval was a success.
1271
+ */
1272
+ refreshRecord: function(recordType, id, storeKey) {
1273
+ return this.retrieveRecord(recordType, id, storeKey, YES);
1274
+ },
1275
+
1276
+ /**
1277
+ Refreshes a set of records from the server. If the records has already been loaded
1278
+ in the store, then this method will request a refresh from the dataSource.
1279
+ Otherwise it will attempt to retrieve them.
1280
+
1281
+ @param {SC.Record|Array} recordTypes class or array of classes
1282
+ @param {Array} ids ids to destroy
1283
+ @param {Array} storeKeys (optional) store keys to destroy
1284
+ @returns {Boolean} YES if the retrieval was a success.
1285
+ */
1286
+ refreshRecords: function(recordTypes, ids, storeKeys) {
1287
+ return this.retrieveRecords(recordTypes, ids, storeKeys, YES);
1288
+ },
1289
+
1290
+ /**
1291
+ Commits the passed store keys. Based on the current state of the
1292
+ record, this will ask the data source to perform the appropriate actions
1293
+ on the store keys.
1294
+
1295
+ @param {String} id to id of the record to load
1296
+ @param {SC.Record} recordType the expected record type
1297
+
1298
+ @returns {SC.Bool} if the action was succesful.
1299
+ */
1300
+ commitRecords: function(recordTypes, ids, storeKeys) {
1301
+ var source = this._getDataSource(),
1302
+ isArray = SC.typeOf(recordTypes) === SC.T_ARRAY,
1303
+ retCreate= [], retUpdate= [], retDestroy = [],
1304
+ rev = SC.Store.generateStoreKey(),
1305
+ K = SC.Record,
1306
+ recordType, idx, storeKey, status, key, ret, len ;
1307
+
1308
+ // If no params are passed, look up storeKeys in the changelog property.
1309
+ // Remove any committed records from changelog property.
1310
+
1311
+ if(recordTypes===undefined && ids===undefined && storeKeys===undefined){
1312
+ storeKeys=this.changelog;
1313
+ }
1314
+
1315
+ // if no storeKeys or ids at this point, return
1316
+ if(!storeKeys && !ids) return;
1317
+
1318
+ len = (storeKeys === undefined) ? ids.length : storeKeys.length;
1319
+
1320
+ for(idx=0;idx<len;idx++) {
1321
+
1322
+ // collect store key
1323
+ if (storeKeys) {
1324
+ storeKey = storeKeys[idx];
1325
+ } else {
1326
+ if (isArray) recordType = recordTypes[idx] || SC.Record;
1327
+ else recordType = recordTypes;
1328
+ storeKey = recordType.storeKeyFor(ids[idx]);
1329
+ }
1330
+
1331
+ // collect status and process
1332
+ status = this.readStatus(storeKey);
1333
+
1334
+ if ((status == K.EMPTY) || (status == K.ERROR)) {
1335
+ throw K.NOT_FOUND_ERROR ;
1336
+ }else{
1337
+ if(status==K.READY_NEW){
1338
+ this.writeStatus(storeKey, K.BUSY_CREATING);
1339
+ this.dataHashDidChange(storeKey, rev, YES);
1340
+ retCreate.push(storeKey);
1341
+ } else if (status==K.READY_DIRTY) {
1342
+ this.writeStatus(storeKey, K.BUSY_COMMITTING);
1343
+ this.dataHashDidChange(storeKey, rev, YES);
1344
+ retUpdate.push(storeKey);
1345
+ } else if (status==K.DESTROYED_DIRTY) {
1346
+ this.writeStatus(storeKey, K.BUSY_DESTROYING);
1347
+ this.dataHashDidChange(storeKey, rev, YES);
1348
+ retDestroy.push(storeKey);
1349
+ } else if (status==K.DESTROYED_CLEAN) {
1350
+ this.dataHashDidChange(storeKey, rev, YES);
1351
+ retDestroy.push(storeKey);
1352
+ }
1353
+ // ignore K.READY_CLEAN, K.BUSY_LOADING, K.BUSY_CREATING, K.BUSY_COMMITTING,
1354
+ // K.BUSY_REFRESH_CLEAN, K_BUSY_REFRESH_DIRTY, KBUSY_DESTROYING
1355
+ }
1356
+ }
1357
+
1358
+ // now commit storekeys to dataSource
1359
+ if (source) ret=source.commitRecords.call(source, this, retCreate, retUpdate, retDestroy);
1360
+ //remove all commited changes from changelog
1361
+ if (ret && recordTypes===undefined && ids===undefined && storeKeys===this.changelog){
1362
+ this.changelog=null;
1363
+ }
1364
+ return ret ;
1365
+ },
1366
+
1367
+ /**
1368
+ Commits the passed store key. Based on the current state of the
1369
+ record, this will ask the data source to perform the appropriate action
1370
+ on the store key.
1371
+
1372
+ You have to pass either the id or the storeKey otherwise it will return NO.
1373
+
1374
+ @param {String} id to id of the record to load
1375
+ @param {SC.Record} recordType the expected record type
1376
+
1377
+ @returns {SC.Bool} if the action was succesful.
1378
+ */
1379
+ commitRecord: function(recordType, id, storeKey) {
1380
+ var array = this._TMP_RETRIEVE_ARRAY,
1381
+ ret ;
1382
+ if (id === undefined && storeKey === undefined ) return NO;
1383
+ if (storeKey !== undefined) {
1384
+ array[0] = storeKey;
1385
+ storeKey = array;
1386
+ id = null ;
1387
+ } else {
1388
+ array[0] = id;
1389
+ id = array;
1390
+ }
1391
+
1392
+ ret = this.commitRecords(recordType, id, storeKey);
1393
+ array.length = 0 ;
1394
+ return ret;
1395
+ },
1396
+
1397
+ /**
1398
+ Cancels an inflight request for the passed records. Depending on the
1399
+ server implementation, this could cancel an entire request, causing
1400
+ other records to also transition their current state.
1401
+
1402
+ @param {SC.Record|Array} recordTypes class or array of classes
1403
+ @param {Array} ids ids to destroy
1404
+ @param {Array} storeKeys (optional) store keys to destroy
1405
+ @returns {SC.Store} the store.
1406
+ */
1407
+ cancelRecords: function(recordTypes, ids, storeKeys) {
1408
+ var source = this._getDataSource(),
1409
+ isArray = SC.typeOf(recordTypes) === SC.T_ARRAY,
1410
+ K = SC.Record,
1411
+ ret = [],
1412
+ status, len, idx, id, recordType, storeKey;
1413
+
1414
+ len = (storeKeys === undefined) ? ids.length : storeKeys.length;
1415
+ for(idx=0;idx<len;idx++) {
1416
+ if (isArray) recordType = recordTypes[idx] || SC.Record;
1417
+ else recordType = recordTypes || SC.Record;
1418
+
1419
+ id = ids ? ids[idx] : undefined ;
1420
+
1421
+ if(storeKeys===undefined){
1422
+ storeKey = recordType.storeKeyFor(id);
1423
+ }else{
1424
+ storeKey = storeKeys ? storeKeys[idx] : undefined ;
1425
+ }
1426
+ if(storeKey) {
1427
+ status = this.readStatus(storeKey);
1428
+
1429
+ if ((status == K.EMPTY) || (status == K.ERROR)) {
1430
+ throw K.NOT_FOUND_ERROR ;
1431
+ }
1432
+ ret.push(storeKey);
1433
+ }
1434
+ }
1435
+
1436
+ if (source) source.cancel.call(source, this, ret);
1437
+
1438
+ return this ;
1439
+ },
1440
+
1441
+ /**
1442
+ Cancels an inflight request for the passed record. Depending on the
1443
+ server implementation, this could cancel an entire request, causing
1444
+ other records to also transition their current state.
1445
+
1446
+ @param {SC.Record|Array} recordTypes class or array of classes
1447
+ @param {Array} ids ids to destroy
1448
+ @param {Array} storeKeys (optional) store keys to destroy
1449
+ @returns {SC.Store} the store.
1450
+ */
1451
+ cancelRecord: function(recordType, id, storeKey) {
1452
+ var array = this._TMP_RETRIEVE_ARRAY,
1453
+ ret ;
1454
+
1455
+ if (storeKey !== undefined) {
1456
+ array[0] = storeKey;
1457
+ storeKey = array;
1458
+ id = null ;
1459
+ } else {
1460
+ array[0] = id;
1461
+ id = array;
1462
+ }
1463
+
1464
+ ret = this.cancelRecords(recordType, id, storeKey);
1465
+ array.length = 0 ;
1466
+ return this;
1467
+ },
1468
+
1469
+ /**
1470
+ Convenience method can be called by the store or other parts of your
1471
+ application to load records into the store. This method will take a
1472
+ recordType and an array of data hashes and either add or update the
1473
+ record in the store.
1474
+
1475
+ The loaded records will be in an SC.Record.READY_CLEAN state, indicating
1476
+ they were loaded from the data source and do not need to be committed
1477
+ back before changing.
1478
+
1479
+ This method is implemented by calling pushRetrieve(). The standard
1480
+ state constraints for that method apply here.
1481
+
1482
+ If you are upgrading from a pre SproutCore 1.0 application, this method
1483
+ is the closest to the old updateRecords().
1484
+
1485
+ @param {SC.Record} recordTypes the record type or array of record types
1486
+ @param {Array} dataHashes array of data hashes to update
1487
+ @param {Array} ids optional array of ids. if not passed lookup on hashes
1488
+ @returns {Array} store keys assigned to these ids
1489
+ */
1490
+ loadRecords: function(recordTypes, dataHashes, ids) {
1491
+ var isArray = SC.typeOf(recordTypes) === SC.T_ARRAY,
1492
+ len = dataHashes.get('length'),
1493
+ ret = [],
1494
+ recordType, id, primaryKey, idx, dataHash, storeKey;
1495
+
1496
+ // save lookup info
1497
+ if (!isArray) {
1498
+ recordType = recordTypes || SC.Record;
1499
+ primaryKey = recordType.prototype.primaryKey ;
1500
+ }
1501
+
1502
+ // push each record
1503
+ for(idx=0;idx<len;idx++) {
1504
+ dataHash = dataHashes.objectAt(idx);
1505
+ if (isArray) {
1506
+ recordType = recordTypes.objectAt(idx) || SC.Record;
1507
+ primaryKey = recordType.prototype.primaryKey ;
1508
+ }
1509
+ id = (ids) ? ids.objectAt(idx) : dataHash[primaryKey];
1510
+ ret[idx] = storeKey = recordType.storeKeyFor(id); // needed to cache
1511
+ this.pushRetrieve(recordType, id, dataHash, storeKey);
1512
+ }
1513
+ // return storeKeys
1514
+ return ret ;
1515
+ },
1516
+
1517
+ // ..........................................................
1518
+ // DATA SOURCE CALLBACKS
1519
+ //
1520
+ // Mathods called by the data source on the store
1521
+
1522
+ /**
1523
+ Called by a dataSource when it cancels an inflight operation on a
1524
+ record. This will transition the record back to it non-inflight state.
1525
+
1526
+ @param {Number} storeKey record store key to cancel
1527
+ @returns {SC.Store} reciever
1528
+ */
1529
+ dataSourceDidCancel: function(storeKey) {
1530
+ var status = this.readStatus(storeKey),
1531
+ K = SC.Record;
1532
+
1533
+ // EMPTY, ERROR, READY_CLEAN, READY_NEW, READY_DIRTY, DESTROYED_CLEAN,
1534
+ // DESTROYED_DIRTY
1535
+ if (!(status & K.BUSY)) {
1536
+ throw K.BAD_STATE_ERROR; // should never be called in this state
1537
+
1538
+ }
1539
+
1540
+ // otherwise, determine proper state transition
1541
+ switch(status) {
1542
+ case K.BUSY_LOADING:
1543
+ status = K.EMPTY;
1544
+ break ;
1545
+
1546
+ case K.BUSY_CREATING:
1547
+ status = K.READY_NEW;
1548
+ break;
1549
+
1550
+ case K.BUSY_COMMITTING:
1551
+ status = K.READY_DIRTY ;
1552
+ break;
1553
+
1554
+ case K.BUSY_REFRESH_CLEAN:
1555
+ status = K.READY_CLEAN;
1556
+ break;
1557
+
1558
+ case K.BUSY_REFRESH_DIRTY:
1559
+ status = K.READY_DIRTY ;
1560
+ break ;
1561
+
1562
+ case K.BUSY_DESTROYING:
1563
+ status = K.DESTROYED_DIRTY ;
1564
+ break;
1565
+
1566
+ default:
1567
+ throw K.BAD_STATE_ERROR ;
1568
+ }
1569
+ this.writeStatus(storeKey, status) ;
1570
+ this.dataHashDidChange(storeKey, null, YES);
1571
+
1572
+ return this ;
1573
+ },
1574
+
1575
+ /**
1576
+ Called by a data source when it creates or commits a record. Passing an
1577
+ optional id will remap the storeKey to the new record id. This is
1578
+ required when you commit a record that does not have an id yet.
1579
+
1580
+ @param {Number} storeKey record store key to change to READY_CLEAN state
1581
+ @returns {SC.Store} reciever
1582
+ */
1583
+ dataSourceDidComplete: function(storeKey, dataHash, newId) {
1584
+ var status = this.readStatus(storeKey), K = SC.Record, statusOnly;
1585
+
1586
+ // EMPTY, ERROR, READY_CLEAN, READY_NEW, READY_DIRTY, DESTROYED_CLEAN,
1587
+ // DESTROYED_DIRTY
1588
+ if (!(status & K.BUSY)) {
1589
+ throw K.BAD_STATE_ERROR; // should never be called in this state
1590
+ }
1591
+
1592
+ // otherwise, determine proper state transition
1593
+ if(status===K.BUSY_DESTROYING) {
1594
+ throw K.BAD_STATE_ERROR ;
1595
+ } else status = K.READY_CLEAN ;
1596
+
1597
+ this.writeStatus(storeKey, status) ;
1598
+ if (dataHash) this.writeDataHash(storeKey, dataHash, status) ;
1599
+ if (newId) SC.Store.replaceIdFor(storeKey, newId);
1600
+
1601
+ statusOnly = dataHash || newId ? NO : YES;
1602
+ this.dataHashDidChange(storeKey, null, statusOnly);
1603
+
1604
+ return this ;
1605
+ },
1606
+
1607
+ /**
1608
+ Called by a data source when it has destroyed a record. This will
1609
+ transition the record to the proper state.
1610
+
1611
+ @param {Number} storeKey record store key to cancel
1612
+ @returns {SC.Store} reciever
1613
+ */
1614
+ dataSourceDidDestroy: function(storeKey) {
1615
+ var status = this.readStatus(storeKey), K = SC.Record;
1616
+
1617
+ // EMPTY, ERROR, READY_CLEAN, READY_NEW, READY_DIRTY, DESTROYED_CLEAN,
1618
+ // DESTROYED_DIRTY
1619
+ if (!(status & K.BUSY)) {
1620
+ throw K.BAD_STATE_ERROR; // should never be called in this state
1621
+ }
1622
+ // otherwise, determine proper state transition
1623
+ else{
1624
+ status = K.DESTROYED_CLEAN ;
1625
+ }
1626
+ this.removeDataHash(storeKey, status) ;
1627
+ this.dataHashDidChange(storeKey);
1628
+
1629
+ return this ;
1630
+ },
1631
+
1632
+ /**
1633
+ Converts the passed record into an error object.
1634
+
1635
+ @param {Number} storeKey record store key to cancel
1636
+ @returns {SC.Store} reciever
1637
+ */
1638
+ dataSourceDidError: function(storeKey, error) {
1639
+ var status = this.readStatus(storeKey), K = SC.Record;
1640
+
1641
+ // EMPTY, ERROR, READY_CLEAN, READY_NEW, READY_DIRTY, DESTROYED_CLEAN,
1642
+ // DESTROYED_DIRTY
1643
+ if (!(status & K.BUSY)) {
1644
+ throw K.BAD_STATE_ERROR; // should never be called in this state
1645
+ }
1646
+ // otherwise, determine proper state transition
1647
+ else{
1648
+ status = error ;
1649
+ }
1650
+ this.writeStatus(storeKey, status) ;
1651
+ this.dataHashDidChange(storeKey, null, YES);
1652
+
1653
+ return this ;
1654
+ },
1655
+
1656
+ // ..........................................................
1657
+ // PUSH CHANGES FROM DATA SOURCE
1658
+ //
1659
+
1660
+ pushRetrieve: function(recordType, id, dataHash, storeKey) {
1661
+ var K = SC.Record, status;
1662
+
1663
+ if(storeKey===undefined){
1664
+ storeKey = recordType.storeKeyFor(id);
1665
+ }
1666
+ status = this.readStatus(storeKey);
1667
+ if(status==K.EMPTY || status==K.ERROR || status==K.READY_CLEAN || status==K.DESTROY_CLEAN) {
1668
+
1669
+ status = K.READY_CLEAN;
1670
+ if(dataHash===undefined) {
1671
+ this.writeStatus(storeKey, status) ;
1672
+ }
1673
+ else {
1674
+ this.writeDataHash(storeKey, dataHash, status) ;
1675
+ }
1676
+ this.dataHashDidChange(storeKey);
1677
+
1678
+ return YES;
1679
+ }
1680
+ //conflicted (ready)
1681
+ return NO;
1682
+ },
1683
+
1684
+ pushDestroy: function(recordType, id, storeKey) {
1685
+ var K = SC.Record, status;
1686
+
1687
+ if(storeKey===undefined){
1688
+ storeKey = recordType.storeKeyFor(id);
1689
+ }
1690
+ status = this.readStatus(storeKey);
1691
+ if(status==K.EMPTY || status==K.ERROR || status==K.READY_CLEAN || status==K.DESTROY_CLEAN){
1692
+ status = K.DESTROY_CLEAN;
1693
+ this.removeDataHash(storeKey, status) ;
1694
+ this.dataHashDidChange(storeKey);
1695
+ return YES;
1696
+ }
1697
+ //conflicted (destroy)
1698
+ return NO;
1699
+ },
1700
+
1701
+ pushError: function(recordType, id, error, storeKey) {
1702
+ var K = SC.Record, status;
1703
+
1704
+ if(storeKey===undefined){
1705
+ storeKey = recordType.storeKeyFor(id);
1706
+ }
1707
+ status = this.readStatus(storeKey);
1708
+ if(status==K.EMPTY || status==K.ERROR || status==K.READY_CLEAN || status==K.DESTROY_CLEAN){
1709
+ status = error;
1710
+ this.writeStatus(storeKey, status) ;
1711
+ this.dataHashDidChange(storeKey, null, YES);
1712
+ return YES;
1713
+ }
1714
+ //conflicted (error)
1715
+ return NO;
1716
+ },
1717
+
1718
+ // ..........................................................
1719
+ // INTERNAL SUPPORT
1720
+ //
1721
+
1722
+ init: function() {
1723
+ sc_super();
1724
+ this.reset();
1725
+ },
1726
+
1727
+
1728
+ // ..........................................................
1729
+ // PRIMARY KEY CONVENIENCE METHODS
1730
+ //
1731
+
1732
+ /**
1733
+ Given a storeKey, return the primaryKey.
1734
+
1735
+ @param {Number} storeKey the store key
1736
+ @returns {String} primaryKey value
1737
+ */
1738
+ idFor: function(storeKey) {
1739
+ return SC.Store.idFor(storeKey);
1740
+ },
1741
+
1742
+ /**
1743
+ Given a storeKey, return the recordType.
1744
+
1745
+ @param {Number} storeKey the store key
1746
+ @returns {SC.Record} record instance
1747
+ */
1748
+ recordTypeFor: function(storeKey) {
1749
+ return SC.Store.recordTypeFor(storeKey) ;
1750
+ },
1751
+
1752
+ /**
1753
+ Given a recordType and primaryKey, find the storeKey. If the primaryKey
1754
+ has not been assigned a storeKey yet, it will be added.
1755
+
1756
+ @param {SC.Record} recordType the record type
1757
+ @param {String} primaryKey the primary key
1758
+ @returns {Number} storeKey
1759
+ */
1760
+ storeKeyFor: function(recordType, primaryKey) {
1761
+ return recordType.storeKeyFor(primaryKey);
1762
+ },
1763
+
1764
+ /**
1765
+ Given a primaryKey value for the record, returns the associated
1766
+ storeKey. As opposed to storeKeyFor() however, this method
1767
+ will NOT generate a new storeKey but returned undefined.
1768
+
1769
+ @param {String} id a record id
1770
+ @returns {Number} a storeKey.
1771
+ */
1772
+ storeKeyExists: function(recordType, primaryKey) {
1773
+ return recordType.storeKeyExists(primaryKey);
1774
+ },
1775
+
1776
+ /**
1777
+ Finds all storeKeys of a certain record type in this store
1778
+ and returns an array.
1779
+
1780
+ @param {SC.Record} recordType
1781
+ @returns {Array} set of storeKeys
1782
+ */
1783
+ storeKeysFor: function(recordType) {
1784
+ var recType, ret = [], storeKey;
1785
+ if(!this.statuses) return;
1786
+
1787
+ for(storeKey in SC.Store.recordTypesByStoreKey) {
1788
+ recType = SC.Store.recordTypesByStoreKey[storeKey];
1789
+ // if same record type and this store has it
1790
+ if(recType===recordType && this.statuses[storeKey]) {
1791
+ ret.push(parseInt(storeKey,0));
1792
+ }
1793
+ }
1794
+
1795
+ return ret;
1796
+ },
1797
+
1798
+ /**
1799
+ Finds all storeKeys in this store
1800
+ and returns an array.
1801
+
1802
+ @returns {Array} set of storeKeys
1803
+ */
1804
+ storeKeys: function() {
1805
+ var ret = [], storeKey;
1806
+ if(!this.statuses) return;
1807
+
1808
+ for(storeKey in this.statuses) {
1809
+ // if status is not empty
1810
+ if(this.statuses[storeKey] != SC.Record.EMPTY) {
1811
+ ret.push(parseInt(storeKey,0));
1812
+ }
1813
+ }
1814
+
1815
+ return ret;
1816
+ },
1817
+
1818
+ /**
1819
+ Returns string representation of a storeKey, with status.
1820
+
1821
+ @param {Number} storeKey
1822
+ @returns {String}
1823
+ */
1824
+ statusString: function(storeKey) {
1825
+ var rec = this.materializeRecord(storeKey);
1826
+ return rec.statusString();
1827
+ }
1828
+
1829
+ }) ;
1830
+
1831
+ SC.Store.mixin({
1832
+
1833
+ CHAIN_CONFLICT_ERROR: new Error("Nested Store Conflict"),
1834
+ NO_PARENT_STORE_ERROR: new Error("Parent Store Required"),
1835
+ NESTED_STORE_UNSUPPORTED_ERROR: new Error("Unsupported In Nested Store"),
1836
+
1837
+ EDITABLE: 'editable',
1838
+ LOCKED: 'locked',
1839
+ INHERITED: 'inherited',
1840
+
1841
+ /** @private
1842
+ This array maps all storeKeys to primary keys. You will not normally
1843
+ access this method directly. Instead use the idFor() and
1844
+ storeKeyFor() methods on SC.Record.
1845
+ */
1846
+ idsByStoreKey: [],
1847
+
1848
+ /** @private
1849
+ Maps all storeKeys to a recordType. Once a storeKey is associated with
1850
+ a primaryKey and recordType that remains constant throughout the lifetime
1851
+ of the application.
1852
+ */
1853
+ recordTypesByStoreKey: {},
1854
+
1855
+ /** @private
1856
+ The next store key to allocate. A storeKey must always be greater than 0
1857
+ */
1858
+ nextStoreKey: 1,
1859
+
1860
+ generateStoreKey: function() { return this.nextStoreKey++; },
1861
+
1862
+ /**
1863
+ Given a storeKey returns the primaryKey associated with the key.
1864
+ If not primaryKey is associated with the storeKey, returns null.
1865
+
1866
+ @param {Number} storeKey the store key
1867
+ @returns {String} the primary key or null
1868
+ */
1869
+ idFor: function(storeKey) {
1870
+ return this.idsByStoreKey[storeKey] ;
1871
+ },
1872
+
1873
+ /**
1874
+ Given a storeKey returns the SC.Record class associated with the key.
1875
+ If no record type is associated with the store key, returns null.
1876
+
1877
+ The SC.Record class will only be found if you have already called
1878
+ storeKeyFor() on the record.
1879
+
1880
+ @param {Number} storeKey the store key
1881
+ @returns {SC.Record} the record type
1882
+ */
1883
+ recordTypeFor: function(storeKey) {
1884
+ return this.recordTypesByStoreKey[storeKey];
1885
+ },
1886
+
1887
+ /**
1888
+ Swaps the primaryKey mapped to the given storeKey with the new
1889
+ primaryKey. If the storeKey is not currently associated with a record
1890
+ this will raise an exception.
1891
+
1892
+ @param {Number} storeKey the existing store key
1893
+ @param {String} newPrimaryKey the new primary key
1894
+ @returns {SC.Store} receiver
1895
+ */
1896
+ replaceIdFor: function(storeKey, primaryKey) {
1897
+ var recordType = this.recordTypeFor(storeKey);
1898
+ if (!recordType) {
1899
+ throw "replaceIdFor: storeKey %@ does not exist".fmt(storeKey);
1900
+ }
1901
+
1902
+ // map one direction...
1903
+ var oldPrimaryKey = this.idsByStoreKey[storeKey];
1904
+ this.idsByStoreKey[storeKey] = primaryKey ;
1905
+
1906
+ // then the other...
1907
+ var storeKeys = recordType.storeKeysById() ;
1908
+ delete storeKeys[oldPrimaryKey];
1909
+ storeKeys[primaryKey] = storeKey;
1910
+
1911
+ return this ;
1912
+ },
1913
+
1914
+ /**
1915
+ Swaps the recordType recorded for a given storeKey. Normally you should
1916
+ not call this method directly as it can damage the store behavior. This
1917
+ method is used by other store methods to set the recordType for a
1918
+ storeKey.
1919
+
1920
+ @param {Integer} storeKey the store key
1921
+ @param {SC.Record} recordType a record class
1922
+ @returns {SC.Store} reciever
1923
+ */
1924
+ replaceRecordTypeFor: function(storeKey, recordType) {
1925
+ this.recordTypesByStoreKey[storeKey] = recordType;
1926
+ return this ;
1927
+ }
1928
+
1929
+ });
1930
+
1931
+
1932
+ SC.Store.prototype.nextStoreIndex = 1;
1933
+
1934
+ // ..........................................................
1935
+ // COMPATIBILITY
1936
+ //
1937
+
1938
+ /** @private
1939
+ global store is used only for deprecated compatibility methods. Don't use
1940
+ this in real code.
1941
+ */
1942
+ SC.Store._getDefaultStore = function() {
1943
+ var store = this._store;
1944
+ if(!store) this._store = store = SC.Store.create();
1945
+ return store;
1946
+ };
1947
+
1948
+ /** @deprecated
1949
+ Included for compatibility, loads data hashes with the named recordType.
1950
+ If no recordType is passed, expects to find a recordType property in the
1951
+ data hashes. dataSource and isLoaded params are ignored.
1952
+
1953
+ Calls SC.Store#loadRecords() on the default store. Do not use this method in
1954
+ new code.
1955
+
1956
+ @param {Array} dataHashes data hashes to import
1957
+ @param {Object} dataSource ignored
1958
+ @param {SC.Record} recordType default record type
1959
+ @param {Boolean} isLoaded ignored
1960
+ @returns {Array} SC.Record instances for loaded data hashes
1961
+ */
1962
+ SC.Store.updateRecords = function(dataHashes, dataSource, recordType, isLoaded) {
1963
+ var store = this._getDefaultStore(),
1964
+ len = dataHashes.length,
1965
+ idx, ret;
1966
+
1967
+ // if no recordType was passed, build an array of recordTypes from hashes
1968
+ if (!recordType) {
1969
+ recordType = [];
1970
+ for(idx=0;idx<len;idx++) recordType[idx] = dataHashes[idx].recordType;
1971
+ }
1972
+
1973
+ // call new API. Returns storeKeys
1974
+ ret = store.loadRecords(recordType, dataHashes);
1975
+
1976
+ // map to SC.Record instances
1977
+ len = ret.length;
1978
+ for(idx=0;idx<len;idx++) ret[idx] = store.materializeRecord(ret[idx]);
1979
+
1980
+ return ret ;
1981
+ };
1982
+
1983
+ /** @deprecated
1984
+ Finds a record with the passed guid on the default store. This is included
1985
+ only for compatibility. You should use the newer find() method defined on
1986
+ SC.Store instead.
1987
+
1988
+ @param {String} guid the guid
1989
+ @param {SC.Record} recordType expected record type
1990
+ @returns {SC.Record} found record
1991
+ */
1992
+ SC.Store.find = function(guid, recordType) {
1993
+ return this._getDefaultStore().find(recordType, guid);
1994
+ };
1995
+
1996
+ /** @deprecated
1997
+ Passes through to findAll on default store. This is included only for
1998
+ compatibility. You should use the newer findAll() defined on SC.Store
1999
+ instead.
2000
+
2001
+ @param {Hash} filter search parameters
2002
+ @param {SC.Record} recordType type of record to find
2003
+ @returns {SC.RecordArray} result set
2004
+ */
2005
+ SC.Store.findAll = function(filter, recordType) {
2006
+ return this._getDefaultStore().findAll(filter, recordType);
2007
+ };