sproutcore 1.7.1.beta → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (445) hide show
  1. data/CHANGELOG +44 -0
  2. data/README.rdoc +20 -20
  3. data/VERSION.yml +3 -3
  4. data/lib/Buildfile +1 -1
  5. data/lib/buildtasks/build.rake +5 -0
  6. data/lib/buildtasks/manifest.rake +19 -1
  7. data/lib/frameworks/sproutcore/Buildfile +19 -17
  8. data/lib/frameworks/sproutcore/CHANGELOG.md +163 -29
  9. data/lib/frameworks/sproutcore/README.md +29 -8
  10. data/lib/frameworks/sproutcore/apps/statechart_routing/Buildfile +12 -0
  11. data/lib/frameworks/sproutcore/apps/statechart_routing/controllers/login_controller.js +11 -0
  12. data/lib/frameworks/sproutcore/apps/statechart_routing/controllers/main_controller.js +7 -0
  13. data/lib/frameworks/sproutcore/apps/statechart_routing/controllers/statechart_controller.js +17 -0
  14. data/lib/frameworks/sproutcore/apps/statechart_routing/core.js +25 -0
  15. data/lib/frameworks/sproutcore/apps/statechart_routing/main.js +15 -0
  16. data/lib/frameworks/sproutcore/apps/statechart_routing/resources/_theme.css +18 -0
  17. data/lib/frameworks/sproutcore/apps/statechart_routing/resources/bar_page.js +14 -0
  18. data/lib/frameworks/sproutcore/apps/statechart_routing/resources/foo_page.js +14 -0
  19. data/lib/frameworks/sproutcore/apps/statechart_routing/resources/loading.rhtml +9 -0
  20. data/lib/frameworks/sproutcore/apps/statechart_routing/resources/login_page.js +61 -0
  21. data/lib/frameworks/sproutcore/apps/statechart_routing/resources/main_page.js +46 -0
  22. data/lib/frameworks/sproutcore/apps/statechart_routing/statechart.js +76 -0
  23. data/lib/frameworks/sproutcore/apps/statechart_routing/theme.js +27 -0
  24. data/lib/frameworks/sproutcore/apps/tests/controllers/targets.js +1 -1
  25. data/lib/frameworks/sproutcore/apps/tests/states/no_targets.js +1 -1
  26. data/lib/frameworks/sproutcore/apps/tests/states/ready_detail.js +1 -1
  27. data/lib/frameworks/sproutcore/apps/tests/states/ready_empty.js +1 -1
  28. data/lib/frameworks/sproutcore/apps/tests/states/ready_list.js +1 -1
  29. data/lib/frameworks/sproutcore/apps/tests/states/ready_no_tests.js +1 -1
  30. data/lib/frameworks/sproutcore/apps/welcome/controllers/targets.js +1 -1
  31. data/lib/frameworks/sproutcore/frameworks/ajax/system/request.js +14 -1
  32. data/lib/frameworks/sproutcore/frameworks/ajax/system/response.js +15 -15
  33. data/lib/frameworks/sproutcore/frameworks/ajax/tests/system/request.js +1 -1
  34. data/lib/frameworks/sproutcore/frameworks/animation/core.js +8 -5
  35. data/lib/frameworks/sproutcore/frameworks/bootstrap/system/browser.js +302 -70
  36. data/lib/frameworks/sproutcore/frameworks/bootstrap/system/loader.js +19 -14
  37. data/lib/frameworks/sproutcore/frameworks/bootstrap/tests/system/browser.js +471 -149
  38. data/lib/frameworks/sproutcore/frameworks/core_foundation/controllers/array.js +3 -3
  39. data/lib/frameworks/sproutcore/frameworks/core_foundation/ext/object.js +42 -0
  40. data/lib/frameworks/sproutcore/frameworks/core_foundation/ext/run_loop.js +3 -2
  41. data/lib/frameworks/sproutcore/frameworks/core_foundation/ext/string.js +7 -0
  42. data/lib/frameworks/sproutcore/frameworks/core_foundation/mixins/action_support.js +1 -1
  43. data/lib/frameworks/sproutcore/frameworks/core_foundation/mixins/delegate_support.js +2 -2
  44. data/lib/frameworks/sproutcore/frameworks/core_foundation/mixins/responder_context.js +3 -3
  45. data/lib/frameworks/sproutcore/frameworks/core_foundation/mixins/selection_support.js +1 -1
  46. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/body_overflow.js +63 -0
  47. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/keyboard.js +1 -1
  48. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/layout.js +37 -2
  49. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/main.js +28 -6
  50. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/pane.js +10 -3
  51. data/lib/frameworks/sproutcore/frameworks/core_foundation/protocols/sparse_array_delegate.js +2 -2
  52. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/browser.js +66 -2
  53. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/builder.js +1 -1
  54. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/cursor.js +1 -1
  55. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/event.js +58 -57
  56. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/locale.js +1 -1
  57. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/locale.js.orig +445 -0
  58. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/platform.js +51 -31
  59. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/ready.js +5 -1
  60. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/render_context.js +53 -69
  61. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/responder.js +1 -1
  62. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/root_responder.js +98 -72
  63. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/string.js +37 -3
  64. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/timer.js +7 -4
  65. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/controllers/array/array_case.js +21 -0
  66. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/controllers/object/content_destroyed.js +7 -7
  67. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/mixins/string.js +23 -1
  68. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/browser.js +66 -0
  69. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/event.js +22 -0
  70. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/locale.js +11 -11
  71. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/render_context/end.js +4 -4
  72. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/render_context/escape_html.js +41 -0
  73. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/render_context/helpers_className.js +1 -1
  74. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/render_context/helpers_style.js +8 -8
  75. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/render_context/update.js +17 -16
  76. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/selection_set/remove.js +1 -1
  77. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/build_children.js +1 -1
  78. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/class_name_bindings_test.js +15 -0
  79. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/createChildViews.js +5 -5
  80. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view.js +50 -30
  81. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/acceleration.js +46 -0
  82. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/animation.js +1 -43
  83. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/keyboard.js +8 -34
  84. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout.js +3 -2
  85. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout_style.js +10 -1
  86. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/manipulation.js +6 -5
  87. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/theming.js +22 -2
  88. data/lib/frameworks/sproutcore/frameworks/datastore/data_sources/data_source.js +2 -2
  89. data/lib/frameworks/sproutcore/frameworks/datastore/mixins/relationship_support.js +1 -1
  90. data/lib/frameworks/sproutcore/frameworks/datastore/models/child_attribute.js +0 -2
  91. data/lib/frameworks/sproutcore/frameworks/datastore/models/children_attribute.js +35 -0
  92. data/lib/frameworks/sproutcore/frameworks/datastore/models/record.js +46 -19
  93. data/lib/frameworks/sproutcore/frameworks/datastore/models/record_attribute.js +23 -9
  94. data/lib/frameworks/sproutcore/frameworks/datastore/models/single_attribute.js +2 -3
  95. data/lib/frameworks/sproutcore/frameworks/datastore/system/many_array.js +1 -1
  96. data/lib/frameworks/sproutcore/frameworks/datastore/system/nested_store.js +2 -2
  97. data/lib/frameworks/sproutcore/frameworks/datastore/system/query.js +294 -302
  98. data/lib/frameworks/sproutcore/frameworks/datastore/system/query.js.orig +1531 -0
  99. data/lib/frameworks/sproutcore/frameworks/datastore/system/record_array.js +4 -2
  100. data/lib/frameworks/sproutcore/frameworks/datastore/system/store.js +14 -11
  101. data/lib/frameworks/sproutcore/frameworks/datastore/tests/integration/many_array.js +63 -0
  102. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/many_attribute.js +1 -1
  103. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/nested_records/nested_record.js +4 -4
  104. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/nested_records/nested_record_array.js +50 -10
  105. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/nested_records/nested_record_array_complex.js +4 -4
  106. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/nested_records/nested_record_complex.js +3 -3
  107. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/record/destroy.js +1 -1
  108. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/record/refresh.js +1 -1
  109. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/record_attribute.js +1 -1
  110. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/single_attribute.js +114 -67
  111. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/commitChangesFromNestedStore.js +1 -1
  112. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/readDataHash.js +1 -1
  113. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/query/compare.js +54 -1
  114. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/query/evaluation.js +29 -9
  115. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/query/parse.js +1 -1
  116. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/record_array/core_methods.js +1 -1
  117. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/record_array/flush.js +1 -1
  118. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/cancelRecord.js +1 -1
  119. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/commitChangesFromNestedStore.js +1 -1
  120. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/commitRecord.js +37 -45
  121. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/find.js +127 -127
  122. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/pushChanges.js +16 -0
  123. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/pushRelationships.js +42 -4
  124. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/store/readDataHash.js +1 -1
  125. data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/core/system/datetime.js +13 -7
  126. data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/core/tests/system/datetime.js +8 -0
  127. data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/localized/resources/strings.js +2 -1
  128. data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/localized/system/datetime.js +1 -0
  129. data/lib/frameworks/sproutcore/frameworks/debug/core.js +3 -3
  130. data/lib/frameworks/sproutcore/frameworks/desktop/core.js +1 -1
  131. data/lib/frameworks/sproutcore/frameworks/desktop/mixins/collection_row_delegate.js +1 -1
  132. data/lib/frameworks/sproutcore/frameworks/desktop/mixins/collection_view_delegate.js +1 -1
  133. data/lib/frameworks/sproutcore/frameworks/desktop/panes/alert.js +1 -4
  134. data/lib/frameworks/sproutcore/frameworks/desktop/panes/menu.js +19 -6
  135. data/lib/frameworks/sproutcore/frameworks/desktop/panes/modal.js +30 -1
  136. data/lib/frameworks/sproutcore/frameworks/desktop/panes/palette.js +1 -1
  137. data/lib/frameworks/sproutcore/frameworks/desktop/panes/panel.js +24 -1
  138. data/lib/frameworks/sproutcore/frameworks/desktop/panes/picker.js +121 -28
  139. data/lib/frameworks/sproutcore/frameworks/desktop/panes/sheet.js +15 -15
  140. data/lib/frameworks/sproutcore/frameworks/desktop/protocols/drag_data_source.js +1 -1
  141. data/lib/frameworks/sproutcore/frameworks/desktop/protocols/drop_target.js +2 -2
  142. data/lib/frameworks/sproutcore/frameworks/desktop/protocols/responder.js +2 -2
  143. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/button.js +39 -15
  144. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/collection.js +3 -3
  145. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/disclosure.js +2 -2
  146. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/image_button.js +2 -2
  147. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/panel.js +14 -6
  148. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/popup_button.js +3 -3
  149. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/progress.js +11 -11
  150. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/segment.js +4 -3
  151. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/segmented.js +1 -51
  152. data/lib/frameworks/sproutcore/frameworks/desktop/render_delegates/slider.js +11 -16
  153. data/lib/frameworks/sproutcore/frameworks/desktop/resources/images/icons/sc-icon-error-48.png +0 -0
  154. data/lib/frameworks/sproutcore/frameworks/desktop/resources/slider.css +0 -2
  155. data/lib/frameworks/sproutcore/frameworks/desktop/system/drag.js +3 -3
  156. data/lib/frameworks/sproutcore/frameworks/desktop/system/undo_manager.js +3 -3
  157. data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/alert/ui.js +9 -9
  158. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/button/content.js +11 -11
  159. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/button/ui.js +2 -1
  160. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/collection/reload.js +1 -1
  161. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/date_field/ui.js +107 -81
  162. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/list/rowDelegate.js +3 -3
  163. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/progress/ui.js +68 -60
  164. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/radio/methods.js +57 -12
  165. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/scroll/integration.js +21 -19
  166. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/scroller.js +5 -0
  167. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/segmented/ui.js +2 -2
  168. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/select/ui.js +32 -3
  169. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/split/methods.js +12 -0
  170. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/stacked/ui_comments.js +12 -0
  171. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/tab/methods.js +0 -8
  172. data/lib/frameworks/sproutcore/frameworks/desktop/views/button.js +77 -132
  173. data/lib/frameworks/sproutcore/frameworks/desktop/views/checkbox.js +5 -6
  174. data/lib/frameworks/sproutcore/frameworks/desktop/views/collection.js +16 -15
  175. data/lib/frameworks/sproutcore/frameworks/desktop/views/date_field.js +52 -52
  176. data/lib/frameworks/sproutcore/frameworks/desktop/views/disclosure.js +1 -1
  177. data/lib/frameworks/sproutcore/frameworks/desktop/views/grid.js +1 -1
  178. data/lib/frameworks/sproutcore/frameworks/desktop/views/list.js +147 -147
  179. data/lib/frameworks/sproutcore/frameworks/desktop/views/list_item.js +11 -2
  180. data/lib/frameworks/sproutcore/frameworks/desktop/views/menu_item.js +2 -2
  181. data/lib/frameworks/sproutcore/frameworks/desktop/views/menu_scroll.js +5 -5
  182. data/lib/frameworks/sproutcore/frameworks/desktop/views/popup_button.js +22 -12
  183. data/lib/frameworks/sproutcore/frameworks/desktop/views/radio.js +13 -7
  184. data/lib/frameworks/sproutcore/frameworks/desktop/views/scene.js +2 -2
  185. data/lib/frameworks/sproutcore/frameworks/desktop/views/scroll.js +462 -441
  186. data/lib/frameworks/sproutcore/frameworks/desktop/views/scroller.js +48 -62
  187. data/lib/frameworks/sproutcore/frameworks/desktop/views/segment.js +22 -2
  188. data/lib/frameworks/sproutcore/frameworks/desktop/views/segmented.js +150 -32
  189. data/lib/frameworks/sproutcore/frameworks/desktop/views/select.js +104 -45
  190. data/lib/frameworks/sproutcore/frameworks/desktop/views/select_button.js +42 -20
  191. data/lib/frameworks/sproutcore/frameworks/desktop/views/slider.js +24 -24
  192. data/lib/frameworks/sproutcore/frameworks/desktop/views/split.js +148 -154
  193. data/lib/frameworks/sproutcore/frameworks/desktop/views/stacked.js +2 -2
  194. data/lib/frameworks/sproutcore/frameworks/desktop/views/static_content.js +2 -2
  195. data/lib/frameworks/sproutcore/frameworks/desktop/views/tab.js +8 -7
  196. data/lib/frameworks/sproutcore/frameworks/desktop/views/web.js +2 -2
  197. data/lib/frameworks/sproutcore/frameworks/experimental/Buildfile +2 -0
  198. data/lib/frameworks/sproutcore/frameworks/experimental/apps/greenhouse/controllers/files.js +1 -1
  199. data/lib/frameworks/sproutcore/frameworks/experimental/apps/greenhouse/controllers/library.js +1 -1
  200. data/lib/frameworks/sproutcore/frameworks/experimental/apps/greenhouse/controllers/targets.js +1 -1
  201. data/lib/frameworks/sproutcore/frameworks/experimental/apps/greenhouse/controllers/view_configs.js +1 -1
  202. data/lib/frameworks/sproutcore/frameworks/experimental/apps/greenhouse/mixins/drop_down.js +1 -1
  203. data/lib/frameworks/sproutcore/frameworks/experimental/apps/greenhouse/states/ready.js +1 -1
  204. data/lib/frameworks/sproutcore/frameworks/experimental/apps/greenhouse/views/plist_item.js +1 -1
  205. data/lib/frameworks/sproutcore/frameworks/experimental/apps/greenhouse/views/web.js +1 -1
  206. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/designer/controllers/page_design.js +2 -2
  207. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/designer/css/css_style_sheet.js +2 -2
  208. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/designer/designers/object_designer.js +1 -1
  209. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/designer/designers/view_designer.js +2 -2
  210. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/designer/mixins/snap_lines.js +3 -3
  211. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/designer/views/designer_drop_target.js +1 -1
  212. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/designer/views/drawing.js +21 -21
  213. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/designer/views/page_item_view.js +1 -1
  214. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/forms/views/form.js +59 -53
  215. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/views/menu/scroll.js +2 -2
  216. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/polymorphism/tests/models/polymorphism/simple.js +1 -1
  217. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/core_scroll.js +6 -6
  218. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/desktop/scroll.js +2 -2
  219. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/touch/scroll.js +2 -2
  220. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/ext/menu.js +14 -10
  221. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/ext/menu_item.js +17 -6
  222. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/views/popup_button.js +38 -14
  223. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/views/select.js +5 -13
  224. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/split_view/mixins/split_child.js +1 -1
  225. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/split_view/mixins/split_thumb.js +5 -3
  226. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/split_view/tests/children.js +19 -0
  227. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/split_view/tests/methods.js +20 -2
  228. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/split_view/tests/split_thumb.js +1 -1
  229. data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/split_view/views/split.js +35 -12
  230. data/lib/frameworks/sproutcore/frameworks/formatters/README +6 -0
  231. data/lib/frameworks/sproutcore/frameworks/formatters/english.lproj/strings.js +174 -0
  232. data/lib/frameworks/sproutcore/frameworks/formatters/formatters/date_formatter.js +351 -0
  233. data/lib/frameworks/sproutcore/frameworks/formatters/tests/date_formatter.js +517 -0
  234. data/lib/frameworks/sproutcore/frameworks/foundation/core.js +1 -1
  235. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/auto_resize.js +345 -138
  236. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/button.js +5 -3
  237. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/content_value_support.js +176 -42
  238. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/editable.js +1 -1
  239. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/flowed_layout.js +137 -105
  240. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/gestureable.js +2 -2
  241. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/inline_editable.js +2 -2
  242. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/inline_editor.js +16 -1
  243. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/static_layout.js +1 -1
  244. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/validatable.js +47 -47
  245. data/lib/frameworks/sproutcore/frameworks/foundation/private/tree_item_observer.js +3 -3
  246. data/lib/frameworks/sproutcore/frameworks/foundation/render_delegates/helpers/sizing.js +1 -1
  247. data/lib/frameworks/sproutcore/frameworks/foundation/render_delegates/label.js +28 -6
  248. data/lib/frameworks/sproutcore/frameworks/foundation/render_delegates/render_delegate.js +1 -1
  249. data/lib/frameworks/sproutcore/frameworks/foundation/resources/benchmark.css +0 -5
  250. data/lib/frameworks/sproutcore/frameworks/foundation/resources/bootstrap.rhtml +34 -19
  251. data/lib/frameworks/sproutcore/frameworks/foundation/resources/button_view.css +0 -2
  252. data/lib/frameworks/sproutcore/frameworks/foundation/resources/label.css +1 -5
  253. data/lib/frameworks/sproutcore/frameworks/foundation/resources/text_field.css +8 -9
  254. data/lib/frameworks/sproutcore/frameworks/foundation/system/benchmark.js +2 -2
  255. data/lib/frameworks/sproutcore/frameworks/foundation/system/module.js +179 -47
  256. data/lib/frameworks/sproutcore/frameworks/foundation/system/task_queue.js +34 -1
  257. data/lib/frameworks/sproutcore/frameworks/foundation/system/text_selection.js +1 -1
  258. data/lib/frameworks/sproutcore/frameworks/foundation/system/user_defaults.js +26 -12
  259. data/lib/frameworks/sproutcore/frameworks/foundation/system/utils/misc.js +7 -7
  260. data/lib/frameworks/sproutcore/frameworks/foundation/system/utils/string_measurement.js +12 -4
  261. data/lib/frameworks/sproutcore/frameworks/foundation/system/utils/string_metric_optimization.js +202 -0
  262. data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/content_value_support/content.js +77 -8
  263. data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/flowed_layout/tests.js +1 -0
  264. data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/inline_editable/beginEditing.js +2 -2
  265. data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/inline_editable/commitEditing.js +4 -3
  266. data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/inline_editable/discardEditing.js +4 -2
  267. data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/inline_editor/beginEditing.js +2 -2
  268. data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/inline_editor/commitEditing.js +4 -2
  269. data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/inline_editor/discardEditing.js +4 -2
  270. data/lib/frameworks/sproutcore/frameworks/foundation/tests/system/utils/pointInElement.js +2 -2
  271. data/lib/frameworks/sproutcore/frameworks/foundation/tests/views/label/ui.js +0 -8
  272. data/lib/frameworks/sproutcore/frameworks/foundation/tests/views/text_field/ui.js +163 -149
  273. data/lib/frameworks/sproutcore/frameworks/foundation/validators/credit_card.js +1 -1
  274. data/lib/frameworks/sproutcore/frameworks/foundation/validators/date.js +1 -1
  275. data/lib/frameworks/sproutcore/frameworks/foundation/validators/date_time.js +1 -1
  276. data/lib/frameworks/sproutcore/frameworks/foundation/validators/password.js +1 -1
  277. data/lib/frameworks/sproutcore/frameworks/foundation/validators/validator.js +3 -3
  278. data/lib/frameworks/sproutcore/frameworks/foundation/views/field.js +16 -43
  279. data/lib/frameworks/sproutcore/frameworks/foundation/views/image.js +4 -3
  280. data/lib/frameworks/sproutcore/frameworks/foundation/views/inline_text_field.js +67 -54
  281. data/lib/frameworks/sproutcore/frameworks/foundation/views/label.js +49 -38
  282. data/lib/frameworks/sproutcore/frameworks/foundation/views/text_field.js +285 -242
  283. data/lib/frameworks/sproutcore/frameworks/jquery/jquery-buffer.js +13 -13
  284. data/lib/frameworks/sproutcore/frameworks/jquery/jquery-buffered.js +19 -22
  285. data/lib/frameworks/sproutcore/frameworks/jquery/jquery-sc.js +9 -3
  286. data/lib/frameworks/sproutcore/frameworks/jquery/jquery.js +231 -186
  287. data/lib/frameworks/sproutcore/frameworks/media/views/audio.js +145 -143
  288. data/lib/frameworks/sproutcore/frameworks/media/views/video.js +156 -154
  289. data/lib/frameworks/sproutcore/frameworks/qunit/qunit/qunit.js +5 -5
  290. data/lib/frameworks/sproutcore/frameworks/routing/system/routes.js +3 -3
  291. data/lib/frameworks/sproutcore/frameworks/routing/system/routes.js.orig +540 -0
  292. data/lib/frameworks/sproutcore/frameworks/routing/tests/system/routes.js +2 -2
  293. data/lib/frameworks/sproutcore/frameworks/runtime/core.js +15 -8
  294. data/lib/frameworks/sproutcore/frameworks/runtime/debug/test_suites/array/base.js +5 -5
  295. data/lib/frameworks/sproutcore/frameworks/runtime/debug/test_suites/array/replace.js +12 -0
  296. data/lib/frameworks/sproutcore/frameworks/runtime/ext/function.js +2 -2
  297. data/lib/frameworks/sproutcore/frameworks/runtime/mixins/array.js +1 -1
  298. data/lib/frameworks/sproutcore/frameworks/runtime/mixins/copyable.js +1 -1
  299. data/lib/frameworks/sproutcore/frameworks/runtime/mixins/enumerable.js +7 -7
  300. data/lib/frameworks/sproutcore/frameworks/runtime/mixins/observable.js +98 -32
  301. data/lib/frameworks/sproutcore/frameworks/runtime/private/chain_observer.js +7 -2
  302. data/lib/frameworks/sproutcore/frameworks/runtime/private/observer_queue.js +14 -3
  303. data/lib/frameworks/sproutcore/frameworks/runtime/private/observer_set.js +98 -13
  304. data/lib/frameworks/sproutcore/frameworks/runtime/system/binding.js +8 -14
  305. data/lib/frameworks/sproutcore/frameworks/runtime/system/enumerator.js +1 -1
  306. data/lib/frameworks/sproutcore/frameworks/runtime/system/error.js +2 -2
  307. data/lib/frameworks/sproutcore/frameworks/runtime/system/index_set.js +23 -6
  308. data/lib/frameworks/sproutcore/frameworks/runtime/system/logger.js +69 -18
  309. data/lib/frameworks/sproutcore/frameworks/runtime/system/object.js +57 -31
  310. data/lib/frameworks/sproutcore/frameworks/runtime/system/run_loop.js +189 -14
  311. data/lib/frameworks/sproutcore/frameworks/runtime/system/string.js +82 -22
  312. data/lib/frameworks/sproutcore/frameworks/runtime/tests/mixins/observable/chained.js +20 -0
  313. data/lib/frameworks/sproutcore/frameworks/runtime/tests/mixins/observable/observable.js +125 -4
  314. data/lib/frameworks/sproutcore/frameworks/runtime/tests/private/observer_queue.js +1 -1
  315. data/lib/frameworks/sproutcore/frameworks/runtime/tests/system/binding.js +2 -2
  316. data/lib/frameworks/sproutcore/frameworks/runtime/tests/system/index_set/rangeStartForIndex.js +37 -0
  317. data/lib/frameworks/sproutcore/frameworks/runtime/tests/system/index_set/remove.js +2 -2
  318. data/lib/frameworks/sproutcore/frameworks/runtime/tests/system/logger.js +16 -0
  319. data/lib/frameworks/sproutcore/frameworks/runtime/tests/system/run_loop.js +75 -4
  320. data/lib/frameworks/sproutcore/frameworks/runtime/tests/system/string.js +41 -0
  321. data/lib/frameworks/sproutcore/frameworks/statechart/mixins/statechart_delegate.js +113 -0
  322. data/lib/frameworks/sproutcore/frameworks/statechart/private/state_path_matcher.js +312 -0
  323. data/lib/frameworks/sproutcore/frameworks/statechart/system/async.js +18 -22
  324. data/lib/frameworks/sproutcore/frameworks/statechart/system/state.js +508 -131
  325. data/lib/frameworks/sproutcore/frameworks/statechart/system/state_route_handler_context.js +78 -0
  326. data/lib/frameworks/sproutcore/frameworks/statechart/system/statechart.js +265 -44
  327. data/lib/frameworks/sproutcore/frameworks/statechart/tests/event_handling/basic/with_concurrent_states.js +16 -0
  328. data/lib/frameworks/sproutcore/frameworks/statechart/tests/event_handling/responder/responder_chain.js +11 -3
  329. data/lib/frameworks/sproutcore/frameworks/statechart/tests/private/state_path_matcher.js +116 -0
  330. data/lib/frameworks/sproutcore/frameworks/statechart/tests/state/methods/add_substate.js +108 -0
  331. data/lib/frameworks/sproutcore/frameworks/statechart/tests/state/methods/find_first_relative_current_state/with_concurrent.js +179 -0
  332. data/lib/frameworks/sproutcore/frameworks/statechart/tests/state/methods/find_first_relative_current_state/without_concurrent.js +74 -0
  333. data/lib/frameworks/sproutcore/frameworks/statechart/tests/state/methods/get_state.js +141 -0
  334. data/lib/frameworks/sproutcore/frameworks/statechart/tests/state/methods/get_substate.js +340 -0
  335. data/lib/frameworks/sproutcore/frameworks/statechart/tests/state/methods/route_triggered.js +161 -0
  336. data/lib/frameworks/sproutcore/frameworks/statechart/tests/state/methods/try_to_handle_event.js +288 -0
  337. data/lib/frameworks/sproutcore/frameworks/statechart/tests/state_transitioning/history_state/standard/without_concurrent_states/context.js +5 -33
  338. data/lib/frameworks/sproutcore/frameworks/statechart/tests/state_transitioning/routing/with_concurrent_states/basic.js +213 -0
  339. data/lib/frameworks/sproutcore/frameworks/statechart/tests/state_transitioning/routing/without_concurrent_states/basic.js +212 -0
  340. data/lib/frameworks/sproutcore/frameworks/statechart/tests/state_transitioning/standard/without_concurrent_states/core.js +8 -0
  341. data/lib/frameworks/sproutcore/frameworks/statechart/tests/{state/namespacing.js → statechart/methods/get_state.js} +3 -41
  342. data/lib/frameworks/sproutcore/frameworks/statechart/tests/statechart/{invoke_state_method.js → methods/invoke_state_method.js} +1 -1
  343. data/lib/frameworks/sproutcore/frameworks/statechart/tests/{event_handling/advanced → statechart}/respond_to_event.js +1 -1
  344. data/lib/frameworks/sproutcore/frameworks/statechart/tests/system/state_route_handler_context/methods/retry.js +64 -0
  345. data/lib/frameworks/sproutcore/frameworks/table/core.js +2 -0
  346. data/lib/frameworks/sproutcore/frameworks/{core_foundation → template_view}/controls/button.js +0 -1
  347. data/lib/frameworks/sproutcore/frameworks/{core_foundation → template_view}/ext/handlebars.js +29 -5
  348. data/lib/frameworks/sproutcore/frameworks/{core_foundation → template_view}/ext/handlebars/bind.js +4 -3
  349. data/lib/frameworks/sproutcore/frameworks/{core_foundation → template_view}/ext/handlebars/collection.js +0 -0
  350. data/lib/frameworks/sproutcore/frameworks/{core_foundation → template_view}/ext/handlebars/localization.js +0 -0
  351. data/lib/frameworks/sproutcore/frameworks/{core_foundation → template_view}/ext/handlebars/view.js +0 -0
  352. data/lib/frameworks/sproutcore/frameworks/{handlebars → template_view}/handlebars.js +493 -357
  353. data/lib/frameworks/sproutcore/frameworks/{core_foundation → template_view}/mixins/template_helpers/checkbox_support.js +0 -0
  354. data/lib/frameworks/sproutcore/frameworks/{core_foundation → template_view}/mixins/template_helpers/text_field_support.js +13 -2
  355. data/lib/frameworks/sproutcore/frameworks/{core_foundation → template_view}/panes/template.js +0 -0
  356. data/lib/frameworks/sproutcore/frameworks/{core_foundation → template_view}/tests/controls/button.js +0 -0
  357. data/lib/frameworks/sproutcore/frameworks/{core_foundation → template_view}/tests/mixins/template_helpers/checkbox_support.js +0 -0
  358. data/lib/frameworks/sproutcore/frameworks/{core_foundation → template_view}/tests/mixins/template_helpers/text_field_support.js +0 -0
  359. data/lib/frameworks/sproutcore/frameworks/{core_foundation → template_view}/tests/panes/template.js +0 -0
  360. data/lib/frameworks/sproutcore/frameworks/{core_foundation → template_view}/tests/views/template/collection.js +39 -14
  361. data/lib/frameworks/sproutcore/frameworks/{core_foundation → template_view}/tests/views/template/core.js +0 -0
  362. data/lib/frameworks/sproutcore/frameworks/{core_foundation → template_view}/tests/views/template/handlebars.js +57 -6
  363. data/lib/frameworks/sproutcore/frameworks/{core_foundation → template_view}/views/bindable_span.js +21 -6
  364. data/lib/frameworks/sproutcore/frameworks/{core_foundation → template_view}/views/template.js +9 -3
  365. data/lib/frameworks/sproutcore/frameworks/{core_foundation → template_view}/views/template_collection.js +55 -26
  366. data/lib/frameworks/sproutcore/frameworks/testing/system/equiv.js +1 -1
  367. data/lib/frameworks/sproutcore/frameworks/testing/system/plan.js +122 -122
  368. data/lib/frameworks/sproutcore/frameworks/testing/system/runner.js +2 -2
  369. data/lib/frameworks/sproutcore/frameworks/testing/system/suite.js +4 -4
  370. data/lib/frameworks/sproutcore/frameworks/yuireset/resources/base.css +1 -1
  371. data/lib/frameworks/sproutcore/frameworks/yuireset/resources/reset.css +0 -1
  372. data/lib/frameworks/sproutcore/frameworks/yuireset/resources/view.css +4 -4
  373. data/lib/frameworks/sproutcore/lib/index.rhtml +55 -32
  374. data/lib/frameworks/sproutcore/license.js +2 -4
  375. data/lib/frameworks/sproutcore/themes/ace/resources/body.css +5 -1
  376. data/lib/frameworks/sproutcore/themes/ace/resources/button/ace/18px/button.css +2 -2
  377. data/lib/frameworks/sproutcore/themes/ace/resources/button/ace/24px/button.css +21 -13
  378. data/lib/frameworks/sproutcore/themes/ace/resources/button/ace/30px/button.css +17 -10
  379. data/lib/frameworks/sproutcore/themes/ace/resources/button/ace/44px/button.css +4 -3
  380. data/lib/frameworks/sproutcore/themes/ace/resources/button/dark/24px/button.css +20 -12
  381. data/lib/frameworks/sproutcore/themes/ace/resources/button/dark/30px/button.css +16 -8
  382. data/lib/frameworks/sproutcore/themes/ace/resources/button/dark/jumbo/button.css +17 -0
  383. data/lib/frameworks/sproutcore/themes/ace/resources/button/dark/small/button.css +17 -0
  384. data/lib/frameworks/sproutcore/themes/ace/resources/disclosure/ace/disclosure.css +2 -2
  385. data/lib/frameworks/sproutcore/themes/ace/resources/master-detail/master-detail.css +2 -2
  386. data/lib/frameworks/sproutcore/themes/ace/resources/picker/popover/popover.css +5 -3
  387. data/lib/frameworks/sproutcore/themes/iphone_theme/english.lproj/core.css +1 -1
  388. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/toolbar.css +1 -1
  389. data/lib/gen/app/USAGE +17 -4
  390. data/lib/gen/language/Buildfile +4 -4
  391. data/lib/gen/language/USAGE +4 -4
  392. data/lib/gen/page/templates/pages/@target_name@/Buildfile +7 -7
  393. data/lib/gen/{html_app → statechart_app}/Buildfile +0 -0
  394. data/lib/gen/{html_app → statechart_app}/README +0 -0
  395. data/lib/gen/statechart_app/USAGE +21 -0
  396. data/lib/gen/statechart_app/templates/apps/@target_name@/Buildfile +9 -0
  397. data/lib/gen/statechart_app/templates/apps/@target_name@/core.js +24 -0
  398. data/lib/gen/statechart_app/templates/apps/@target_name@/main.js +26 -0
  399. data/lib/gen/statechart_app/templates/apps/@target_name@/resources/_theme.css +18 -0
  400. data/lib/gen/statechart_app/templates/apps/@target_name@/resources/loading.rhtml +9 -0
  401. data/lib/gen/statechart_app/templates/apps/@target_name@/resources/main_page.js +21 -0
  402. data/lib/gen/statechart_app/templates/apps/@target_name@/statechart.js +8 -0
  403. data/lib/gen/statechart_app/templates/apps/@target_name@/states/ready_state.js +12 -0
  404. data/lib/gen/statechart_app/templates/apps/@target_name@/theme.js +24 -0
  405. data/lib/sproutcore/builders.rb +1 -0
  406. data/lib/sproutcore/builders/base.rb +19 -1
  407. data/lib/sproutcore/builders/chance_file.rb +6 -1
  408. data/lib/sproutcore/builders/handlebars.rb +1 -9
  409. data/lib/sproutcore/builders/javascript.rb +1 -10
  410. data/lib/sproutcore/builders/json.rb +25 -0
  411. data/lib/sproutcore/builders/less.rb +1 -1
  412. data/lib/sproutcore/builders/sass.rb +1 -1
  413. data/lib/sproutcore/builders/stylesheet.rb +1 -9
  414. data/lib/sproutcore/helpers/html5_manifest.rb +1 -1
  415. data/lib/sproutcore/helpers/static_helper.rb +42 -0
  416. data/lib/sproutcore/rack/proxy.rb +21 -3
  417. data/lib/sproutcore/rack/service.rb +3 -2
  418. data/lib/sproutcore/tools.rb +18 -25
  419. data/lib/sproutcore/tools/gen.rb +10 -3
  420. data/lib/sproutcore/tools/init.rb +11 -10
  421. data/spec/buildtasks/manifest/prepare_build_tasks/json_spec.rb +62 -0
  422. data/spec/fixtures/builder_tests/apps/handlebars_test/Buildfile +1 -1
  423. data/spec/fixtures/builder_tests/apps/json_test/sc_static.json +2 -0
  424. data/spec/lib/builders/json_spec.rb +53 -0
  425. data/sproutcore.gemspec +2 -2
  426. data/vendor/chance/lib/chance/parser.rb +1 -1
  427. metadata +222 -177
  428. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/datetime.js +0 -0
  429. data/lib/frameworks/sproutcore/frameworks/debug/invoke_once_last_debugging.js +0 -259
  430. data/lib/frameworks/sproutcore/frameworks/documentation/core.js +0 -0
  431. data/lib/frameworks/sproutcore/frameworks/foundation/system/chance.js +0 -69
  432. data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/editable/ui.js +0 -44
  433. data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/inline_text_field/ui.js +0 -64
  434. data/lib/frameworks/sproutcore/frameworks/mini/license.js +0 -30
  435. data/lib/gen/html_app/USAGE +0 -15
  436. data/lib/gen/html_app/templates/apps/@target_name@/@target_name@.js +0 -11
  437. data/lib/gen/html_app/templates/apps/@target_name@/resources/images/.gitkeep +0 -0
  438. data/lib/gen/html_app/templates/apps/@target_name@/resources/stylesheets/@target_name@.css +0 -6
  439. data/lib/gen/html_app/templates/apps/@target_name@/resources/templates/@target_name@.handlebars +0 -1
  440. data/lib/gen/html_project/Buildfile +0 -45
  441. data/lib/gen/html_project/INIT +0 -3
  442. data/lib/gen/html_project/README +0 -1
  443. data/lib/gen/html_project/USAGE +0 -2
  444. data/lib/gen/html_project/templates/@filename@/Buildfile +0 -5
  445. data/lib/gen/html_project/templates/@filename@/README +0 -4
@@ -19,13 +19,13 @@
19
19
  */
20
20
  SC.Async = SC.Object.extend(
21
21
  /** @scope SC.Async.prototype */{
22
-
22
+
23
23
  func: null,
24
-
24
+
25
25
  arg1: null,
26
-
26
+
27
27
  arg2: null,
28
-
28
+
29
29
  /** @private
30
30
  Called by the statechart
31
31
  */
@@ -34,49 +34,45 @@ SC.Async = SC.Object.extend(
34
34
  arg1 = this.get('arg1'),
35
35
  arg2 = this.get('arg2'),
36
36
  funcType = SC.typeOf(func);
37
-
37
+
38
38
  if (funcType === SC.T_STRING) {
39
39
  state.tryToPerform(func, arg1, arg2);
40
- }
40
+ }
41
41
  else if (funcType === SC.T_FUNCTION) {
42
42
  func.apply(state, [arg1, arg2]);
43
43
  }
44
44
  }
45
-
45
+
46
46
  });
47
47
 
48
48
  /**
49
49
  Singleton
50
50
  */
51
51
  SC.Async.mixin(/** @scope SC.Async */{
52
-
52
+
53
53
  /**
54
54
  Call in either a state's enterState or exitState method when you
55
55
  want a state to perform an asynchronous action, such as an animation.
56
-
56
+
57
57
  Examples:
58
-
59
- {{
60
-
58
+
61
59
  SC.State.extend({
62
-
60
+
63
61
  enterState: function() {
64
62
  return SC.Async.perform('foo');
65
63
  },
66
-
64
+
67
65
  exitState: function() {
68
66
  return SC.Async.perform('bar', 100);
69
67
  }
70
-
68
+
71
69
  foo: function() { ... },
72
-
70
+
73
71
  bar: function(arg) { ... }
74
-
72
+
75
73
  });
76
-
77
- }}
78
-
79
- @param func {String|Function} the functio to be invoked on a state
74
+
75
+ @param func {String|Function} the function to be invoked on a state
80
76
  @param arg1 Optional. An argument to pass to the given function
81
77
  @param arg2 Optional. An argument to pass to the given function
82
78
  @return {SC.Async} a new instance of a SC.Async
@@ -84,5 +80,5 @@ SC.Async.mixin(/** @scope SC.Async */{
84
80
  perform: function(func, arg1, arg2) {
85
81
  return SC.Async.create({ func: func, arg1: arg1, arg2: arg2 });
86
82
  }
87
-
83
+
88
84
  });
@@ -110,6 +110,25 @@ SC.State = SC.Object.extend(
110
110
  */
111
111
  enteredSubstates: null,
112
112
 
113
+ /**
114
+ Can optionally assign what route this state is to represent.
115
+
116
+ If assigned then this state will be notified to handle the route when triggered
117
+ any time the app's location changes and matches this state's assigned route.
118
+ The handler invoked is this state's {@link #routeTriggered} method.
119
+
120
+ The value assigned to this property is dependent on the underlying routing
121
+ mechanism used by the application. The default routing mechanism is to use
122
+ SC.routes.
123
+
124
+ @property {String|Hash}
125
+
126
+ @see #routeTriggered
127
+ @see #location
128
+ @see SC.StatechartDelegate
129
+ */
130
+ representRoute: null,
131
+
113
132
  /**
114
133
  Indicates if this state should trace actions. Useful for debugging
115
134
  purposes. Managed by the statechart.
@@ -139,6 +158,49 @@ SC.State = SC.Object.extend(
139
158
  return owner ? owner : sc;
140
159
  }.property().cacheable(),
141
160
 
161
+ /**
162
+ Returns the statechart's assigned delegate. A statechart delegate is one
163
+ that adheres to the {@link SC.StatechartDelegate} mixin.
164
+
165
+ @property {SC.Object}
166
+
167
+ @see SC.StatechartDelegate
168
+ */
169
+ statechartDelegate: function() {
170
+ return this.getPath('statechart.statechartDelegate');
171
+ }.property().cacheable(),
172
+
173
+ /**
174
+ A volatile property used to get and set the app's current location.
175
+
176
+ This computed property defers to the the statechart's delegate to
177
+ actually update and acquire the app's location.
178
+
179
+ Note: Binding for this pariticular case is discouraged since in most
180
+ cases we need the location value immediately. If we were to use
181
+ bindings then the location value wouldn't be updated until at least
182
+ the end of one run loop. It is also advised that the delegate not
183
+ have its `statechartUpdateLocationForState` and
184
+ `statechartAcquireLocationForState` methods implemented where bindings
185
+ are used since they will inadvertenly stall the location value from
186
+ propogating immediately.
187
+
188
+ @property {String}
189
+
190
+ @see SC.StatechartDelegate#statechartUpdateLocationForState
191
+ @see SC.StatechartDelegate#statechartAcquireLocationForState
192
+ */
193
+ location: function(key, value) {
194
+ var sc = this.get('statechart'),
195
+ del = this.get('statechartDelegate');
196
+
197
+ if (value !== undefined) {
198
+ del.statechartUpdateLocationForState(sc, value, this);
199
+ }
200
+
201
+ return del.statechartAcquireLocationForState(sc, this);
202
+ }.property().idempotent(),
203
+
142
204
  init: function() {
143
205
  sc_super();
144
206
 
@@ -146,9 +208,14 @@ SC.State = SC.Object.extend(
146
208
  this._registeredStringEventHandlers = {};
147
209
  this._registeredRegExpEventHandlers = [];
148
210
  this._registeredStateObserveHandlers = {};
211
+ this._registeredSubstatePaths = {};
212
+ this._registeredSubstates = [];
213
+ this._isEnteringState = NO;
214
+ this._isExitingState = NO;
149
215
 
150
216
  // Setting up observes this way is faster then using .observes,
151
217
  // which adds a noticable increase in initialization time.
218
+
152
219
  var sc = this.get('statechart'),
153
220
  ownerKey = sc ? sc.get('statechartOwnerKey') : null,
154
221
  traceKey = sc ? sc.get('statechartTraceKey') : null;
@@ -168,13 +235,13 @@ SC.State = SC.Object.extend(
168
235
  sc.removeObserver(ownerKey, this, '_statechartOwnerDidChange');
169
236
  sc.removeObserver(traceKey, this, '_statechartTraceDidChange');
170
237
  }
171
-
238
+
172
239
  var substates = this.get('substates');
173
240
  if (substates) {
174
241
  substates.forEach(function(state) {
175
242
  state.destroy();
176
243
  });
177
- }
244
+ }
178
245
 
179
246
  this._teardownAllStateObserveHandlers();
180
247
 
@@ -193,6 +260,8 @@ SC.State = SC.Object.extend(
193
260
  this._registeredStringEventHandlers = null;
194
261
  this._registeredRegExpEventHandlers = null;
195
262
  this._registeredStateObserveHandlers = null;
263
+ this._registeredSubstatePaths = null;
264
+ this._registeredSubstates = null;
196
265
 
197
266
  sc_super();
198
267
  },
@@ -204,6 +273,7 @@ SC.State = SC.Object.extend(
204
273
  if (this.get('stateIsInitialized')) return;
205
274
 
206
275
  this._registerWithParentStates();
276
+ this._setupRouteHandling();
207
277
 
208
278
  var key = null,
209
279
  value = null,
@@ -217,9 +287,11 @@ SC.State = SC.Object.extend(
217
287
  len = 0,
218
288
  valueIsFunc = NO,
219
289
  historyState = null;
290
+
291
+ this.set('substates', substates);
220
292
 
221
293
  if (SC.kindOf(initialSubstate, SC.HistoryState) && initialSubstate.isClass) {
222
- historyState = this.createHistoryState(initialSubstate, { parentState: this, statechart: statechart });
294
+ historyState = this.createSubstate(initialSubstate);
223
295
  this.set('initialSubstate', historyState);
224
296
 
225
297
  if (SC.none(historyState.get('defaultState'))) {
@@ -250,10 +322,7 @@ SC.State = SC.Object.extend(
250
322
  }
251
323
 
252
324
  if (SC.kindOf(value, SC.State) && value.isClass && this[key] !== this.constructor) {
253
- state = this.createSubstate(value, { name: key, parentState: this, statechart: statechart });
254
- substates.push(state);
255
- this[key] = state;
256
- state.initState();
325
+ state = this._addSubstate(key, value);
257
326
  if (key === initialSubstate) {
258
327
  this.set('initialSubstate', state);
259
328
  matchedInitialSubstate = YES;
@@ -274,45 +343,224 @@ SC.State = SC.Object.extend(
274
343
  }
275
344
  }
276
345
  else if (substates.length > 0) {
277
- if (SC.none(initialSubstate) && !substatesAreConcurrent) {
278
- state = this.createEmptyState({ parentState: this, statechart: statechart });
279
- this.set('initialSubstate', state);
280
- substates.push(state);
281
- this[state.get('name')] = state;
282
- state.initState();
283
- this.stateLogWarning("state %@ has no initial substate defined. Will default to using an empty state as initial substate".fmt(this));
284
- }
285
- else if (!SC.none(initialSubstate) && substatesAreConcurrent) {
346
+ state = this._addEmptyInitialSubstateIfNeeded();
347
+ if (!state && initialSubstate && substatesAreConcurrent) {
286
348
  this.set('initialSubstate', null);
287
349
  this.stateLogWarning("Can not use %@ as initial substate since substates are all concurrent for state %@".fmt(initialSubstate, this));
288
350
  }
289
351
  }
290
352
 
291
- this.set('substates', substates);
353
+ this.notifyPropertyChange('substates');
292
354
  this.set('currentSubstates', []);
293
355
  this.set('enteredSubstates', []);
294
356
  this.set('stateIsInitialized', YES);
295
357
  },
296
358
 
359
+ /** @private
360
+
361
+ Used to bind this state with a route this state is to represent if a route has been assigned.
362
+
363
+ When invoked, the method will delegate the actual binding strategy to the statechart delegate
364
+ via the delegate's {@link SC.StatechartDelegate#statechartBindStateToRoute} method.
365
+
366
+ Note that a state cannot be bound to a route if this state is a concurrent state.
367
+
368
+ @see #representRoute
369
+ @see SC.StatechartDelegate#statechartBindStateToRoute
370
+ */
371
+ _setupRouteHandling: function() {
372
+ var route = this.get('representRoute'),
373
+ sc = this.get('statechart'),
374
+ del = this.get('statechartDelegate');
375
+
376
+ if (!route) return;
377
+
378
+ if (this.get('isConcurrentState')) {
379
+ this.stateLogError("State %@ cannot handle route '%@' since state is concurrent".fmt(this, route));
380
+ return;
381
+ }
382
+
383
+ del.statechartBindStateToRoute(sc, this, route, this.routeTriggered);
384
+ },
385
+
386
+ /**
387
+ Main handler that gets triggered whenever the app's location matches this state's assigned
388
+ route.
389
+
390
+ When invoked the handler will first refer to the statechart delegate to determine if it
391
+ should actually handle the route via the delegate's
392
+ {@see SC.StatechartDelegate#statechartShouldStateHandleTriggeredRoute} method. If the
393
+ delegate allows the handling of the route then the state will continue on with handling
394
+ the triggered route by calling the state's {@link #handleTriggeredRoute} method, otherwise
395
+ the state will cancel the handling and inform the delegate through the delegate's
396
+ {@see SC.StatechartDelegate#statechartStateCancelledHandlingRoute} method.
397
+
398
+ The handler will create a state route context ({@link SC.StateRouteContext}) object
399
+ that packages information about what is being currently handled. This context object gets
400
+ passed along to the delegate's invoked methods as well as the state transition process.
401
+
402
+ Note that this method is not intended to be directly called or overridden.
403
+
404
+ @see #representRoute
405
+ @see SC.StatechartDelegate#statechartShouldStateHandleRoute
406
+ @see SC.StatechartDelegate#statechartStateCancelledHandlingRoute
407
+ @see #createStateRouteHandlerContext
408
+ @see #handleTriggeredRoute
409
+ */
410
+ routeTriggered: function(params) {
411
+ if (this._isEnteringState) return;
412
+
413
+ var sc = this.get('statechart'),
414
+ del = this.get('statechartDelegate'),
415
+ loc = this.get('location');
416
+
417
+ var attr = {
418
+ state: this,
419
+ location: loc,
420
+ params: params,
421
+ handler: this.routeTriggered
422
+ };
423
+
424
+ var context = this.createStateRouteHandlerContext(attr);
425
+
426
+ if (del.statechartShouldStateHandleTriggeredRoute(sc, this, context)) {
427
+ if (this.get('trace') && loc) {
428
+ this.stateLogTrace("will handle route '%@'".fmt(loc));
429
+ }
430
+ this.handleTriggeredRoute(context);
431
+ } else {
432
+ del.statechartStateCancelledHandlingTriggeredRoute(sc, this, context);
433
+ }
434
+ },
435
+
297
436
  /**
298
- creates a substate for this state
437
+ Constructs a new instance of a state routing context object.
438
+
439
+ @param {Hash} attr attributes to apply to the constructed object
440
+ @return {SC.StateRouteContext}
441
+
442
+ @see #handleRoute
299
443
  */
300
- createSubstate: function(state, attrs) {
301
- return state.create(attrs);
444
+ createStateRouteHandlerContext: function(attr) {
445
+ return SC.StateRouteHandlerContext.create(attr);
302
446
  },
303
447
 
304
448
  /**
305
- Create a history state for this state
449
+ Invoked by this state's {@link #routeTriggered} method if the state is
450
+ actually allowed to handle the triggered route.
451
+
452
+ By default the method invokes a state transition to this state.
306
453
  */
307
- createHistoryState: function(state, attrs) {
308
- return state.create(attrs);
454
+ handleTriggeredRoute: function(context) {
455
+ this.gotoState(this, context);
456
+ },
457
+
458
+ /** @private */
459
+ _addEmptyInitialSubstateIfNeeded: function() {
460
+ var initialSubstate = this.get('initialSubstate'),
461
+ substatesAreConcurrent = this.get('substatesAreConcurrent');
462
+
463
+ if (initialSubstate || substatesAreConcurrent) return null;
464
+
465
+ var state = this.createSubstate(SC.EmptyState);
466
+ this.set('initialSubstate', state);
467
+ this.get('substates').push(state);
468
+ this[state.get('name')] = state;
469
+ state.initState();
470
+ this.stateLogWarning("state %@ has no initial substate defined. Will default to using an empty state as initial substate".fmt(this));
471
+ return state;
472
+ },
473
+
474
+ /** @private */
475
+ _addSubstate: function(name, state, attr) {
476
+ var substates = this.get('substates');
477
+
478
+ attr = SC.clone(attr) || {};
479
+ attr.name = name;
480
+ state = this.createSubstate(state, attr);
481
+ substates.push(state);
482
+ this[name] = state;
483
+ state.initState();
484
+ return state;
309
485
  },
310
486
 
311
487
  /**
312
- Create an empty state for this state's initial substate
488
+ Used to dynamically add a substate to this state. Once added successfully you
489
+ are then able to go to it from any other state within the owning statechart.
490
+
491
+ A couple of notes when adding a substate:
492
+
493
+ - If this state does not have any substates, then in addition to the
494
+ substate being added, an empty state will also be added and set as the
495
+ initial substate. To make the added substate the initial substate, set
496
+ this object's initialSubstate property.
497
+
498
+ - If this state is a current state, the added substate will not be entered.
499
+
500
+ - If this state is entered and its substates are concurrent, the added
501
+ substate will not be entered.
502
+
503
+ If this state is either entered or current and you'd like the added substate
504
+ to take affect, you will need to explicitly reenter this state by calling
505
+ its `reenter` method.
506
+
507
+ Be aware that the name of the state you are adding must not conflict with
508
+ the name of a property on this state or else you will get an error.
509
+ In addition, this state must be initialized to add substates.
510
+
511
+ @param {String} name a unique name for the given substate.
512
+ @param {SC.State} state a class that derives from `SC.State`
513
+ @param {Hash} [attr] liternal to be applied to the substate
514
+ @returns {SC.State} an instance of the given state class
313
515
  */
314
- createEmptyState: function(attrs) {
315
- return SC.EmptyState.create(attrs);
516
+ addSubstate: function(name, state, attr) {
517
+ if (SC.empty(name)) {
518
+ this.stateLogError("Can not add substate. name required");
519
+ return null;
520
+ }
521
+
522
+ if (this[name] !== undefined) {
523
+ this.stateLogError("Can not add substate '%@'. Already a defined property".fmt(name));
524
+ return null;
525
+ }
526
+
527
+ if (!this.get('stateIsInitialized')) {
528
+ this.stateLogError("Can not add substate '%@'. this state is not yet initialized".fmt(name));
529
+ return null;
530
+ }
531
+
532
+ var len = arguments.length;
533
+
534
+ if (len === 1) {
535
+ state = SC.State;
536
+ } else if (len === 2 && SC.typeOf(state) === SC.T_HASH) {
537
+ attr = state;
538
+ state = SC.State;
539
+ }
540
+
541
+ var stateIsValid = SC.kindOf(state, SC.State) && state.isClass;
542
+
543
+ if (!stateIsValid) {
544
+ this.stateLogError("Can not add substate '%@'. must provide a state class".fmt(name));
545
+ return null;
546
+ }
547
+
548
+ state = this._addSubstate(name, state, attr);
549
+ this._addEmptyInitialSubstateIfNeeded();
550
+ this.notifyPropertyChange('substates');
551
+
552
+ return state;
553
+ },
554
+
555
+ /**
556
+ creates a substate for this state
557
+ */
558
+ createSubstate: function(state, attr) {
559
+ attr = attr || {};
560
+ return state.create({
561
+ parentState: this,
562
+ statechart: this.get('statechart')
563
+ }, attr);
316
564
  },
317
565
 
318
566
  /** @private
@@ -384,7 +632,6 @@ SC.State = SC.Object.extend(
384
632
  this state with them.
385
633
  */
386
634
  _registerWithParentStates: function() {
387
- this._registerSubstate(this);
388
635
  var parent = this.get('parentState');
389
636
  while (!SC.none(parent)) {
390
637
  parent._registerSubstate(this);
@@ -399,25 +646,17 @@ SC.State = SC.Object.extend(
399
646
  var path = state.pathRelativeTo(this);
400
647
  if (SC.none(path)) return;
401
648
 
402
- // Create special private member variables to help
403
- // keep track of substates and access them.
404
- if (SC.none(this._registeredSubstatePaths)) {
405
- this._registeredSubstatePaths = {};
406
- this._registeredSubstates = [];
407
- }
408
-
409
649
  this._registeredSubstates.push(state);
410
650
 
411
651
  // Keep track of states based on their relative path
412
652
  // to this state.
413
653
  var regPaths = this._registeredSubstatePaths;
414
654
  if (regPaths[state.get('name')] === undefined) {
415
- regPaths[state.get('name')] = { __ki_paths__: [] };
655
+ regPaths[state.get('name')] = { };
416
656
  }
417
657
 
418
658
  var paths = regPaths[state.get('name')];
419
659
  paths[path] = state;
420
- paths.__ki_paths__.push(path);
421
660
  },
422
661
 
423
662
  /**
@@ -451,15 +690,37 @@ SC.State = SC.Object.extend(
451
690
  If the value is a state object, then the value will be returned if it is indeed
452
691
  a substate of this state, otherwise null is returned.
453
692
 
454
- If the given value is a string, then the string is assumed to be a path to a substate.
455
- The value is then parsed to find the closes match. If there is no match then null
456
- is returned. If there is more than one match then null is return and an error
457
- is generated indicating ambiguity of the given value.
693
+ If the given value is a string, then the string is assumed to be a path expression
694
+ to a substate. The value is then parsed to find the closes match. For path expression
695
+ syntax, refer to the {@link SC.StatePathMatcher} class.
696
+
697
+ If there is no match then null is returned. If there is more than one match then null
698
+ is return and an error is generated indicating ambiguity of the given value.
699
+
700
+ An optional callback can be provided to handle the scenario when either no
701
+ substate is found or there is more than one match. The callback is then given
702
+ the opportunity to further handle the outcome and return a result which the
703
+ getSubstate method will then return. The callback should have the following
704
+ signature:
705
+
706
+ function(state, value, paths)
707
+
708
+ - state: The state getState was invoked on
709
+ - value: The value supplied to getState
710
+ - paths: An array of substate paths that matched the given value
711
+
712
+ If there were no matches then `paths` is not provided to the callback.
458
713
 
459
- Note that when the value is a string, it is assumed to be a path relative to this
460
- state; not the root state of the statechart.
714
+ You can also optionally provide a target that the callback is invoked on. If no
715
+ target is provided then this state is used as the target.
716
+
717
+ @param value {State|String} used to identify a substate of this state
718
+ @param [callback] {Function} the callback
719
+ @param [target] {Object} the target
461
720
  */
462
- getSubstate: function(value) {
721
+ getSubstate: function(value, callback, target) {
722
+ if (!value) return null;
723
+
463
724
  var valueType = SC.typeOf(value);
464
725
 
465
726
  // If the value is an object then just check if the value is
@@ -473,107 +734,141 @@ SC.State = SC.Object.extend(
473
734
  return null;
474
735
  }
475
736
 
476
- // The value is a string. Therefore treat the value as a relative path to
477
- // a substate of this state.
478
-
479
- // Extract that last part of the string. Ex. 'foo' => 'foo', 'foo.bar' => 'bar'
480
- var matches = value.match(/(^|\.)(\w+)$/);
481
- if (!matches) return null;
737
+ var matcher = SC.StatePathMatcher.create({ state: this, expression: value }),
738
+ matches = [], key;
482
739
 
483
- // Get all the paths related to the matched value. If no paths then return null.
484
- var paths = this._registeredSubstatePaths[matches[2]];
485
- if (SC.none(paths)) return null;
486
-
487
- // Do a quick check to see if there is a path that exactly matches the given
488
- // value, and if so return the corresponding state
489
- var state = paths[value];
490
- if (!SC.none(state)) return state;
491
-
492
- // No exact match found. If the value given is a basic string with no ".", then check
493
- // if there is only one path containing that string. If so, return it. If there is
494
- // more than one path then it is ambiguous as to what state is trying to be reached.
495
- if (matches[1] === "") {
496
- if (paths.__ki_paths__.length === 1) return paths[paths.__ki_paths__[0]];
497
- if (paths.__ki_paths__.length > 1) {
498
- var msg = 'Can not find substate matching %@ in state %@. Ambiguous with the following: %@';
499
- this.stateLogError(msg.fmt(value, this, paths.__ki_paths__));
740
+ if (matcher.get('tokens').length === 0) return null;
741
+
742
+ var paths = this._registeredSubstatePaths[matcher.get('lastPart')];
743
+ if (!paths) return this._notifySubstateNotFound(callback, target, value);
744
+
745
+ for (key in paths) {
746
+ if (matcher.match(key)) {
747
+ matches.push(paths[key]);
500
748
  }
749
+ }
750
+
751
+ if (matches.length === 1) return matches[0];
752
+
753
+ if (matches.length > 1) {
754
+ var keys = [];
755
+ for (key in paths) { keys.push(key); }
756
+
757
+ if (callback) return this._notifySubstateNotFound(callback, target, value, keys);
758
+
759
+ var msg = "Can not find substate matching '%@' in state %@. Ambiguous with the following: %@";
760
+ this.stateLogError(msg.fmt(value, this.get('fullPath'), keys.join(', ')));
501
761
  }
502
762
 
503
- return null;
763
+ return this._notifySubstateNotFound(callback, target, value);
764
+ },
765
+
766
+ /** @private */
767
+ _notifySubstateNotFound: function(callback, target, value, keys) {
768
+ return callback ? callback.call(target || this, this, value, keys) : null;
504
769
  },
505
770
 
506
771
  /**
507
- Used to go to a state in the statechart either directly from this state if it is a current state,
508
- or from one of this state's current substates.
772
+ Will attempt to get a state relative to this state.
509
773
 
510
- Note that if the value given is a string, it will be assumed to be a path to a state. The path
511
- will be relative to the statechart's root state; not relative to this state.
774
+ A state is returned based on the following:
512
775
 
513
- Method can be called in the following ways:
776
+ 1. First check this state's substates for a match; and
777
+ 2. If no matching substate then attempt to get the state from
778
+ this state's parent state.
779
+
780
+ Therefore states are recursively traversed up to the root state
781
+ to identify a match, and if found is ultimately returned, otherwise
782
+ null is returned. In the case that the value supplied is ambiguous
783
+ an error message is returned.
514
784
 
515
- // With one argument
516
- gotoState(<state>)
517
-
518
- // With two arguments
519
- gotoState(<state>, <hash>)
520
-
521
- Where <state> is either a string or a SC.State object and <hash> is a regular JS hash object.
522
-
523
- @param state {SC.State|String} the state to go to
524
- @param context {Hash} Optional. context object that will be supplied to all states that are
525
- exited and entered during the state transition process
785
+ The value provided can either be a state object or a state path expression.
786
+ For path expression syntax, refer to the {@link SC.StatePathMatcher} class.
526
787
  */
527
- gotoState: function(state, context) {
528
- var fromState = null;
788
+ getState: function(value) {
789
+ if (value === this.get('name')) return this;
790
+ if (SC.kindOf(value, SC.State)) return value;
791
+ return this.getSubstate(value, this._handleSubstateNotFound);
792
+ },
793
+
794
+ /** @private */
795
+ _handleSubstateNotFound: function(state, value, keys) {
796
+ var parentState = this.get('parentState');
797
+
798
+ if (parentState) return parentState.getState(value);
529
799
 
530
- if (this.get('isCurrentState')) {
531
- fromState = this;
532
- } else if (this.get('hasCurrentSubstates')) {
533
- fromState = this.get('currentSubstates')[0];
800
+ if (keys) {
801
+ var msg = "Can not find state matching '%@'. Ambiguous with the following: %@";
802
+ this.stateLogError(msg.fmt(value, keys.join(', ')));
534
803
  }
535
804
 
536
- this.get('statechart').gotoState(state, fromState, context);
805
+ return null;
806
+ },
807
+
808
+ /**
809
+ Used to go to a state in the statechart either directly from this state if it is a current state,
810
+ or from the first relative current state from this state.
811
+
812
+ If the value given is a string then it is considered a state path expression. The path is then
813
+ used to find a state relative to this state based on rules of the {@link #getState} method.
814
+
815
+ @param value {SC.State|String} the state to go to
816
+ @param [context] {Hash|Object} context object that will be supplied to all states that are
817
+ exited and entered during the state transition process. Context can not be an instance of
818
+ SC.State.
819
+ */
820
+ gotoState: function(value, context) {
821
+ var state = this.getState(value);
822
+
823
+ if (!state) {
824
+ var msg = "can not go to state %@ from state %@. Invalid value.";
825
+ this.stateLogError(msg.fmt(value, this));
826
+ return;
827
+ }
828
+
829
+ var from = this.findFirstRelativeCurrentState(state);
830
+ this.get('statechart').gotoState(state, from, false, context);
537
831
  },
538
832
 
539
833
  /**
540
834
  Used to go to a given state's history state in the statechart either directly from this state if it
541
835
  is a current state or from one of this state's current substates.
542
836
 
543
- Note that if the value given is a string, it will be assumed to be a path to a state. The path
544
- will be relative to the statechart's root state; not relative to this state.
837
+ If the value given is a string then it is considered a state path expression. The path is then
838
+ used to find a state relative to this state based on rules of the {@link #getState} method.
545
839
 
546
840
  Method can be called in the following ways:
547
841
 
548
842
  // With one argument
549
- gotoHistoryState(<state>)
843
+ gotoHistoryState(<value>)
550
844
 
551
845
  // With two arguments
552
- gotoHistoryState(<state>, <boolean | hash>)
846
+ gotoHistoryState(<value>, <boolean | hash>)
553
847
 
554
848
  // With three arguments
555
- gotoHistoryState(<state>, <boolean>, <hash>)
849
+ gotoHistoryState(<value>, <boolean>, <hash>)
556
850
 
557
- Where <state> is either a string or a SC.State object and <hash> is a regular JS hash object.
851
+ Where <value> is either a string or a SC.State object and <hash> is a regular JS hash object.
558
852
 
559
- @param state {SC.State|String} the state whose history state to go to
560
- @param recusive {Boolean} Optional. Indicates whether to follow history states recusively starting
853
+ @param value {SC.State|String} the state whose history state to go to
854
+ @param [recusive] {Boolean} indicates whether to follow history states recusively starting
561
855
  from the given state
562
- @param context {Hash} Optional. context object that will be supplied to all states that are exited
563
- entered during the state transition process
856
+ @param [context] {Hash|Object} context object that will be supplied to all states that are exited
857
+ entered during the state transition process. Context can not be an instance of SC.State.
564
858
  */
565
- gotoHistoryState: function(state, recursive, context) {
566
- var fromState = null;
859
+ gotoHistoryState: function(value, recursive, context) {
860
+ var state = this.getState(value);
567
861
 
568
- if (this.get('isCurrentState')) {
569
- fromState = this;
570
- } else if (this.get('hasCurrentSubstates')) {
571
- fromState = this.get('currentSubstates')[0];
862
+ if (!state) {
863
+ var msg = "can not go to history state %@ from state %@. Invalid value.";
864
+ this.stateLogError(msg.fmt(value, this));
865
+ return;
572
866
  }
573
867
 
574
- this.get('statechart').gotoHistoryState(state, fromState, recursive, context);
868
+ var from = this.findFirstRelativeCurrentState(state);
869
+ this.get('statechart').gotoHistoryState(state, from, recursive, context);
575
870
  },
576
-
871
+
577
872
  /**
578
873
  Resumes an active goto state transition process that has been suspended.
579
874
  */
@@ -668,17 +963,57 @@ SC.State = SC.Object.extend(
668
963
  var entered = this.get('enteredSubstates');
669
964
  return !!entered && entered.get('length') > 0;
670
965
  }.property('enteredSubstates').cacheable(),
671
-
966
+
967
+ /**
968
+ Will attempt to find a current state in the statechart that is relative to
969
+ this state.
970
+
971
+ Ordered set of rules to find a relative current state:
972
+
973
+ 1. If this state is a current state then it will be returned
974
+
975
+ 2. If this state has no current states and this state has a parent state then
976
+ return parent state's first relative current state, otherwise return null
977
+
978
+ 3. If this state has more than one current state then use the given anchor state
979
+ to get a corresponding substate that can be used to find a current state relative
980
+ to the substate, if a substate was found.
981
+
982
+ 4. If (3) did not find a relative current state then default to returning
983
+ this state's first current substate.
984
+
985
+ @param anchor {State|String} Optional. a substate of this state used to help direct
986
+ finding a current state
987
+ @return {SC.State} a current state
988
+ */
989
+ findFirstRelativeCurrentState: function(anchor) {
990
+ if (this.get('isCurrentState')) return this;
991
+
992
+ var currentSubstates = this.get('currentSubstates') || [],
993
+ numCurrent = currentSubstates.get('length'),
994
+ parent = this.get('parentState');
995
+
996
+ if (numCurrent === 0) {
997
+ return parent ? parent.findFirstRelativeCurrentState() : null;
998
+ }
999
+
1000
+ if (numCurrent > 1) {
1001
+ anchor = this.getSubstate(anchor);
1002
+ if (anchor) return anchor.findFirstRelativeCurrentState();
1003
+ }
1004
+
1005
+ return currentSubstates[0];
1006
+ },
1007
+
672
1008
  /**
673
1009
  Used to re-enter this state. Call this only when the state a current state of
674
1010
  the statechart.
675
1011
  */
676
1012
  reenter: function() {
677
- var statechart = this.get('statechart');
678
- if (this.get('isCurrentState')) {
679
- statechart.gotoState(this);
1013
+ if (this.get('isEnteredState')) {
1014
+ this.gotoState(this);
680
1015
  } else {
681
- SC.Logger.error('Can not re-enter state %@ since it is not a current state in the statechart'.fmt(this));
1016
+ SC.Logger.error('Can not re-enter state %@ since it is not an entered state in the statechart'.fmt(this));
682
1017
  }
683
1018
  },
684
1019
 
@@ -728,31 +1063,39 @@ SC.State = SC.Object.extend(
728
1063
  */
729
1064
  tryToHandleEvent: function(event, arg1, arg2) {
730
1065
 
731
- var trace = this.get('trace');
1066
+ var trace = this.get('trace'),
1067
+ sc = this.get('statechart'),
1068
+ ret;
732
1069
 
733
1070
  // First check if the name of the event is the same as a registered event handler. If so,
734
1071
  // then do not handle the event.
735
1072
  if (this._registeredEventHandlers[event]) {
736
- this.stateLogWarning("state %@ can not handle event %@ since it is a registered event handler".fmt(this, event));
1073
+ this.stateLogWarning("state %@ can not handle event '%@' since it is a registered event handler".fmt(this, event));
737
1074
  return NO;
738
1075
  }
739
1076
 
740
1077
  if (this._registeredStateObserveHandlers[event]) {
741
- this.stateLogWarning("state %@ can not handle event %@ since it is a registered state observe handler".fmt(this, event));
1078
+ this.stateLogWarning("state %@ can not handle event '%@' since it is a registered state observe handler".fmt(this, event));
742
1079
  return NO;
743
1080
  }
744
1081
 
745
1082
  // Now begin by trying a basic method on the state to respond to the event
746
1083
  if (SC.typeOf(this[event]) === SC.T_FUNCTION) {
747
- if (trace) this.stateLogTrace("will handle event %@".fmt(event));
748
- return (this[event](arg1, arg2) !== NO);
1084
+ if (trace) this.stateLogTrace("will handle event '%@'".fmt(event));
1085
+ sc.stateWillTryToHandleEvent(this, event, event);
1086
+ ret = (this[event](arg1, arg2) !== NO);
1087
+ sc.stateDidTryToHandleEvent(this, event, event, ret);
1088
+ return ret;
749
1089
  }
750
1090
 
751
1091
  // Try an event handler that is associated with an event represented as a string
752
1092
  var handler = this._registeredStringEventHandlers[event];
753
1093
  if (handler) {
754
- if (trace) this.stateLogTrace("%@ will handle event %@".fmt(handler.name, event));
755
- return (handler.handler.call(this, event, arg1, arg2) !== NO);
1094
+ if (trace) this.stateLogTrace("%@ will handle event '%@'".fmt(handler.name, event));
1095
+ sc.stateWillTryToHandleEvent(this, event, handler.name);
1096
+ ret = (handler.handler.call(this, event, arg1, arg2) !== NO);
1097
+ sc.stateDidTryToHandleEvent(this, event, handler.name, ret);
1098
+ return ret;
756
1099
  }
757
1100
 
758
1101
  // Try an event handler that is associated with events matching a regular expression
@@ -763,16 +1106,22 @@ SC.State = SC.Object.extend(
763
1106
  for (; i < len; i += 1) {
764
1107
  handler = this._registeredRegExpEventHandlers[i];
765
1108
  if (event.match(handler.regexp)) {
766
- if (trace) this.stateLogTrace("%@ will handle event %@".fmt(handler.name, event));
767
- return (handler.handler.call(this, event, arg1, arg2) !== NO);
1109
+ if (trace) this.stateLogTrace("%@ will handle event '%@'".fmt(handler.name, event));
1110
+ sc.stateWillTryToHandleEvent(this, event, handler.name);
1111
+ ret = (handler.handler.call(this, event, arg1, arg2) !== NO);
1112
+ sc.stateDidTryToHandleEvent(this, event, handler.name, ret);
1113
+ return ret;
768
1114
  }
769
1115
  }
770
1116
 
771
1117
  // Final attempt. If the state has an unknownEvent function then invoke it to
772
1118
  // handle the event
773
1119
  if (SC.typeOf(this['unknownEvent']) === SC.T_FUNCTION) {
774
- if (trace) this.stateLogTrace("unknownEvent will handle event %@".fmt(event));
775
- return (this.unknownEvent(event, arg1, arg2) !== NO);
1120
+ if (trace) this.stateLogTrace("unknownEvent will handle event '%@'".fmt(event));
1121
+ sc.stateWillTryToHandleEvent(this, event, 'unknownEvent');
1122
+ ret = (this.unknownEvent(event, arg1, arg2) !== NO);
1123
+ sc.stateDidTryToHandleEvent(this, event, 'unknownEvent', ret);
1124
+ return ret;
776
1125
  }
777
1126
 
778
1127
  // Nothing was able to handle the given event for this state
@@ -799,7 +1148,16 @@ SC.State = SC.Object.extend(
799
1148
  When the enterState method is called, an optional context value may be supplied if
800
1149
  one was provided to the gotoState method.
801
1150
 
802
- @param context {Hash} Optional value if one was supplied to gotoState when invoked
1151
+ In the case that the context being supplied is a state context object
1152
+ ({@link SC.StateRouteHandlerContext}), an optional `enterStateByRoute` method can be invoked
1153
+ on this state if the state has implemented the method. If `enterStateByRoute` is
1154
+ not part of this state then the `enterState` method will be invoked by default. The
1155
+ `enterStateByRoute` is simply a convenience method that helps removes checks to
1156
+ determine if the context provide is a state route context object.
1157
+
1158
+ @param {Hash} [context] value if one was supplied to gotoState when invoked
1159
+
1160
+ @see #representRoute
803
1161
  */
804
1162
  enterState: function(context) { },
805
1163
 
@@ -809,9 +1167,12 @@ SC.State = SC.Object.extend(
809
1167
  Note: This is intended to be used by the owning statechart but it can be overridden if
810
1168
  you need to do something special.
811
1169
 
1170
+ @param {Hash} [context] value if one was supplied to gotoState when invoked
812
1171
  @see #enterState
813
1172
  */
814
- stateWillBecomeEntered: function() { },
1173
+ stateWillBecomeEntered: function(context) {
1174
+ this._isEnteringState = YES;
1175
+ },
815
1176
 
816
1177
  /**
817
1178
  Notification called just after enterState is invoked.
@@ -819,10 +1180,12 @@ SC.State = SC.Object.extend(
819
1180
  Note: This is intended to be used by the owning statechart but it can be overridden if
820
1181
  you need to do something special.
821
1182
 
1183
+ @param context {Hash} Optional value if one was supplied to gotoState when invoked
822
1184
  @see #enterState
823
1185
  */
824
- stateDidBecomeEntered: function() {
1186
+ stateDidBecomeEntered: function(context) {
825
1187
  this._setupAllStateObserveHandlers();
1188
+ this._isEnteringState = NO;
826
1189
  },
827
1190
 
828
1191
  /**
@@ -855,9 +1218,11 @@ SC.State = SC.Object.extend(
855
1218
  Note: This is intended to be used by the owning statechart but it can be overridden
856
1219
  if you need to do something special.
857
1220
 
1221
+ @param context {Hash} Optional value if one was supplied to gotoState when invoked
858
1222
  @see #exitState
859
1223
  */
860
- stateWillBecomeExited: function() {
1224
+ stateWillBecomeExited: function(context) {
1225
+ this._isExitingState = YES;
861
1226
  this._teardownAllStateObserveHandlers();
862
1227
  },
863
1228
 
@@ -867,9 +1232,12 @@ SC.State = SC.Object.extend(
867
1232
  Note: This is intended to be used by the owning statechart but it can be overridden
868
1233
  if you need to do something special.
869
1234
 
1235
+ @param context {Hash} Optional value if one was supplied to gotoState when invoked
870
1236
  @see #exitState
871
1237
  */
872
- stateDidBecomeExited: function() { },
1238
+ stateDidBecomeExited: function(context) {
1239
+ this._isExitingState = NO;
1240
+ },
873
1241
 
874
1242
  /** @private
875
1243
 
@@ -992,10 +1360,19 @@ SC.State = SC.Object.extend(
992
1360
  }.property('name', 'parentState').cacheable(),
993
1361
 
994
1362
  toString: function() {
995
- var className = SC._object_className(this.constructor);
996
- return "%@<%@, %@>".fmt(className, this.get('fullPath'), SC.guidFor(this));
1363
+ return this.get('fullPath');
997
1364
  },
998
1365
 
1366
+ /** @private */
1367
+ _enteredSubstatesDidChange: function() {
1368
+ this.notifyPropertyChange('enteredSubstates');
1369
+ }.observes('*enteredSubstates.[]'),
1370
+
1371
+ /** @private */
1372
+ _currentSubstatesDidChange: function() {
1373
+ this.notifyPropertyChange('currentSubstates');
1374
+ }.observes('*currentSubstates.[]'),
1375
+
999
1376
  /** @private */
1000
1377
  _statechartTraceDidChange: function() {
1001
1378
  this.notifyPropertyChange('trace');