sproutcore 1.5.0.rc.1 → 1.5.0.rc.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (193) hide show
  1. data/CHANGELOG +4 -0
  2. data/VERSION.yml +1 -1
  3. data/lib/frameworks/sproutcore/Buildfile +9 -4
  4. data/lib/frameworks/sproutcore/README.md +1 -0
  5. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/QuickLook/Preview.pdf +0 -0
  6. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/QuickLook/Thumbnail.tiff +0 -0
  7. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/data.plist +0 -0
  8. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image10.png +0 -0
  9. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image11.png +0 -0
  10. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image13.png +0 -0
  11. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image15.png +0 -0
  12. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image16.png +0 -0
  13. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image17.png +0 -0
  14. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image18.png +0 -0
  15. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image19.png +0 -0
  16. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image22.tiff +0 -0
  17. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image23.png +0 -0
  18. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image24.png +0 -0
  19. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image25.png +0 -0
  20. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image30.png +0 -0
  21. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image31.png +0 -0
  22. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image8.png +0 -0
  23. data/lib/frameworks/sproutcore/design/{TestRunner_Design.gaffle → TestRunner_Design.graffle}/image9.png +0 -0
  24. data/lib/frameworks/sproutcore/frameworks/animation/core.js +23 -25
  25. data/lib/frameworks/sproutcore/frameworks/bootstrap/system/browser.js +160 -0
  26. data/lib/frameworks/sproutcore/frameworks/core_foundation/controllers/array.js +73 -82
  27. data/lib/frameworks/sproutcore/frameworks/core_foundation/core.js +1 -3
  28. data/lib/frameworks/sproutcore/frameworks/{handlebars/extensions → core_foundation/ext/handlebars}/bind.js +110 -7
  29. data/lib/frameworks/sproutcore/frameworks/{handlebars/extensions → core_foundation/ext/handlebars}/collection.js +10 -7
  30. data/lib/frameworks/sproutcore/frameworks/{handlebars/extensions → core_foundation/ext/handlebars}/localization.js +1 -1
  31. data/lib/frameworks/sproutcore/frameworks/{handlebars/extensions → core_foundation/ext/handlebars}/view.js +4 -2
  32. data/lib/frameworks/sproutcore/frameworks/{handlebars/extensions.js → core_foundation/ext/handlebars.js} +0 -57
  33. data/lib/frameworks/sproutcore/frameworks/core_foundation/ext/object.js +1 -3
  34. data/lib/frameworks/sproutcore/frameworks/core_foundation/mixins/template_helpers/text_field_support.js +11 -0
  35. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/main.js +1 -3
  36. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/pane.js +2 -4
  37. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/application.js +14 -16
  38. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/builder.js +29 -37
  39. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/datetime.js +0 -0
  40. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/event.js +71 -19
  41. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/locale.js +3 -7
  42. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/page.js +5 -7
  43. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/selection_set.js +1 -3
  44. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/sparse_array.js +4 -0
  45. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/timer.js +21 -27
  46. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/utils.js +3 -5
  47. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/controllers/array/array_case.js +3 -3
  48. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/controllers/object/single_enumerable_case.js +1 -1
  49. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/system/sparse_array.js +1 -1
  50. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/template/handlebars.js +93 -1
  51. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/clippingFrame.js +1 -1
  52. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/convertLayouts.js +13 -11
  53. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layer.js +2 -6
  54. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutStyle.js +4 -4
  55. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/theme.js +2 -0
  56. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/view.js +4 -4
  57. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/template.js +6 -2
  58. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/template_collection.js +87 -32
  59. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout.js +21 -25
  60. data/lib/frameworks/sproutcore/frameworks/datastore/data_sources/cascade.js +15 -19
  61. data/lib/frameworks/sproutcore/frameworks/datastore/data_sources/data_source.js +114 -167
  62. data/lib/frameworks/sproutcore/frameworks/datastore/data_sources/fixtures.js +4 -4
  63. data/lib/frameworks/sproutcore/frameworks/datastore/models/child_attribute.js +4 -6
  64. data/lib/frameworks/sproutcore/frameworks/datastore/models/children_attribute.js +2 -4
  65. data/lib/frameworks/sproutcore/frameworks/datastore/models/fetched_attribute.js +7 -7
  66. data/lib/frameworks/sproutcore/frameworks/datastore/models/many_attribute.js +18 -20
  67. data/lib/frameworks/sproutcore/frameworks/datastore/models/record.js +74 -72
  68. data/lib/frameworks/sproutcore/frameworks/datastore/models/record_attribute.js +36 -29
  69. data/lib/frameworks/sproutcore/frameworks/datastore/models/single_attribute.js +2 -2
  70. data/lib/frameworks/sproutcore/frameworks/datastore/system/child_array.js +97 -78
  71. data/lib/frameworks/sproutcore/frameworks/datastore/system/many_array.js +117 -97
  72. data/lib/frameworks/sproutcore/frameworks/datastore/system/nested_store.js +13 -13
  73. data/lib/frameworks/sproutcore/frameworks/datastore/system/query.js +111 -108
  74. data/lib/frameworks/sproutcore/frameworks/datastore/system/record_array.js +231 -198
  75. data/lib/frameworks/sproutcore/frameworks/datastore/system/store.js +146 -145
  76. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/query/builders.js +21 -21
  77. data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/record_array/flush.js +49 -50
  78. data/lib/frameworks/sproutcore/frameworks/datetime/{system → frameworks/core/system}/datetime.js +122 -171
  79. data/lib/frameworks/sproutcore/frameworks/datetime/{tests → frameworks/core/tests}/system/datetime.js +0 -0
  80. data/lib/frameworks/sproutcore/frameworks/datetime/{resources → frameworks/localized/resources}/strings.js +0 -0
  81. data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/localized/system/datetime.js +91 -0
  82. data/lib/frameworks/sproutcore/frameworks/desktop/core.js +18 -2
  83. data/lib/frameworks/sproutcore/frameworks/desktop/mixins/border.js +23 -16
  84. data/lib/frameworks/sproutcore/frameworks/desktop/mixins/collection_fast_path.js +56 -45
  85. data/lib/frameworks/sproutcore/frameworks/desktop/mixins/collection_group.js +5 -2
  86. data/lib/frameworks/sproutcore/frameworks/desktop/mixins/collection_row_delegate.js +21 -19
  87. data/lib/frameworks/sproutcore/frameworks/desktop/mixins/collection_view_delegate.js +82 -77
  88. data/lib/frameworks/sproutcore/frameworks/desktop/mixins/navigation_builder.js +18 -12
  89. data/lib/frameworks/sproutcore/frameworks/desktop/mixins/scrollable.js +29 -17
  90. data/lib/frameworks/sproutcore/frameworks/desktop/panes/alert.js +148 -107
  91. data/lib/frameworks/sproutcore/frameworks/desktop/panes/menu.js +31 -16
  92. data/lib/frameworks/sproutcore/frameworks/desktop/panes/modal.js +16 -13
  93. data/lib/frameworks/sproutcore/frameworks/desktop/panes/palette.js +38 -17
  94. data/lib/frameworks/sproutcore/frameworks/desktop/panes/panel.js +37 -25
  95. data/lib/frameworks/sproutcore/frameworks/desktop/panes/picker.js +247 -144
  96. data/lib/frameworks/sproutcore/frameworks/desktop/panes/select_button.js +155 -100
  97. data/lib/frameworks/sproutcore/frameworks/desktop/panes/sheet.js +39 -17
  98. data/lib/frameworks/sproutcore/frameworks/desktop/protocols/drag_data_source.js +9 -6
  99. data/lib/frameworks/sproutcore/frameworks/desktop/protocols/drag_source.js +18 -22
  100. data/lib/frameworks/sproutcore/frameworks/desktop/protocols/drop_target.js +27 -17
  101. data/lib/frameworks/sproutcore/frameworks/desktop/system/drag.js +77 -44
  102. data/lib/frameworks/sproutcore/frameworks/desktop/system/undo_manager.js +68 -33
  103. data/lib/frameworks/sproutcore/frameworks/desktop/views/button.js +168 -110
  104. data/lib/frameworks/sproutcore/frameworks/desktop/views/checkbox.js +37 -5
  105. data/lib/frameworks/sproutcore/frameworks/desktop/views/collection.js +187 -123
  106. data/lib/frameworks/sproutcore/frameworks/desktop/views/date_field.js +73 -49
  107. data/lib/frameworks/sproutcore/frameworks/desktop/views/disclosure.js +34 -9
  108. data/lib/frameworks/sproutcore/frameworks/desktop/views/file.js +51 -14
  109. data/lib/frameworks/sproutcore/frameworks/desktop/views/grid.js +38 -8
  110. data/lib/frameworks/sproutcore/frameworks/desktop/views/image_button.js +15 -9
  111. data/lib/frameworks/sproutcore/frameworks/desktop/views/list.js +54 -34
  112. data/lib/frameworks/sproutcore/frameworks/desktop/views/list_item.js +113 -42
  113. data/lib/frameworks/sproutcore/frameworks/desktop/views/master_detail.js +84 -28
  114. data/lib/frameworks/sproutcore/frameworks/desktop/views/menu_item.js +67 -51
  115. data/lib/frameworks/sproutcore/frameworks/desktop/views/menu_scroll.js +122 -35
  116. data/lib/frameworks/sproutcore/frameworks/desktop/views/navigation.js +40 -16
  117. data/lib/frameworks/sproutcore/frameworks/desktop/views/navigation_bar.js +28 -18
  118. data/lib/frameworks/sproutcore/frameworks/desktop/views/popup_button.js +27 -31
  119. data/lib/frameworks/sproutcore/frameworks/desktop/views/progress.js +118 -68
  120. data/lib/frameworks/sproutcore/frameworks/desktop/views/radio.js +117 -61
  121. data/lib/frameworks/sproutcore/frameworks/desktop/views/scene.js +23 -16
  122. data/lib/frameworks/sproutcore/frameworks/desktop/views/scroll.js +241 -77
  123. data/lib/frameworks/sproutcore/frameworks/desktop/views/scroller.js +134 -69
  124. data/lib/frameworks/sproutcore/frameworks/desktop/views/segment.js +107 -25
  125. data/lib/frameworks/sproutcore/frameworks/desktop/views/segmented.js +125 -48
  126. data/lib/frameworks/sproutcore/frameworks/desktop/views/select.js +165 -69
  127. data/lib/frameworks/sproutcore/frameworks/desktop/views/select_field.js +73 -24
  128. data/lib/frameworks/sproutcore/frameworks/desktop/views/separator.js +19 -5
  129. data/lib/frameworks/sproutcore/frameworks/desktop/views/source_list.js +16 -4
  130. data/lib/frameworks/sproutcore/frameworks/desktop/views/source_list_group.js +14 -7
  131. data/lib/frameworks/sproutcore/frameworks/desktop/views/split.js +43 -37
  132. data/lib/frameworks/sproutcore/frameworks/desktop/views/split_divider.js +8 -1
  133. data/lib/frameworks/sproutcore/frameworks/desktop/views/stacked.js +14 -3
  134. data/lib/frameworks/sproutcore/frameworks/desktop/views/static_content.js +16 -2
  135. data/lib/frameworks/sproutcore/frameworks/desktop/views/tab.js +99 -0
  136. data/lib/frameworks/sproutcore/frameworks/desktop/views/thumb.js +13 -1
  137. data/lib/frameworks/sproutcore/frameworks/desktop/views/toolbar.js +58 -8
  138. data/lib/frameworks/sproutcore/frameworks/desktop/views/web.js +34 -18
  139. data/lib/frameworks/sproutcore/frameworks/desktop/views/well.js +25 -9
  140. data/lib/frameworks/sproutcore/frameworks/desktop/views/workspace.js +70 -36
  141. data/lib/frameworks/sproutcore/frameworks/foundation/controllers/tree.js +10 -5
  142. data/lib/frameworks/sproutcore/frameworks/foundation/debug/control_test_pane.js +28 -17
  143. data/lib/frameworks/sproutcore/frameworks/foundation/delegates/inline_text_field.js +41 -43
  144. data/lib/frameworks/sproutcore/frameworks/foundation/gestures/pinch.js +42 -4
  145. data/lib/frameworks/sproutcore/frameworks/foundation/gestures/swipe.js +94 -4
  146. data/lib/frameworks/sproutcore/frameworks/foundation/gestures/tap.js +41 -1
  147. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/auto_mixin.js +2 -0
  148. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/auto_resize.js +18 -9
  149. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/collection_content.js +7 -5
  150. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/content_display.js +7 -8
  151. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/content_value_support.js +34 -24
  152. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/control.js +48 -18
  153. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/inline_text_field.js +1 -0
  154. data/lib/frameworks/sproutcore/frameworks/foundation/system/utils/misc.js +1 -2
  155. data/lib/frameworks/sproutcore/frameworks/foundation/tasks/preload_bundle.js +1 -1
  156. data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/inline_text_field/beginEditing.js +0 -11
  157. data/lib/frameworks/sproutcore/frameworks/foundation/validators/date_time.js +1 -1
  158. data/lib/frameworks/sproutcore/frameworks/foundation/views/text_field.js +8 -0
  159. data/lib/frameworks/sproutcore/frameworks/qunit/README.md +24 -0
  160. data/lib/frameworks/sproutcore/frameworks/qunit/package.json +21 -0
  161. data/lib/frameworks/sproutcore/frameworks/qunit/qunit/qunit.css +215 -0
  162. data/lib/frameworks/sproutcore/frameworks/qunit/qunit/qunit.js +1442 -0
  163. data/lib/frameworks/sproutcore/frameworks/qunit/test/headless.html +24 -0
  164. data/lib/frameworks/sproutcore/frameworks/qunit/test/index.html +18 -0
  165. data/lib/frameworks/sproutcore/frameworks/qunit/test/logs.html +17 -0
  166. data/lib/frameworks/sproutcore/frameworks/qunit/test/logs.js +150 -0
  167. data/lib/frameworks/sproutcore/frameworks/qunit/test/same.js +1421 -0
  168. data/lib/frameworks/sproutcore/frameworks/qunit/test/test.js +314 -0
  169. data/lib/frameworks/sproutcore/frameworks/runtime/core.js +1 -1
  170. data/lib/frameworks/sproutcore/frameworks/runtime/mixins/array.js +369 -60
  171. data/lib/frameworks/sproutcore/frameworks/runtime/mixins/enumerable.js +2 -405
  172. data/lib/frameworks/sproutcore/frameworks/runtime/mixins/observable.js +3 -9
  173. data/lib/frameworks/sproutcore/frameworks/runtime/private/property_chain.js +50 -45
  174. data/lib/frameworks/sproutcore/frameworks/runtime/system/binding.js +20 -1
  175. data/lib/frameworks/sproutcore/frameworks/runtime/system/object.js +0 -9
  176. data/lib/frameworks/sproutcore/frameworks/runtime/tests/core/guidFor.js +1 -1
  177. data/lib/frameworks/sproutcore/frameworks/runtime/tests/mixins/array.js +36 -14
  178. data/lib/frameworks/sproutcore/frameworks/runtime/tests/mixins/enumerable/enumerable.js +0 -34
  179. data/lib/frameworks/sproutcore/frameworks/runtime/tests/mixins/enumerable/enumerable_observers.js +50 -61
  180. data/lib/frameworks/sproutcore/frameworks/runtime/tests/mixins/observable/observable.js +2 -2
  181. data/lib/frameworks/sproutcore/frameworks/runtime/tests/mixins/observable/propertyChanges.js +1 -1
  182. data/lib/frameworks/sproutcore/frameworks/runtime/tests/mixins/observable/registerDependentKeys.js +45 -1
  183. data/lib/frameworks/sproutcore/frameworks/runtime/tests/mixins/propertyChanges.js +1 -1
  184. data/lib/frameworks/sproutcore/frameworks/runtime/tests/system/object/bindings.js +5 -0
  185. data/lib/frameworks/sproutcore/frameworks/runtime/tests/system/object/enhance.js +1 -1
  186. data/lib/frameworks/sproutcore/frameworks/testing/core.js +3 -0
  187. data/lib/frameworks/sproutcore/frameworks/testing/system/plan.js +0 -1
  188. data/lib/frameworks/sproutcore/frameworks/testing/system/runner.js +0 -1
  189. data/lib/gen/html_app/templates/apps/@target_name@/@target_name@.js +1 -1
  190. data/vendor/chance/lib/chance/instance.rb +8 -6
  191. metadata +41 -31
  192. data/lib/frameworks/sproutcore/frameworks/testing/jquery.js +0 -3559
  193. data/lib/frameworks/sproutcore/frameworks/testing/qunit.js +0 -827
@@ -32,7 +32,7 @@ sc_require('system/enumerator');
32
32
  with an SC.Object subclass, you should be sure to change the length
33
33
  property using set().
34
34
 
35
- 2. If you must implement nextObject(). See documentation.
35
+ 2. You must implement nextObject(). See documentation.
36
36
 
37
37
  Once you have these two methods implemented, apply the SC.Enumerable mixin
38
38
  to your class and you will be able to enumerate the contents of your object
@@ -805,411 +805,8 @@ SC.Reducers = /** @scope SC.Reducers.prototype */ {
805
805
  @param {Array} removedObjects the objects that were removed
806
806
  @returns {Object} receiver
807
807
  */
808
- enumerableContentDidChange: function(start, length, delta, addedObjects, removedObjects) {
809
- this._setupContentObservers(addedObjects, removedObjects);
808
+ enumerableContentDidChange: function(start, length, deltas) {
810
809
  this.notifyPropertyChange('[]') ;
811
- this._notifyEnumerableObservers(addedObjects, removedObjects, start);
812
- },
813
-
814
- /**
815
- For all registered property chains on this object, removed them from objects
816
- being removed from the enumerable, and clone them onto newly added objects.
817
-
818
- @param {Object[]} addedObjects the objects being added to the enumerable
819
- @param {Object[]} removedObjects the objected being removed from the enumerable
820
- @returns {Object} receiver
821
- */
822
- setupPropertyChainsForEnumerableContent: function(addedObjects, removedObjects) {
823
- var chains = this._kvo_enumerable_property_chains;
824
-
825
- if (chains) {
826
- chains.forEach(function(chain) {
827
- var idx, len = removedObjects.get('length'),
828
- chainGuid = SC.guidFor(chain),
829
- clonedChain, item, kvoChainList = '_kvo_enumerable_property_clones';
830
-
831
- chain.notifyPropertyDidChange();
832
-
833
- for (idx = 0; idx < len; idx++) {
834
- item = removedObjects[idx];
835
- clonedChain = item[kvoChainList][chainGuid];
836
- clonedChain.deactivate();
837
- delete item[kvoChainList][chainGuid];
838
- }
839
-
840
- len = addedObjects.get('length');
841
- for (idx = 0; idx < len; idx++) {
842
- this._clonePropertyChainToItem(chain, addedObjects[idx]);
843
- }
844
- }, this);
845
- }
846
- return this ;
847
- },
848
-
849
- /**
850
- Register a property chain to propagate to enumerable content.
851
-
852
- This will clone the property chain to each item in the enumerable,
853
- then save it so that it is automatically set up and torn down when
854
- the enumerable content changes.
855
-
856
- @param {String} property the property being listened for on this object
857
- @param {SC._PropertyChain} chain the chain to clone to items
858
- */
859
- registerDependentKeyWithChain: function(property, chain) {
860
- // Get the set of all existing property chains that should
861
- // be propagated to enumerable contents. If that set doesn't
862
- // exist yet, _kvo_for() will create it.
863
- var kvoChainList = '_kvo_enumerable_property_chains',
864
- chains, item, clone, cloneList;
865
-
866
- chains = this._kvo_for(kvoChainList, SC.CoreSet);
867
-
868
- // Save a reference to the chain on this object. If new objects
869
- // are added to the enumerable, we will clone this chain and add
870
- // it to the new object.
871
- chains.add(chain);
872
-
873
- this.forEach(function(item) {
874
- this._clonePropertyChainToItem(chain, item);
875
- }, this);
876
- },
877
-
878
- /**
879
- Clones an SC._PropertyChain to a content item.
880
-
881
- @param {SC._PropertyChain} chain
882
- @param {Object} item
883
- */
884
- _clonePropertyChainToItem: function(chain, item) {
885
- var clone = SC.clone(chain),
886
- kvoCloneList = '_kvo_enumerable_property_clones',
887
- cloneList;
888
-
889
- clone.object = item;
890
-
891
- cloneList = item[kvoCloneList] = item[kvoCloneList] || {};
892
- cloneList[SC.guidFor(chain)] = clone;
893
-
894
- clone.activate(item);
895
- },
896
-
897
- /**
898
- Removes a dependent key from the enumerable, and tears it down on
899
- all content objects.
900
-
901
- @param {String} property
902
- @param {SC._PropertyChain} chain
903
- */
904
- removeDependentKeyWithChain: function(property, chain) {
905
- var kvoChainList = '_kvo_enumerable_property_chains',
906
- kvoCloneList = '_kvo_enumerable_property_clones',
907
- chains, item, clone, cloneList;
908
-
909
- this.forEach(function(item) {
910
- item.removeDependentKeyWithChain(property, chain);
911
-
912
- cloneList = item[kvoCloneList];
913
- clone = cloneList[SC.guidFor(chain)];
914
-
915
- clone.deactivate(item);
916
- }, this);
917
- },
918
-
919
- /**
920
- Called when the contents of the enumerable mutates.
921
-
922
- Implementers of classes that mixin SC.Enumerable should ensure that they
923
- call enumerableContentDidChange(), which invokes this method automatically.
924
-
925
- @param {Array} addedObjects the array of objects that were added to the enumerable
926
- @param {Array} removedObjects the array of objects that were removed from the enumerable
927
- @param {Number} index the index at which the mutation occurred
928
- */
929
- _notifyEnumerableObservers: function(addedObjects, removedObjects, index) {
930
- var observers, members, member, memberLoc, membersLength;
931
- var target, method, context;
932
-
933
- observers = this._kvo_enumerable_observers;
934
-
935
- if (observers) {
936
- members = SC.clone(observers.getMembers());
937
- membersLength = members.length;
938
-
939
- for(memberLoc=0; memberLoc < membersLength; memberLoc++) {
940
- member = members[memberLoc];
941
-
942
- target = member[0];
943
- method = member[1];
944
- context = member[2];
945
-
946
- method.call(target, addedObjects, removedObjects, index, this, context);
947
- }
948
- }
949
- },
950
-
951
- /**
952
- Adds an enumerable observer to the enumerable.
953
-
954
- Enumerable observers are called whenever the enumerable's content
955
- mutates. For example, adding an object via pushObject(), or replacing
956
- objects via replace(), will cause all enumerable observers to be fired.
957
-
958
- Observer methods that you register should have the following signature:
959
-
960
- enumerableDidChange: function(addedObjects, removedObjects, index, source)
961
-
962
- addedObjects will contain an array of the objects added and removedObjects
963
- will contain an array of the objects that were removed. The index parameter
964
- contains the index at which the mutation occurred.
965
-
966
- The fourth parameter, source, is the enumerable that mutated. This is useful
967
- if you register the same observer method on multiple enumerables.
968
-
969
- If you pass a context parameter to addEnumerableObserver(), it will be
970
- included when the observer is fired:
971
-
972
- function(addedObjects, removedObjects, sender, context);
973
-
974
- @param {Object} target the target object to invoke
975
- @param {String|Function} method the method to invoke
976
- @param {Object} context optional context
977
-
978
- @returns {SC.Object} self
979
- */
980
- addEnumerableObserver: function(target, method, context) {
981
- var observers;
982
-
983
- // Normalize parameters. If a function is passed as
984
- // target, make it the method.
985
- if (method === undefined) {
986
- method = target;
987
- target = this;
988
- }
989
-
990
- // Call the observer in the context of the enumerable
991
- // if no explicit target is given.
992
- if (!target) { target = this; }
993
-
994
- // If the method is provided as a string, look it up on
995
- // the target.
996
- if (typeof method === "string") {
997
- method = target[method];
998
- }
999
-
1000
- if (!method) {
1001
- throw "You must pass a method to addEnumerableObserver()";
1002
- }
1003
-
1004
- observers = this._kvo_for('_kvo_enumerable_observers', SC.ObserverSet);
1005
- observers.add(target, method, context);
1006
-
1007
- return this;
1008
- },
1009
-
1010
- /**
1011
- Removes an enumerable observer. Expects the same target and method that
1012
- were used to register the observer.
1013
-
1014
- @param {Object} target the target object to invoke
1015
- @param {String|Function} method the method to invoke
1016
-
1017
- @returns {SC.Object} self
1018
- */
1019
- removeEnumerableObserver: function(target, method) {
1020
- var observers;
1021
-
1022
- // Normalize parameters. If a function is passed as
1023
- // target, make it the method.
1024
- if (method === undefined) {
1025
- method = target;
1026
- target = this;
1027
- }
1028
-
1029
- // Call the observer in the context of the enumerable
1030
- // if no explicit target is given.
1031
- if (!target) { target = this; }
1032
-
1033
- // If the method is provided as a string, look it up on
1034
- // the target.
1035
- if (typeof method === "string") {
1036
- method = target[method];
1037
- }
1038
-
1039
- if (!method) {
1040
- throw "You must pass a method to removeEnumerableObserver()";
1041
- }
1042
-
1043
- observers = this._kvo_enumerable_observers;
1044
-
1045
- if (observers) {
1046
- observers.remove(target, method);
1047
- } else {
1048
- throw "%@: Can't remove observers if no observer has been added.";
1049
- }
1050
-
1051
- return this;
1052
- },
1053
-
1054
- /**
1055
- @private
1056
-
1057
- Clones a segment of an observer chain and applies it
1058
- to an element of this Enumerable.
1059
-
1060
- @param {Object} item The element
1061
- @param {SC._ChainObserver} chainObserver the chain segment to begin from
1062
- */
1063
- _resumeChainObservingForItemWithChainObserver: function(item, chainObserver) {
1064
- var observer = SC.clone(chainObserver.next);
1065
- var key = observer.property;
1066
-
1067
- // The chain observer should create new observers on the child object
1068
- observer.object = item;
1069
- item.addObserver(key, observer, observer.propertyDidChange);
1070
-
1071
- // if we're in the initial chained observer setup phase, add the tail
1072
- // of the current observer segment to the list of tracked tails.
1073
- if(chainObserver.root.tails) {
1074
- chainObserver.root.tails.pushObject(observer.tail());
1075
- }
1076
-
1077
- observer.propertyDidChange();
1078
-
1079
- // Maintain a list of observers on the item so we can remove them
1080
- // if it is removed from the enumerable.
1081
- item._kvo_for(SC.keyFor('_kvo_content_observers', key)).push(observer);
1082
- },
1083
-
1084
- /**
1085
- @private
1086
-
1087
- When enumerable content has changed, remove enumerable observers from
1088
- items that are no longer in the enumerable, and add observers to newly
1089
- added items.
1090
-
1091
- @param {Array} addedObjects the array of objects that have been added
1092
- @param {Array} removedObjects the array of objects that have been removed
1093
- */
1094
- _setupContentObservers: function(addedObjects, removedObjects) {
1095
- if (!addedObjects) { addedObjects = this; }
1096
- if (!removedObjects) { removedObjects = []; }
1097
-
1098
- // Check the last values passed and skip this step if they are
1099
- // the same.
1100
- //
1101
- // TODO: This is obviously a suboptimal workaround to the fact that
1102
- // enumerableContentDidChange can get called twice when implementing
1103
- // SC.ArrayController. We should revisit how enumerableContentDidChange
1104
- // works in that context. --TD
1105
- var lastAdded = this._lastAdded;
1106
- var lastRemoved = this._lastRemoved;
1107
-
1108
- if(lastAdded === addedObjects) { addedObjects = []; }
1109
- if(lastRemoved === removedObjects) { removedObjects = []; }
1110
-
1111
- this._lastAdded = addedObjects;
1112
- this._lastRemoved = removedObjects;
1113
-
1114
- var observedKeys = this._kvo_for('_kvo_content_observed_keys', SC.CoreSet);
1115
- var kvoKey;
1116
-
1117
- // Only setup and teardown enumerable observers if we have keys to observe
1118
- if (observedKeys.get('length') > 0) {
1119
-
1120
- // added and resume the chain observer.
1121
- observedKeys.forEach(function(key) {
1122
- kvoKey = SC.keyFor('_kvo_content_observers', key);
1123
-
1124
- // Loop through removed objects and remove any enumerable observers that
1125
- // belong to them.
1126
- removedObjects.forEach(function(item) {
1127
- item._kvo_for(kvoKey).forEach(function(observer) {
1128
- observer.destroyChain();
1129
- }, this);
1130
- }, this);
1131
- var lastObserver;
1132
-
1133
- // Get all original ChainObservers associated with the key
1134
- this._kvo_for(kvoKey).forEach(function(observer) {
1135
- // if there are no added objects or removed objects, this
1136
- // object is a proxy (like ArrayController), which does
1137
- // not currently receive the added or removed objects.
1138
- // As a result, walk down to the last element of the
1139
- // chain and trigger its propertyDidChange, which will
1140
- // invalidate anything listening.
1141
- if(!addedObjects.get('length') && !removedObjects.get('length')) {
1142
- lastObserver = observer;
1143
- while(lastObserver.next) { lastObserver = lastObserver.next; }
1144
- lastObserver.propertyDidChange();
1145
- } else {
1146
- addedObjects.forEach(function(item) {
1147
- this._resumeChainObservingForItemWithChainObserver(item, observer);
1148
- }, this);
1149
- }
1150
- }, this);
1151
- }, this);
1152
- }
1153
- },
1154
-
1155
- /**
1156
- @private
1157
-
1158
- Adds a content observer. Content observers are able to
1159
- propagate chain observers to each member item in the enumerable,
1160
- so that the observer is fired whenever a single item changes.
1161
-
1162
- You should never call this method directly. Instead, you should
1163
- call addObserver() with the special '@each' property in the path.
1164
-
1165
- For example, if you wanted to observe changes to each item's isDone
1166
- property, you could call:
1167
-
1168
- arrayController.addObserver('@each.isDone');
1169
-
1170
- @param {SC._ChainObserver} chainObserver the chain observer to propagate
1171
- */
1172
- _addContentObserver: function(chainObserver) {
1173
- var key = chainObserver.next.property;
1174
-
1175
- // Add the key to a set so we know what we are observing
1176
- this._kvo_for('_kvo_content_observed_keys', SC.CoreSet).push(key);
1177
-
1178
- // Add the passed ChainObserver to an ObserverSet for that key
1179
- var kvoKey = SC.keyFor('_kvo_content_observers', key);
1180
- this._kvo_for(kvoKey).push(chainObserver);
1181
-
1182
- // set up chained observers on the initial content
1183
- this._setupContentObservers(this);
1184
- },
1185
-
1186
- /**
1187
- @private
1188
-
1189
- Removes a content observer. Pass the same chain observer
1190
- that was used to add the content observer.
1191
-
1192
- @param {SC._ChainObserver} chainObserver the chain observer to propagate
1193
- */
1194
-
1195
- _removeContentObserver: function(chainObserver) {
1196
- var observers, kvoKey;
1197
- var observedKeys = this._kvo_content_observed_keys;
1198
- var key = chainObserver.next.property;
1199
-
1200
- if (observedKeys.contains(key)) {
1201
-
1202
- kvoKey = SC.keyFor('_kvo_content_observers', key);
1203
- observers = this._kvo_for(kvoKey);
1204
-
1205
- observers.removeObject(chainObserver);
1206
-
1207
- this._setupContentObservers([], this);
1208
-
1209
- if (observers.length === 0) {
1210
- this._kvo_for('_kvo_content_observed_keys').remove(key);
1211
- }
1212
- }
1213
810
  },
1214
811
 
1215
812
  /**
@@ -438,13 +438,13 @@ SC.Observable = /** @scope SC.Observable.prototype */{
438
438
  var keyChains = chains[key];
439
439
 
440
440
  if (keyChains) {
441
+ this.beginPropertyChanges();
441
442
  keyChains = SC.clone(keyChains);
442
443
  keyChains.forEach(function(chain) {
443
444
  // Invalidate the property that depends on the changed key.
444
445
  chain.notifyPropertyDidChange();
445
- // Now that the chain is potentially invalid, rebuild it.
446
- chain.rebuildChain();
447
446
  });
447
+ this.endPropertyChanges();
448
448
  }
449
449
  }
450
450
 
@@ -560,9 +560,6 @@ SC.Observable = /** @scope SC.Observable.prototype */{
560
560
  registerDependentKeyWithChain: function(property, chain) {
561
561
  var chains = this._chainsFor(property), next;
562
562
  chains.add(chain);
563
-
564
- next = chain.next;
565
- if (next) { next.activate(this); }
566
563
  },
567
564
 
568
565
  /** @private
@@ -578,9 +575,6 @@ SC.Observable = /** @scope SC.Observable.prototype */{
578
575
  if (chains.get('length') === 0) {
579
576
  delete this._kvo_property_chains[property];
580
577
  }
581
-
582
- next = chain.next;
583
- if (next) { next.deactivate(); }
584
578
  },
585
579
 
586
580
  /** @private
@@ -1408,7 +1402,7 @@ SC.Observable = /** @scope SC.Observable.prototype */{
1408
1402
  },
1409
1403
 
1410
1404
  /**
1411
- Notifies all of observers of a property changes.
1405
+ Notifies observers of all possible property changes.
1412
1406
 
1413
1407
  Sometimes when you make a major update to your object, it is cheaper to
1414
1408
  simply notify all observers that their property might have changed than
@@ -31,8 +31,7 @@ sc_require('system/object');
31
31
  */
32
32
 
33
33
  SC._PropertyChain = SC.Object.extend(
34
- /** @scope SC.ObjectController.prototype */ {
35
-
34
+ /** @scope SC.Object.prototype */ {
36
35
  /**
37
36
  The object represented by this node in the chain.
38
37
 
@@ -80,52 +79,52 @@ SC._PropertyChain = SC.Object.extend(
80
79
  assume it is the root node in the chain and treat the target as the previous
81
80
  object.
82
81
 
83
- @param {Object} [prev] The previous object in the chain.
82
+ @param {Object} [newObject] The object in the chain to hook to.
84
83
  */
85
- activate: function(prev) {
86
- var object = this.get('object'),
87
- property = this.get('property');
84
+ activate: function(newObject) {
85
+ var curObject = this.get('object'),
86
+ property = this.get('property'),
87
+ nextObject;
88
88
 
89
89
  // If no parameter is passed, assume we are the root in the chain
90
90
  // and look up property relative to the target, since dependent key
91
91
  // paths are always relative.
92
- if (!prev) { prev = this.get('target'); }
93
-
94
- // If this node has not yet been associated with an object,
95
- // look up the object and associate it.
96
- if (!object) {
97
- // In the special case of @each, we treat the enumerable as the next
98
- // property.
99
- if (property === '@each') {
100
- object = prev;
101
- } else {
102
- object = prev.get(property);
103
- }
104
- this.set('object', object);
92
+ if (!newObject) { newObject = this.get('target'); }
93
+
94
+ if (curObject && curObject!==newObject) {
95
+ this.deactivate();
105
96
  }
97
+ this.set('object', newObject);
106
98
 
107
- // If there is still no object, don't associate any KVO
108
- // property chains.
109
- if (!object) { return; }
99
+ // In the special case of @each, we treat the enumerable as the next
100
+ // property so just skip registering it
101
+ if (newObject && property!=='@each') {
102
+ newObject.registerDependentKeyWithChain(property, this);
103
+ }
104
+
105
+ // now - lookup the object for the next one...
106
+ if (this.next) {
107
+ nextObject = newObject ? newObject.get(property) : undefined;
108
+ this.next.activate(nextObject);
109
+ }
110
110
 
111
- // Register this node with the object, and tell it which key changing should
112
- // cause the node to be notified.
113
- object.registerDependentKeyWithChain(this.get('nextProperty'), this);
111
+ return this;
114
112
  },
115
113
 
116
114
  /**
117
- Removes this segment of the chain from the object it represents. This is usually
118
- called when the object represented by the previous segment in the chain changes.
115
+ Removes this segment of the chain from the object it represents. This is
116
+ usually called when the object represented by the previous segment in the
117
+ chain changes.
119
118
  */
120
119
  deactivate: function() {
121
- var object = this.get('object'),
122
- nextProperty = this.get('nextProperty');
120
+ var object = this.get('object'),
121
+ property = this.get('property');
123
122
 
124
123
  // If the chain element is not associated with an object,
125
124
  // we don't need to deactivate anything.
126
- if (!object) { return; }
127
-
128
- object.removeDependentKeyWithChain(nextProperty, this);
125
+ if (object) object.removeDependentKeyWithChain(property, this);
126
+ if (this.next) this.next.deactivate();
127
+ return this;
129
128
  },
130
129
 
131
130
  /**
@@ -133,36 +132,41 @@ SC._PropertyChain = SC.Object.extend(
133
132
  */
134
133
  notifyPropertyDidChange: function() {
135
134
  var target = this.get('target'),
136
- toInvalidate = this.get('toInvalidate');
135
+ toInvalidate = this.get('toInvalidate'),
136
+ curObj, newObj;
137
137
 
138
138
  // Tell the target of the chain to invalidate the property
139
139
  // that depends on this element of the chain
140
140
  target.propertyDidChange(toInvalidate);
141
- },
142
141
 
143
- /**
144
- Deactivates the current chain, then recreates it with the new
145
- values.
146
- */
147
- rebuildChain: function() {
148
- this.deactivate();
149
- this.activate();
142
+ // If there are more dependent keys in the chain, we need
143
+ // to invalidate them and set them up again.
144
+ if (this.next) {
145
+ // Get the new value of the object associated with this node to pass to
146
+ // activate().
147
+ curObj = this.get('object');
148
+ newObj = curObj.get(this.get('property'));
149
+
150
+ this.next.activate(newObj); // reactivate down the line
151
+ }
150
152
  },
151
153
 
154
+ //@ if (debug)
152
155
  /**
153
156
  Returns a string representation of the chain segment.
154
157
 
155
158
  @returns {String}
156
159
  */
157
160
  toString: function() {
158
- return "SC._ChainProperty(target: %@, property: %@)".fmt(
161
+ return "SC._PropertyChain(target: %@, property: %@)".fmt(
159
162
  this.get('target'), this.get('property'));
160
163
  }
164
+ //@ endif
161
165
  });
162
166
 
163
167
  SC._PropertyChain.createChain = function(path, target, toInvalidate) {
164
168
  var parts = path.split('.');
165
- var len = parts.length - 1,
169
+ var len = parts.length,
166
170
  i = 1;
167
171
 
168
172
  var root = SC._PropertyChain.create({
@@ -172,10 +176,11 @@ SC._PropertyChain.createChain = function(path, target, toInvalidate) {
172
176
  nextProperty: parts[1]
173
177
  });
174
178
 
175
- root.set('length', len--);
179
+
180
+ root.set('length', len);
176
181
  var tail = root;
177
182
 
178
- while(len--) {
183
+ while(--len >= 1) {
179
184
  tail = tail.next = SC._PropertyChain.create({
180
185
  property: parts[i],
181
186
  target: target,
@@ -339,7 +339,13 @@ SC.Binding = /** @scope SC.Binding.prototype */{
339
339
  this.isConnected = YES ;
340
340
  this._connectionPending = YES ; // its connected but not really...
341
341
  this._syncOnConnect = YES ;
342
+
342
343
  SC.Binding._connectQueue.add(this) ;
344
+
345
+ if (!SC.RunLoop.isRunLoopInProgress()) {
346
+ this._scheduleSync();
347
+ }
348
+
343
349
  return this;
344
350
  },
345
351
 
@@ -446,6 +452,8 @@ SC.Binding = /** @scope SC.Binding.prototype */{
446
452
  this._setBindingValue(target, key) ;
447
453
  this._changePending = YES ;
448
454
  SC.Binding._changeQueue.add(this) ; // save for later.
455
+
456
+ this._scheduleSync();
449
457
  }
450
458
  },
451
459
 
@@ -473,9 +481,20 @@ SC.Binding = /** @scope SC.Binding.prototype */{
473
481
  this._setBindingValue(target, key) ;
474
482
  this._changePending = YES ;
475
483
  SC.Binding._changeQueue.add(this) ; // save for later.
484
+
485
+ this._scheduleSync();
476
486
  }
477
487
  },
478
488
 
489
+ _scheduleSync: function() {
490
+ if (SC.RunLoop.isRunLoopInProgress() || this._syncScheduled) { return; }
491
+
492
+ this._syncScheduled = YES;
493
+ var self = this;
494
+
495
+ setTimeout(function() { SC.run(); self._syncScheduled = NO; }, 1);
496
+ },
497
+
479
498
  /** @private
480
499
  Saves the source location for the binding value. This will be used later
481
500
  to actually update the binding value.
@@ -844,7 +863,7 @@ SC.Binding = /** @scope SC.Binding.prototype */{
844
863
 
845
864
  /**
846
865
  Adds a transform that will return the placeholder value if the value is
847
- null. Otherwise it will passthrough untouched. See also notEmpty().
866
+ null or undefined. Otherwise it will passthrough untouched. See also notEmpty().
848
867
 
849
868
  @param {String} fromPath from path or null
850
869
  @param {Object} placeholder optional placeholder;
@@ -118,15 +118,6 @@ SC._object_extend = function _object_extend(base, ext, proto) {
118
118
 
119
119
  // Possibly add to a bindings.
120
120
  if (key.length > 7 && key.slice(-7) === "Binding") {
121
- // Properties MUST be established before a binding can be made from them.
122
- // We won't slow things down by checking in production, but in dev, give a warning.
123
- // @if (debug)
124
- var bindPropertyKey = key.substr(0, key.length - 7);
125
- if (ext[bindPropertyKey] === undefined && base[bindPropertyKey] === undefined) {
126
- SC.Logger.warn("Uninitialized property '%@'. '%@' will not work as expected.".fmt(bindPropertyKey, key));
127
- }
128
- // @endif
129
-
130
121
  if (!clonedBindings) {
131
122
  bindings = (bindings || SC.EMPTY_ARRAY).slice() ;
132
123
  clonedBindings = YES ;