sproutcore 1.10.0.rc.3 → 1.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (161) hide show
  1. checksums.yaml +8 -8
  2. data/VERSION.yml +1 -1
  3. data/lib/buildtasks/manifest.rake +3 -2
  4. data/lib/frameworks/sproutcore/Buildfile +3 -1
  5. data/lib/frameworks/sproutcore/CHANGELOG.md +26 -2
  6. data/lib/frameworks/sproutcore/apps/showcase/resources/main_page.js +3 -0
  7. data/lib/frameworks/sproutcore/apps/showcase/views/views_item_view.js +1 -1
  8. data/lib/frameworks/sproutcore/apps/welcome/english.lproj/main_page.js +3 -0
  9. data/lib/frameworks/sproutcore/frameworks/bootstrap/system/browser.js +5 -5
  10. data/lib/frameworks/sproutcore/frameworks/bootstrap/tests/system/browser.js +9 -0
  11. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/pane_statechart.js +2 -2
  12. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/browser.js +6 -0
  13. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/root_responder.js +17 -55
  14. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/animation.js +57 -0
  15. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/isVisible.js +24 -0
  16. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/view_states_test.js +31 -13
  17. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view.js +8 -5
  18. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/animation.js +24 -20
  19. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout.js +39 -29
  20. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/statechart.js +400 -242
  21. data/lib/frameworks/sproutcore/frameworks/datastore/models/record.js +37 -32
  22. data/lib/frameworks/sproutcore/frameworks/datastore/models/record_attribute.js +1 -8
  23. data/lib/frameworks/sproutcore/frameworks/desktop/panes/modal.js +3 -2
  24. data/lib/frameworks/sproutcore/frameworks/desktop/panes/panel.js +4 -5
  25. data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/panel/ui.js +53 -6
  26. data/lib/frameworks/sproutcore/frameworks/desktop/views/collection.js +9 -3
  27. data/lib/frameworks/sproutcore/frameworks/desktop/views/grid.js +1 -1
  28. data/lib/frameworks/sproutcore/frameworks/desktop/views/scroll.js +16 -12
  29. data/lib/frameworks/sproutcore/frameworks/desktop/views/scroller.js +16 -2
  30. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/auto_resize.js +10 -8
  31. data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/auto_resize_test.js +102 -0
  32. data/lib/frameworks/sproutcore/frameworks/foundation/tests/validators/password.js +15 -7
  33. data/lib/frameworks/sproutcore/frameworks/runtime/system/run_loop.js +2 -2
  34. data/lib/frameworks/sproutcore/frameworks/testing/system/runner.js +4 -0
  35. data/lib/frameworks/sproutcore/phantomjs/minimist.js +181 -0
  36. data/lib/frameworks/sproutcore/phantomjs/q.js +1937 -0
  37. data/lib/frameworks/sproutcore/phantomjs/test_runner.js +733 -0
  38. data/lib/frameworks/sproutcore/themes/ace/resources/button/ace/44px/button.css +2 -2
  39. data/lib/frameworks/sproutcore/themes/ace/resources/button/ace/button.css +11 -11
  40. data/lib/frameworks/sproutcore/themes/ace/resources/button/dark/button.css +5 -5
  41. data/lib/frameworks/sproutcore/themes/ace/resources/button/dark/jumbo/button.css +3 -3
  42. data/lib/frameworks/sproutcore/themes/ace/resources/button/dark/small/button.css +3 -3
  43. data/lib/frameworks/sproutcore/themes/ace/resources/button/popup/select.css +1 -1
  44. data/lib/frameworks/sproutcore/themes/ace/resources/checkbox/ace/checkbox.css +3 -3
  45. data/lib/frameworks/sproutcore/themes/ace/resources/collection/source-list/source_list_view.css +4 -4
  46. data/lib/frameworks/sproutcore/themes/ace/resources/disclosure/ace/disclosure.css +6 -6
  47. data/lib/frameworks/sproutcore/themes/ace/resources/imagebutton/ace/imagebutton.css +5 -5
  48. data/lib/frameworks/sproutcore/themes/ace/resources/menu/menu.css +16 -16
  49. data/lib/frameworks/sproutcore/themes/ace/resources/picker/popover/popover.css +42 -42
  50. data/lib/frameworks/sproutcore/themes/ace/resources/progress/ace/progress.css +19 -19
  51. data/lib/frameworks/sproutcore/themes/ace/resources/radio/radio.css +12 -12
  52. data/lib/frameworks/sproutcore/themes/ace/resources/scroller/horizontal/horizontal.css +7 -7
  53. data/lib/frameworks/sproutcore/themes/ace/resources/scroller/horizontal/horizontal_touch.css +18 -18
  54. data/lib/frameworks/sproutcore/themes/ace/resources/scroller/vertical/vertical.css +8 -8
  55. data/lib/frameworks/sproutcore/themes/ace/resources/scroller/vertical/vertical_touch.css +16 -16
  56. data/lib/frameworks/sproutcore/themes/ace/resources/segmented/44px/segmented.css +2 -2
  57. data/lib/frameworks/sproutcore/themes/ace/resources/segmented/segmented.css +13 -13
  58. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/14px/slider.css +11 -11
  59. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/16px/slider.css +11 -11
  60. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/22px/slider.css +11 -11
  61. data/lib/frameworks/sproutcore/themes/ace/resources/split/split.css +6 -6
  62. data/lib/frameworks/sproutcore/themes/ace/resources/toolbar/toolbar.css +2 -2
  63. data/lib/frameworks/sproutcore/themes/iphone_theme/english.lproj/button.css +3 -3
  64. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/button.css +18 -18
  65. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/checkbox.css +7 -7
  66. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/collection.css +2 -2
  67. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/core.css +7 -7
  68. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/disclosure.css +3 -3
  69. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/list_item.css +4 -4
  70. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/menu.css +3 -3
  71. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/menu_item_view.css +5 -5
  72. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/panel.css +7 -7
  73. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/picker.css +3 -3
  74. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/progress.css +5 -5
  75. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/radio.css +4 -4
  76. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/scroller.css +3 -3
  77. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/segmented.css +7 -7
  78. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/slider.css +2 -2
  79. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/split_view.css +2 -2
  80. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/toolbar.css +3 -3
  81. data/lib/sproutcore/tools/server.rb +9 -3
  82. metadata +8 -83
  83. data/lib/frameworks/sproutcore/design/Assorted Images/sproutcore-startup-landscape.jpg +0 -0
  84. data/lib/frameworks/sproutcore/design/Assorted Images/sproutcore-startup-landscape.png +0 -0
  85. data/lib/frameworks/sproutcore/design/Assorted Images/sproutcore-startup-portrait.jpg +0 -0
  86. data/lib/frameworks/sproutcore/design/Assorted Images/sproutcore-startup-portrait.png +0 -0
  87. data/lib/frameworks/sproutcore/design/Assorted Images/sproutcore-startup.png +0 -0
  88. data/lib/frameworks/sproutcore/design/Record State Table.numbers +0 -0
  89. data/lib/frameworks/sproutcore/design/greenhouse-statechart.pdf +0 -0
  90. data/lib/frameworks/sproutcore/tests/phantomjs_runner.phantomjs +0 -611
  91. data/lib/frameworks/sproutcore/themes/ace/designs/dark.png +0 -0
  92. data/lib/frameworks/sproutcore/themes/ace/designs/light.png +0 -0
  93. data/lib/frameworks/sproutcore/themes/ace/designs/psds/panel/PanelPane.opacity +0 -0
  94. data/lib/frameworks/sproutcore/themes/ace/designs/psds/panel/Pointers.opacity +0 -0
  95. data/lib/frameworks/sproutcore/themes/ace/designs/switch/switch_handle.png +0 -0
  96. data/lib/frameworks/sproutcore/themes/ace/designs/switch/switch_off.png +0 -0
  97. data/lib/frameworks/sproutcore/themes/ace/designs/switch/switch_on.png +0 -0
  98. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/10.png +0 -0
  99. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/100.png +0 -0
  100. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/102.png +0 -0
  101. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/110.png +0 -0
  102. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/120.png +0 -0
  103. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/127.png +0 -0
  104. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/18.png +0 -0
  105. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/19.png +0 -0
  106. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/2.png +0 -0
  107. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/24.png +0 -0
  108. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/26.png +0 -0
  109. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/27.png +0 -0
  110. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/28.png +0 -0
  111. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/29.png +0 -0
  112. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/30.png +0 -0
  113. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/31.png +0 -0
  114. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/33.png +0 -0
  115. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/37.png +0 -0
  116. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/41.png +0 -0
  117. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/99.png +0 -0
  118. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/10.png +0 -0
  119. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/100.png +0 -0
  120. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/102.png +0 -0
  121. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/110.png +0 -0
  122. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/120.png +0 -0
  123. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/127.png +0 -0
  124. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/18.png +0 -0
  125. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/19.png +0 -0
  126. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/2.png +0 -0
  127. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/24.png +0 -0
  128. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/26.png +0 -0
  129. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/27.png +0 -0
  130. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/28.png +0 -0
  131. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/29.png +0 -0
  132. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/30.png +0 -0
  133. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/31.png +0 -0
  134. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/33.png +0 -0
  135. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/37.png +0 -0
  136. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/41.png +0 -0
  137. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/99.png +0 -0
  138. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/10.png +0 -0
  139. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/100.png +0 -0
  140. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/102.png +0 -0
  141. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/110.png +0 -0
  142. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/120.png +0 -0
  143. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/127.png +0 -0
  144. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/18.png +0 -0
  145. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/19.png +0 -0
  146. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/2.png +0 -0
  147. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/24.png +0 -0
  148. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/26.png +0 -0
  149. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/27.png +0 -0
  150. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/28.png +0 -0
  151. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/29.png +0 -0
  152. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/30.png +0 -0
  153. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/31.png +0 -0
  154. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/33.png +0 -0
  155. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/37.png +0 -0
  156. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/41.png +0 -0
  157. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/99.png +0 -0
  158. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/48/10.png +0 -0
  159. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/48/18.png +0 -0
  160. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/48/19.png +0 -0
  161. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/48/2.png +0 -0
@@ -283,7 +283,7 @@ SC.CoreView.reopen(
283
283
  displayDidChange: function () {
284
284
  //@if (debug)
285
285
  if (SC.LOG_VIEW_STATES) {
286
- SC.Logger.log('%@:%@ — displayDidChange()'.fmt(this, this.get('viewState')));
286
+ SC.Logger.log('%c%@:%@ — displayDidChange()'.fmt(this, this.get('viewState')), SC.LOG_VIEW_STATES_STYLE[this.get('viewState')]);
287
287
  }
288
288
  //@endif
289
289
 
@@ -1881,6 +1881,10 @@ SC.CoreView.unload = function () {
1881
1881
  - `render` -- override this method to generate or update your HTML to reflect
1882
1882
  the current state of your view. This method is called both when your view
1883
1883
  is first created and later anytime it needs to be updated.
1884
+ - `update` -- Normally, when a view needs to update its content, it will
1885
+ re-render the view using the render() method. If you would like to
1886
+ override this behavior with your own custom updating code, you can
1887
+ replace update() with your own implementation instead.
1884
1888
  - `didCreateLayer` -- the render() method is used to generate new HTML.
1885
1889
  Override this method to perform any additional setup on the DOM you might
1886
1890
  need to do after creating the view. For example, if you need to listen
@@ -1888,10 +1892,6 @@ SC.CoreView.unload = function () {
1888
1892
  - `willDestroyLayer` -- if you implement didCreateLayer() to setup event
1889
1893
  listeners, you should implement this method as well to remove the same
1890
1894
  just before the DOM for your view is destroyed.
1891
- - `updateLayer` -- Normally, when a view needs to update its content, it will
1892
- re-render the view using the render() method. If you would like to
1893
- override this behavior with your own custom updating code, you can
1894
- replace updateLayer() with your own implementation instead.
1895
1895
  - `didAppendToDocument` -- in theory all DOM setup could be done
1896
1896
  in didCreateLayer() as you already have a DOM element instantiated.
1897
1897
  However there is cases where the element has to be first appended to the
@@ -1899,6 +1899,9 @@ SC.CoreView.unload = function () {
1899
1899
  plugins which objects are not instantiated until you actually append the
1900
1900
  element to the DOM. This will allow you to do things like registering
1901
1901
  DOM events on flash or quicktime objects.
1902
+ - `willRemoveFromDocument` -- This method is called on the view immediately
1903
+ before its layer is removed from the DOM. You can use this to reverse any
1904
+ setup that is performed in `didAppendToDocument`.
1902
1905
 
1903
1906
  @extends SC.Responder
1904
1907
  @extends SC.DelegateSupport
@@ -83,6 +83,21 @@ SC.LayoutState = {
83
83
  SC.View.reopen(
84
84
  /** @scope SC.View.prototype */ {
85
85
 
86
+ /* @private Internal variable to store the active (i.e. applied) animations. */
87
+ _activeAnimations: null,
88
+
89
+ /* @private Internal variable to store the count of active animations. */
90
+ _activeAnimationsLength: null,
91
+
92
+ /* @private Internal variable to store the animation layout until the next run loop when it can be safely applied. */
93
+ _animateLayout: null,
94
+
95
+ /* @private Internal variable to store the pending (i.e. not yet applied) animations. */
96
+ _pendingAnimations: null,
97
+
98
+ /* @private Internal variable to store the previous layout for in case the animation is cancelled and meant to return to original point. */
99
+ _prevLayout: null,
100
+
86
101
  /**
87
102
  Method protocol.
88
103
 
@@ -214,7 +229,7 @@ SC.View.reopen(
214
229
 
215
230
  @param {Object|String} properties Hash of property names with new layout values or a single property name.
216
231
  @param {Number} [value] The new layout value for a single property (only provide if the first parameter is a String).
217
- @param {Object} options Hash of transition options.
232
+ @param {Number|Object} Duration or hash of transition options.
218
233
  @param {Object} [target=this] The target for the method.
219
234
  @param {AnimateCallback|String} [method] The method to run when the transition completes. May be a function or a property path.
220
235
  @returns {SC.View} receiver
@@ -229,13 +244,14 @@ SC.View.reopen(
229
244
  timing;
230
245
 
231
246
  //@if(debug)
232
- // Provide a little developer support if they are doing something that should be considered wrong.
247
+ // Provide a little developer support if they are doing something that may not work.
233
248
  if (this.get('useStaticLayout')) {
234
249
  SC.warn("Developer Warning: SC.View:animate() was called on a view with useStaticLayout and may not work. If you are using CSS to layout the view (i.e. useStaticLayout: YES), then you should manage the animation manually.");
235
250
  }
236
251
  //@endif
237
252
 
238
253
  // Normalize arguments
254
+ // TODO: Revisit .animate() arguments re: overloading.
239
255
  if (typeof key === SC.T_STRING) {
240
256
  hash = {};
241
257
  hash[key] = value;
@@ -247,23 +263,13 @@ SC.View.reopen(
247
263
  }
248
264
 
249
265
  optionsType = SC.typeOf(options);
250
- // This support should be deprecated. Too much argument overloading.
251
266
  if (optionsType === SC.T_NUMBER) {
252
- //@if(debug)
253
- // Provide a little developer support if they are doing something that should be considered wrong.
254
- SC.warn("Developer Warning: The duration should be given as a property of the options object.");
255
- //@endif
256
267
  options = { duration: options };
257
268
  } else if (optionsType !== SC.T_HASH) {
258
269
  throw new Error("Must provide options hash!");
259
270
  }
260
271
 
261
- // This support should be deprecated. Too much argument overloading.
262
272
  if (options.callback) {
263
- //@if(debug)
264
- // Provide a little developer support if they are doing something that should be considered wrong.
265
- SC.warn("Developer Warning: The callback method should be given as an argument not as part of the options object.");
266
- //@endif
267
273
  method = options.callback;
268
274
  delete options.callback;
269
275
  }
@@ -402,7 +408,7 @@ SC.View.reopen(
402
408
  this.set('layout', this._animateLayout);
403
409
 
404
410
  // Clear the layout cache value.
405
- delete this._animateLayout;
411
+ this._animateLayout = null;
406
412
  }
407
413
  },
408
414
 
@@ -475,6 +481,7 @@ SC.View.reopen(
475
481
  layout = this.get('liveAdjustments');
476
482
  break;
477
483
  default:
484
+ layout = this._animateLayout;
478
485
  }
479
486
 
480
487
  // Immediately remove the pending animations while calling the callbacks.
@@ -510,9 +517,7 @@ SC.View.reopen(
510
517
  }
511
518
 
512
519
  // Clean up.
513
- delete this._prevLayout;
514
- delete this._activeAnimations;
515
- delete this._pendingAnimations;
520
+ this._prevLayout = this._activeAnimations = this._pendingAnimations = this._animateLayout = null;
516
521
 
517
522
  return this;
518
523
  },
@@ -605,11 +610,11 @@ SC.View.reopen(
605
610
  }.property(),
606
611
 
607
612
  /** @private Removes the animation CSS from the layer style. */
608
- removeAnimationFromLayout: function (propertyName, updateStyle) {
613
+ removeAnimationFromLayout: function (propertyName, shouldUpdateStyle) {
609
614
  var activeAnimations = this._activeAnimations,
610
615
  layer = this.get('layer');
611
616
 
612
- if (!!layer && updateStyle) {
617
+ if (!!layer && shouldUpdateStyle) {
613
618
  var updatedCSS = [];
614
619
 
615
620
  // Calculate the transition CSS that should remain.
@@ -680,8 +685,7 @@ SC.View.reopen(
680
685
  // Clean up the internal hash.
681
686
  this._activeAnimationsLength -= 1;
682
687
  if (this._activeAnimationsLength === 0) {
683
- delete this._activeAnimations;
684
- delete this._prevLayout;
688
+ this._activeAnimations = this._prevLayout = null;
685
689
  }
686
690
  }
687
691
  },
@@ -51,6 +51,9 @@ SC.View.reopen(
51
51
  */
52
52
  backgroundColor: null,
53
53
 
54
+ /* @private Internal variable used to check for layout changes that resize. */
55
+ _previousLayout: null,
56
+
54
57
  /**
55
58
  Activates use of brower's static layout. To activate, set this
56
59
  property to YES.
@@ -143,18 +146,47 @@ SC.View.reopen(
143
146
  @returns {SC.View} receiver
144
147
  */
145
148
  adjust: function (key, value) {
146
- var layout = this.get('layout'), didChange = NO, cur, hash;
147
-
148
149
  if (key === undefined) { return this; } // nothing to do.
149
150
 
150
- // handle string case
151
+ var layout = this.get('layout'),
152
+ didChange = NO,
153
+ animateLayout = this._animateLayout,
154
+ cur, hash;
155
+
156
+ // Normalize arguments.
151
157
  if (SC.typeOf(key) === SC.T_STRING) {
152
- // this is copied from below
158
+ hash = {};
159
+ hash[key] = value;
160
+ } else {
161
+ hash = key;
162
+ }
163
+
164
+ for (key in hash) {
165
+ if (!hash.hasOwnProperty(key)) { continue; }
166
+
167
+ value = hash[key];
153
168
  cur = layout[key];
154
169
 
155
- if (value === undefined || cur == value) return this;
170
+ // If a call to animate occurs in the same run loop, the animation layout
171
+ // would still be applied in the next run loop, potentially overriding this
172
+ // adjustment. So we need to fix up the animation layout.
173
+ if (animateLayout) {
174
+ if (value === null) {
175
+ delete animateLayout[key];
176
+ } else {
177
+ animateLayout[key] = value;
178
+ }
179
+
180
+ if (this._pendingAnimations[key]) {
181
+ // Adjusting a value that was previously about to be animated cancels the animation.
182
+ delete this._pendingAnimations[key];
183
+ }
184
+ }
185
+
186
+ if (value === undefined || cur == value) { continue; }
156
187
 
157
- layout = SC.clone(layout);
188
+ // only clone the layout the first time we see a change
189
+ if (!didChange) layout = SC.clone(layout);
158
190
 
159
191
  if (value === null) {
160
192
  delete layout[key];
@@ -163,28 +195,6 @@ SC.View.reopen(
163
195
  }
164
196
 
165
197
  didChange = YES;
166
- } else {
167
- hash = key;
168
-
169
- for (key in hash) {
170
- if (!hash.hasOwnProperty(key)) { continue; }
171
-
172
- value = hash[key];
173
- cur = layout[key];
174
-
175
- if (value === undefined || cur == value) { continue; }
176
-
177
- // only clone the layout the first time we see a change
178
- if (!didChange) layout = SC.clone(layout);
179
-
180
- if (value === null) {
181
- delete layout[key];
182
- } else {
183
- layout[key] = value;
184
- }
185
-
186
- didChange = YES;
187
- }
188
198
  }
189
199
 
190
200
  // now set adjusted layout
@@ -1229,7 +1239,7 @@ SC.View.reopen(
1229
1239
  }.enhance(),
1230
1240
 
1231
1241
  /** @private Override: Notify on attached (avoids notify of frame changed). */
1232
- _notifyAttached: function () {
1242
+ _notifyDidAttach: function () {
1233
1243
  // If we are using static layout then we don't know the frame until appended to the document.
1234
1244
  if (this.get('useStaticLayout')) {
1235
1245
  // We call viewDidResize so that it calls parentViewDidResize on all child views.
@@ -3,6 +3,19 @@ sc_require("views/view/base");
3
3
  // When in debug mode, core developers can log the view state.
4
4
  //@if (debug)
5
5
  SC.LOG_VIEW_STATES = false;
6
+ SC.LOG_VIEW_STATES_STYLE = {
7
+ 0x0200: 'color: #67b7db; font-style: italic;', // UNRENDERED
8
+ 0x0300: 'color: #67b7db; font-style: italic;', // UNATTACHED
9
+ 0x0301: 'color: #67b7db; font-style: italic;', // UNATTACHED_BY_PARENT
10
+ 0x03C0: 'color: #23abf5; font-style: italic;', // ATTACHED_SHOWN
11
+ 0x03A0: 'color: #67b7db; font-style: italic;', // ATTACHED_HIDDEN
12
+ 0x03A1: 'color: #67b7db; font-style: italic;', // ATTACHED_HIDDEN_BY_PARENT
13
+ 0x03C1: 'color: #b800db; font-style: italic;', // ATTACHED_BUILDING_IN
14
+ 0x0381: 'color: #b800db; font-style: italic;', // ATTACHED_BUILDING_OUT
15
+ 0x0382: 'color: #b800db; font-style: italic;', // ATTACHED_BUILDING_OUT_BY_PARENT
16
+ 0x03C2: 'color: #b800db; font-style: italic;', // ATTACHED_SHOWING
17
+ 0x03A2: 'color: #b800db; font-style: italic;' // ATTACHED_HIDING
18
+ };
6
19
  //@endif
7
20
 
8
21
 
@@ -167,10 +180,46 @@ SC.CoreView.mixin(
167
180
  SC.CoreView.reopen(
168
181
  /** @scope SC.CoreView.prototype */ {
169
182
 
183
+ //@if(debug)
184
+ /* BEGIN DEBUG ONLY PROPERTIES AND METHODS */
185
+
186
+ /** @private Creates string representation of view, with view state. */
187
+ toString: function () {
188
+ return "%@ (%@)".fmt(sc_super(), this._viewStateString());
189
+ },
190
+
191
+ /** @private Creates string representation of view state. */
192
+ _viewStateString: function () {
193
+ var ret = [], state = this.get('viewState');
194
+
195
+ for (var prop in SC.CoreView) {
196
+ if (prop.match(/[A-Z_]$/) && SC.CoreView[prop] === state) {
197
+ ret.push(prop);
198
+ }
199
+ }
200
+
201
+ return ret.join(" ");
202
+ },
203
+
204
+ /* END DEBUG ONLY PROPERTIES AND METHODS */
205
+ //@endif
206
+
170
207
  // ------------------------------------------------------------------------
171
208
  // Properties
172
209
  //
173
210
 
211
+ /* @private Internal variable used to store the number of children building out while we wait to be detached. */
212
+ _buildingOutCount: null,
213
+
214
+ /* @private Internal variable used to track the original view being detached that we are delaying so that we can build out. */
215
+ _owningView: null,
216
+
217
+ /* @private Internal variable used to store the original layout before running an automatic transition. */
218
+ _preTransitionLayout: null,
219
+
220
+ /* @private Internal variable used to store the original frame before running an automatic transition. */
221
+ _preTransitionFrame: null,
222
+
174
223
  /**
175
224
  The current state of the view as managed by its internal statechart.
176
225
 
@@ -255,11 +304,11 @@ SC.CoreView.reopen(
255
304
  state !== SC.CoreView.ATTACHED_HIDDEN_BY_PARENT;
256
305
  }.property('viewState').cacheable(),
257
306
 
307
+
258
308
  // ------------------------------------------------------------------------
259
309
  // Actions (Locked down to the proper state)
260
310
  //
261
311
 
262
-
263
312
  /** @private Adopt this view action. */
264
313
  _doAdopt: function (parentView, beforeView) {
265
314
  var curParentView = this.get('parentView'),
@@ -267,7 +316,7 @@ SC.CoreView.reopen(
267
316
 
268
317
  //@if (debug)
269
318
  if (SC.LOG_VIEW_STATES) {
270
- SC.Logger.log('%@:%@ — _doAdopt(%@, %@)'.fmt(this, this.get('viewState'), parentView, beforeView));
319
+ SC.Logger.log('%c%@ — _doAdopt(%@, %@)'.fmt(this, parentView, beforeView), SC.LOG_VIEW_STATES_STYLE[this.get('viewState')]);
271
320
  }
272
321
  //@endif
273
322
 
@@ -290,7 +339,7 @@ SC.CoreView.reopen(
290
339
  parentViewState = parentView.get('viewState'),
291
340
  parentNode, nextNode, nextView, siblings;
292
341
 
293
- // Send notifications.
342
+ // Notify *will* (top-down from parent to children).
294
343
  if (parentView.willAddChild) { parentView.willAddChild(this, beforeView); }
295
344
  if (this.willAddToParent) { this.willAddToParent(parentView, beforeView); }
296
345
 
@@ -347,9 +396,9 @@ SC.CoreView.reopen(
347
396
  }
348
397
  }
349
398
 
350
- // Notify.
351
- if (parentView.didAddChild) { parentView.didAddChild(this, beforeView); }
399
+ // Notify *did* (bottom-up from children to parent).
352
400
  if (this.didAddToParent) { this.didAddToParent(parentView, beforeView); }
401
+ if (parentView.didAddChild) { parentView.didAddChild(this, beforeView); }
353
402
  } else {
354
403
  handled = false;
355
404
  }
@@ -361,50 +410,64 @@ SC.CoreView.reopen(
361
410
  _doAttach: function (parentNode, nextNode) {
362
411
  var state = this.get('viewState'),
363
412
  transitionIn = this.get('transitionIn'),
364
- parentView;
413
+ parentView,
414
+ isHandled = false;
365
415
 
366
416
  //@if (debug)
367
417
  if (SC.LOG_VIEW_STATES) {
368
- SC.Logger.log('%@:%@ — _doAttach(%@, %@)'.fmt(this, state, parentNode, nextNode));
418
+ SC.Logger.log('%c%@ — _doAttach(%@, %@)'.fmt(this, parentNode, nextNode), SC.LOG_VIEW_STATES_STYLE[this.get('viewState')]);
369
419
  }
370
420
  //@endif
371
421
 
372
422
  switch (state) {
373
- case SC.CoreView.ATTACHED_HIDING: // FAST PATH!
374
- case SC.CoreView.ATTACHED_HIDDEN: // FAST PATH!
375
- case SC.CoreView.ATTACHED_HIDDEN_BY_PARENT: // FAST PATH!
376
- case SC.CoreView.ATTACHED_BUILDING_IN: // FAST PATH!
377
- case SC.CoreView.ATTACHED_BUILDING_OUT_BY_PARENT: // FAST PATH!
378
- case SC.CoreView.ATTACHED_SHOWING: // FAST PATH!
379
- case SC.CoreView.ATTACHED_SHOWN: // FAST PATH!
380
- //@if(debug)
381
- // This should be avoided, because moving the view layer without explicitly removing it first is a dangerous practice.
382
- SC.warn("Developer Warning: You can not attach the view, %@, to a new node without properly detaching it first.".fmt(this));
383
- //@endif
384
- return false;
385
- case SC.CoreView.UNATTACHED_BY_PARENT:
386
- //@if(debug)
387
- SC.warn("Developer Warning: You can not attach the child view, %@, directly.".fmt(this));
388
- //@endif
389
- return false;
390
- case SC.CoreView.UNRENDERED: // FAST PATH!
391
- return false;
423
+
424
+ // Normal case: view is not attached and is being attached.
425
+ case SC.CoreView.UNATTACHED:
426
+ var node = this.get('layer');
427
+
428
+ this._executeQueuedUpdates();
429
+
430
+ // Attach to parentNode
431
+ // IE doesn't support insertBefore(blah, undefined) in version IE9.
432
+ parentNode.insertBefore(node, nextNode || null);
433
+
434
+ parentView = this.get('parentView');
435
+ if (!parentView || (parentView && parentView.get('isAttached'))) {
436
+ // Update states after *will* and before *did* notifications!
437
+ this._routeOnAttached();
438
+
439
+ // Give child views a chance to notify and update state.
440
+ this._callOnChildViews('_parentDidAppendToDocument');
441
+
442
+ // Notify *did* (bottom-up from children to parent).
443
+ this._notifyDidAttach();
444
+ } else {
445
+ // Update states after *will* and before *did* notifications!
446
+ this._gotoUnattachedByParentState();
447
+ }
448
+
449
+ isHandled = true;
450
+ break;
451
+
452
+ // Special case: view switched from building out to building in.
392
453
  case SC.CoreView.ATTACHED_BUILDING_OUT:
393
454
  // If already building out, we need to cancel and possibly build in.
394
455
  this._callOnChildViews('_parentDidCancelBuildOut');
395
456
 
396
457
  // Remove the shared building out count if it exists.
397
- delete this._buildingOutCount;
458
+ this._buildingOutCount = null;
398
459
 
399
460
  // Note: We can be in ATTACHED_BUILDING_OUT state without a transition out while we wait for child views.
461
+ // Update states after *will* and before *did* notifications!
400
462
  if (this.get('transitionOut')) {
401
463
  if (transitionIn) {
402
- this._transitionIn();
464
+ // this.invokeNext(function () {
465
+ this._transitionIn();
466
+ // });
403
467
 
404
- // Route.
405
468
  this._gotoAttachedBuildingInState();
406
469
  } else {
407
- // Route first!
470
+ // Update state first!
408
471
  this._gotoAttachedShownState();
409
472
 
410
473
  this._cancelTransition();
@@ -415,122 +478,178 @@ SC.CoreView.reopen(
415
478
  this._gotoAttachedShownState();
416
479
  }
417
480
 
481
+ isHandled = true;
418
482
  break;
419
- case SC.CoreView.UNATTACHED:
420
- var node = this.get('layer');
421
-
422
- this._executeQueuedUpdates();
423
-
424
- // Attach to parentNode
425
- // IE doesn't support insertBefore(blah, undefined) in version IE9.
426
- parentNode.insertBefore(node, nextNode || null);
427
-
428
- parentView = this.get('parentView');
429
- if (!parentView || (parentView && parentView.get('isAttached'))) {
430
- // Notify.
431
- this._notifyAttached();
432
483
 
433
- // Route.
434
- this._routeOnAttached();
484
+ // Invalid states that have no effect.
485
+ case SC.CoreView.ATTACHED_HIDING:
486
+ case SC.CoreView.ATTACHED_HIDDEN:
487
+ case SC.CoreView.ATTACHED_HIDDEN_BY_PARENT:
488
+ case SC.CoreView.ATTACHED_BUILDING_IN:
489
+ case SC.CoreView.ATTACHED_BUILDING_OUT_BY_PARENT:
490
+ case SC.CoreView.ATTACHED_SHOWING:
491
+ case SC.CoreView.UNRENDERED:
492
+ break;
435
493
 
436
- // Give child views a chance to notify and update state.
437
- this._callOnChildViews('_parentDidAppendToDocument');
438
- } else {
439
- // Route.
440
- this._gotoUnattachedByParentState();
441
- }
494
+ // Improper states that have no effect, but should be discouraged.
495
+ case SC.CoreView.ATTACHED_SHOWN:
496
+ //@if(debug)
497
+ // This should be avoided, because moving the view layer without explicitly removing it first is a dangerous practice.
498
+ SC.warn("Developer Warning: You can not attach the view, %@, to a new node without properly detaching it first.".fmt(this));
499
+ //@endif
500
+ break;
501
+ case SC.CoreView.UNATTACHED_BY_PARENT:
502
+ //@if(debug)
503
+ SC.warn("Developer Warning: You can not attach the child view, %@, directly.".fmt(this));
504
+ //@endif
442
505
  break;
443
- default:
444
506
  }
445
507
 
446
- return true;
508
+ return isHandled;
447
509
  },
448
510
 
449
511
  /** @private Destroy the layer of this view action. */
450
512
  _doDestroyLayer: function () {
451
- var handled = true;
513
+ var state = this.get('viewState'),
514
+ isHandled = false;
452
515
 
453
516
  //@if (debug)
454
517
  if (SC.LOG_VIEW_STATES) {
455
- SC.Logger.log('%@:%@ — _doDestroyLayer()'.fmt(this, this.get('viewState')));
518
+ SC.Logger.log('%c%@ — _doDestroyLayer()'.fmt(this), SC.LOG_VIEW_STATES_STYLE[this.get('viewState')]);
456
519
  }
457
520
  //@endif
458
521
 
459
- if (this.get('_isRendered') && !this.get('isAttached')) {
522
+ switch (state) {
523
+
524
+ // Invalid states that have no effect.
525
+ case SC.CoreView.UNRENDERED:
526
+ case SC.CoreView.ATTACHED_HIDING:
527
+ case SC.CoreView.ATTACHED_HIDDEN:
528
+ case SC.CoreView.ATTACHED_HIDDEN_BY_PARENT:
529
+ case SC.CoreView.ATTACHED_BUILDING_IN:
530
+ case SC.CoreView.ATTACHED_BUILDING_OUT_BY_PARENT:
531
+ case SC.CoreView.ATTACHED_SHOWING:
532
+ case SC.CoreView.ATTACHED_SHOWN:
533
+ case SC.CoreView.UNATTACHED_BY_PARENT:
534
+ case SC.CoreView.ATTACHED_BUILDING_OUT:
535
+ break;
536
+
537
+ // Normal case (SC.CoreView.UNATTACHED): view is rendered and its layer is being destroyed.
538
+ default:
539
+ // Notify *will* (top-down from parent to children).
540
+ this._notifyWillDestroyLayer();
541
+ this._callOnChildViews('_notifyWillDestroyLayer');
542
+
460
543
  // Remove our reference to the layer (our self and all our child views).
461
544
  this._executeDoDestroyLayer();
462
545
  this._callOnChildViews('_executeDoDestroyLayer');
463
- } else {
464
- handled = false;
546
+
547
+ // UNUSED.
548
+ // Notify *did* (bottom-up from children to parent).
549
+ // this._callOnChildViews('_notifyDidDestroyLayer');
550
+ // this._notifyDidDestroyLayer();
551
+
552
+ isHandled = true;
465
553
  }
466
554
 
467
- return handled;
555
+ return isHandled;
468
556
  },
469
557
 
470
558
  /** @private Detach this view action. */
471
559
  _doDetach: function (immediately) {
472
560
  var state = this.get('viewState'),
473
- transitionOut = this.get('transitionOut');
561
+ transitionOut = this.get('transitionOut'),
562
+ inPlace = false,
563
+ isHandled = true;
474
564
 
475
565
  //@if (debug)
476
566
  if (SC.LOG_VIEW_STATES) {
477
- SC.Logger.log('%@:%@ — _doDetach()'.fmt(this, state));
567
+ SC.Logger.log('%c%@ — _doDetach()'.fmt(this), SC.LOG_VIEW_STATES_STYLE[this.get('viewState')]);
478
568
  }
479
569
  //@endif
480
570
 
481
571
  switch (state) {
482
- case SC.CoreView.UNRENDERED: // FAST PATH!
483
- case SC.CoreView.UNATTACHED: // FAST PATH!
484
- return false;
485
- case SC.CoreView.ATTACHED_BUILDING_OUT_BY_PARENT: // FAST PATH!
486
- if (immediately) {
487
- // Don't wait for the build out to complete.
488
- this._cancelTransition();
489
572
 
490
- // Detach immediately.
491
- this._executeDoDetach();
492
- } else {
493
- // TODO: take ownership of the building out of self and all childviews. Super edge case stuff here..
494
- this._gotoAttachedBuildingOutState();
495
- }
496
-
497
- // Don't try to notify or run transition out code again.
498
- return true;
499
- case SC.CoreView.ATTACHED_BUILDING_OUT: // FAST PATH!
500
- // If already building out, only cancel if immediately is set.
501
- if (immediately) {
502
- this._cancelTransition();
503
-
504
- // Detach immediately.
505
- this._executeDoDetach();
506
- }
573
+ // Normal case: Attached visible view being detached.
574
+ case SC.CoreView.ATTACHED_SHOWN:
575
+ break;
507
576
 
508
- // Don't try to notify or run transition out code again.
509
- return true;
577
+ // Normal case: Attached non-visible view being detached.
510
578
  case SC.CoreView.UNATTACHED_BY_PARENT:
511
579
  case SC.CoreView.ATTACHED_HIDDEN:
512
580
  case SC.CoreView.ATTACHED_HIDDEN_BY_PARENT:
513
581
  // No need to transition out, since we're hidden.
514
582
  immediately = true;
515
583
  break;
584
+
585
+ // Near normal case: Attached showing view. We cancel the incoming animation
586
+ // rather than swapping to a build out (difficult to get right, because we lose track of the correct final layout).
587
+ case SC.CoreView.ATTACHED_SHOWING:
588
+ this.cancelAnimation(); // Fires didTransitionIn callback (state changes to ATTACHED_SHOWN/notifications sent).
589
+ break;
590
+
591
+ // Near normal case: Attached hiding view. We cancel the outgoing animation
592
+ // rather than swapping to a build out (difficult to get right, because we lose track of the correct final layout).
516
593
  case SC.CoreView.ATTACHED_HIDING:
517
- if (immediately || !transitionOut) {
518
- this._cancelTransition();
519
- }
594
+ this.cancelAnimation(); // Fires didTransitionOut callback (state changes to ATTACHED_HIDDEN/notifications sent).
595
+
596
+ // No need to transition out, since we're hidden.
597
+ immediately = true;
520
598
  break;
599
+
600
+ // Near normal case: Attached building in view. We cancel the incoming
601
+ // animation and build out the view in place.
521
602
  case SC.CoreView.ATTACHED_BUILDING_IN:
522
603
  if (immediately || !transitionOut) {
523
- this._cancelTransition();
604
+ this.cancelAnimation(); // Fires didTransitionIn callback (state changes to ATTACHED_SHOWN/notifications sent).
605
+ } else {
606
+ // Set the state manually so the callback doesn't do clean up and notify.
607
+ this._gotoAttachedShownState();
608
+
609
+ // Cancel the animation in place (setup properties still exist and will be cleared by transitionOut)
610
+ this.cancelAnimation(SC.LayoutState.CURRENT); // Fires didTransitionIn callback (no state change/no notifications).
611
+
612
+ // Transition out in place.
613
+ inPlace = true;
524
614
  }
525
615
  break;
526
- case SC.CoreView.ATTACHED_SHOWING:
527
- case SC.CoreView.ATTACHED_SHOWN:
616
+
617
+ // Special case: Already building out, because parent is building out. Stop
618
+ // the transition in place so that it can continue in place on its own.
619
+ case SC.CoreView.ATTACHED_BUILDING_OUT_BY_PARENT: // FAST PATH!
620
+ // Note: *will* detach notice already sent.
621
+ this.cancelAnimation(SC.LayoutState.CURRENT); // Fires didTransitionOut callback (necessary to clean up parent view build out wait)
622
+
623
+ // Switch state to regular state (the view should only have been able to get to ATTACHED_BUILDING_OUT_BY_PARENT from ATTACHED_SHOWN).
624
+ this._gotoAttachedShownState();
625
+
626
+ // TODO: Grab the build out count for all child views of this view. What a nightmare for an edge case!
627
+
628
+ // Transition out in place.
629
+ inPlace = true;
630
+
528
631
  break;
529
- default:
632
+
633
+ // Special case: Already building out. Fast path!
634
+ case SC.CoreView.ATTACHED_BUILDING_OUT:
635
+ // If immediately is passed, cancel the build out prematurely.
636
+ if (immediately) {
637
+ // Note: *will* detach notice already sent.
638
+ this.cancelAnimation(); // Fires didTransitionOut callback (state changes to UNATTACHED/notifications sent).
639
+ }
640
+
641
+ // Don't try to notify or run transition out code again.
642
+ return true;
643
+
644
+ // Invalid states that have no effect. Fast path!
645
+ case SC.CoreView.UNRENDERED:
646
+ case SC.CoreView.UNATTACHED:
647
+ return false;
530
648
  }
531
649
 
532
- // Notify.
533
- this._notifyDetaching();
650
+ // Notify *will* (top-down from parent to children). The children will be
651
+ // notified only when they are actually about to be removed.
652
+ // this._notifyWillDetach();
534
653
 
535
654
  if (immediately) {
536
655
  // Detach immediately.
@@ -545,22 +664,24 @@ SC.CoreView.reopen(
545
664
  this._callOnChildViews('_parentWillBuildOutFromDocument', this);
546
665
 
547
666
  if (transitionOut) {
548
- this._transitionOut(this);
667
+ // this.invokeNext(function () {
668
+ this._transitionOut(inPlace, this);
669
+ // });
549
670
 
550
- // Route.
671
+ // Update states after *will* and before *did* notifications!
551
672
  this._gotoAttachedBuildingOutState();
552
673
  } else if (this._buildingOutCount > 0) {
553
- // Some children are building out, we will have to wait for them.
674
+ // Some children are building out, we will have to wait for them.
554
675
  this._gotoAttachedBuildingOutState();
555
676
  } else {
556
- delete this._buildingOutCount;
677
+ this._buildingOutCount = null;
557
678
 
558
679
  // Detach immediately.
559
680
  this._executeDoDetach();
560
681
  }
561
682
  }
562
683
 
563
- return true;
684
+ return isHandled;
564
685
  },
565
686
 
566
687
  /** @private Hide this view action. */
@@ -570,7 +691,7 @@ SC.CoreView.reopen(
570
691
 
571
692
  //@if (debug)
572
693
  if (SC.LOG_VIEW_STATES) {
573
- SC.Logger.log('%@:%@ — _doHide()'.fmt(this, state));
694
+ SC.Logger.log('%c%@ — _doHide()'.fmt(this), SC.LOG_VIEW_STATES_STYLE[this.get('viewState')]);
574
695
  }
575
696
  //@endif
576
697
 
@@ -591,6 +712,7 @@ SC.CoreView.reopen(
591
712
  // Note that visibility update is NOT conditional for this state.
592
713
  this._doUpdateVisibleStyle();
593
714
 
715
+ // Update states after *will* and before *did* notifications!
594
716
  this._gotoAttachedHiddenState();
595
717
 
596
718
  return true;
@@ -605,14 +727,17 @@ SC.CoreView.reopen(
605
727
  default:
606
728
  }
607
729
 
608
- // Notify will hide.
730
+ // Notify *will* (top-down from parent to children).
609
731
  if (this.willHideInDocument) { this.willHideInDocument(); }
610
732
 
611
733
  if (transitionHide) {
612
- this._transitionHide();
613
-
614
- // Route.
734
+ // Update states after *will* and before *did* notifications!
615
735
  this._gotoAttachedHidingState();
736
+
737
+ // this.invokeNext(function () {
738
+ this._transitionHide();
739
+ // });
740
+
616
741
  } else {
617
742
  // Clear out any child views that are still transitioning before we hide.
618
743
  this._callOnChildViews('_parentWillHideInDocument');
@@ -620,13 +745,12 @@ SC.CoreView.reopen(
620
745
  // Note that visibility update is NOT conditional for this state.
621
746
  this.invokeOnce(this._doUpdateVisibleStyle);
622
747
 
623
- // Notify.
624
- if (this.didHideInDocument) { this.didHideInDocument(); }
625
-
748
+ // Update states after *will* and before *did* notifications!
749
+ this._gotoAttachedHiddenState();
626
750
  this._callOnChildViews('_parentDidHideInDocument');
627
751
 
628
- // Route.
629
- this._gotoAttachedHiddenState();
752
+ // Notify *did* (bottom-up from children to parent).
753
+ if (this.didHideInDocument) { this.didHideInDocument(); }
630
754
  }
631
755
 
632
756
  return true;
@@ -639,7 +763,7 @@ SC.CoreView.reopen(
639
763
 
640
764
  //@if (debug)
641
765
  if (SC.LOG_VIEW_STATES) {
642
- SC.Logger.log('%@:%@ — _doOrphan()'.fmt(this, this.get('viewState')));
766
+ SC.Logger.log('%c%@ — _doOrphan()'.fmt(this), SC.LOG_VIEW_STATES_STYLE[this.get('viewState')]);
643
767
  }
644
768
  //@endif
645
769
 
@@ -668,7 +792,7 @@ SC.CoreView.reopen(
668
792
 
669
793
  //@if (debug)
670
794
  if (SC.LOG_VIEW_STATES) {
671
- SC.Logger.log('%@:%@ — _doRender()'.fmt(this, state));
795
+ SC.Logger.log('%c%@ — _doRender()'.fmt(this), SC.LOG_VIEW_STATES_STYLE[this.get('viewState')]);
672
796
  }
673
797
  //@endif
674
798
 
@@ -691,12 +815,12 @@ SC.CoreView.reopen(
691
815
  this.renderToContext(context);
692
816
  this.set('layer', context.element());
693
817
 
694
- // Route first.
818
+ // Update states after *will* and before *did* notifications!
695
819
  this._gotoUnattachedState();
696
820
 
697
- // Notify rendered (on self and all child views).
698
- this._rendered();
821
+ // Notify *did* (bottom-up from children to parent).
699
822
  this._callOnChildViews('_parentDidRender');
823
+ this._rendered();
700
824
 
701
825
  // Bypass the unattached state for adopted views.
702
826
  var parentView = this.get('parentView');
@@ -726,65 +850,74 @@ SC.CoreView.reopen(
726
850
 
727
851
  //@if (debug)
728
852
  if (SC.LOG_VIEW_STATES) {
729
- SC.Logger.log('%@:%@ — _doShow()'.fmt(this, state));
853
+ SC.Logger.log('%c%@ — _doShow()'.fmt(this), SC.LOG_VIEW_STATES_STYLE[this.get('viewState')]);
730
854
  }
731
855
  //@endif
732
856
 
733
857
  switch (state) {
734
- case SC.CoreView.ATTACHED_SHOWN: // FAST PATH!
735
- case SC.CoreView.ATTACHED_SHOWING: // FAST PATH!
736
- case SC.CoreView.ATTACHED_HIDDEN_BY_PARENT: // FAST PATH!
737
- case SC.CoreView.ATTACHED_BUILDING_IN: // FAST PATH!
738
- case SC.CoreView.ATTACHED_BUILDING_OUT_BY_PARENT: // FAST PATH!
739
- case SC.CoreView.ATTACHED_BUILDING_OUT: // FAST PATH!
740
- return false;
741
- case SC.CoreView.UNRENDERED: // FAST PATH!
742
- case SC.CoreView.UNATTACHED: // FAST PATH!
743
- case SC.CoreView.UNATTACHED_BY_PARENT: // FAST PATH!
744
- // Queue the visibility update for the next time we display.
745
- this._visibleStyleNeedsUpdate = true;
746
- return true;
858
+
859
+ // Normal case: view is hidden and is being shown.
747
860
  case SC.CoreView.ATTACHED_HIDDEN:
748
861
  if (isParentShown) {
749
862
  // Update before showing (note that visibility update is NOT conditional for this state).
750
863
  this._doUpdateVisibleStyle();
751
864
 
752
- // Notify will show.
865
+ // Notify *will* (top-down from parent to children).
753
866
  this._callOnChildViews('_parentWillShowInDocument');
754
-
755
867
  if (this.willShowInDocument) { this.willShowInDocument(); }
756
868
  } else {
757
869
  // Queue the visibility update for the next time we display.
758
870
  this._visibleStyleNeedsUpdate = true;
759
871
 
760
- // Route.
872
+ // Update states after *will* and before *did* notifications!
761
873
  this._gotoAttachedHiddenByParentState();
762
874
 
763
875
  return true;
764
876
  }
765
877
  break;
878
+
766
879
  case SC.CoreView.ATTACHED_HIDING:
767
880
  if (!transitionShow) {
768
881
  this._cancelTransition();
769
882
  }
770
883
  break;
884
+
885
+ // Special case: Layer exists but is not attached. Queue an update to the visibility style.
886
+ case SC.CoreView.UNATTACHED:
887
+ case SC.CoreView.UNATTACHED_BY_PARENT:
888
+ // Queue the visibility update for the next time we display.
889
+ this._visibleStyleNeedsUpdate = true;
890
+ return true;
891
+
892
+ // Invalid states that have no effect.
893
+ case SC.CoreView.UNRENDERED: // FAST PATH!
894
+ case SC.CoreView.ATTACHED_SHOWN: // FAST PATH!
895
+ case SC.CoreView.ATTACHED_SHOWING: // FAST PATH!
896
+ case SC.CoreView.ATTACHED_HIDDEN_BY_PARENT: // FAST PATH!
897
+ case SC.CoreView.ATTACHED_BUILDING_IN: // FAST PATH!
898
+ case SC.CoreView.ATTACHED_BUILDING_OUT_BY_PARENT: // FAST PATH!
899
+ case SC.CoreView.ATTACHED_BUILDING_OUT: // FAST PATH!
900
+ return false;
901
+
771
902
  default:
772
903
  }
773
904
 
774
905
  this._executeQueuedUpdates();
775
906
 
776
907
  if (transitionShow) {
777
- this._transitionShow();
778
-
779
- // Route.
908
+ // Update states after *will* and before *did* notifications!
780
909
  this._gotoAttachedShowingState();
910
+
911
+ // this.invokeNext(function () {
912
+ this._transitionShow();
913
+ // });
781
914
  } else {
782
- // Notify.
915
+ // Update states after *will* and before *did* notifications!
916
+ this._gotoAttachedShownState();
917
+
918
+ // Notify *did* (bottom-up from children to parent).
783
919
  if (this.didShowInDocument) { this.didShowInDocument(); }
784
920
  this._callOnChildViews('_parentDidShowInDocument');
785
-
786
- // Route.
787
- this._gotoAttachedShownState();
788
921
  }
789
922
 
790
923
  return true;
@@ -797,7 +930,7 @@ SC.CoreView.reopen(
797
930
 
798
931
  //@if (debug)
799
932
  if (SC.LOG_VIEW_STATES) {
800
- SC.Logger.log('%@:%@ — _doUpdateContent(%@)'.fmt(this, this.get('viewState'), force));
933
+ SC.Logger.log('%c%@ — _doUpdateContent(%@)'.fmt(this, force), SC.LOG_VIEW_STATES_STYLE[this.get('viewState')]);
801
934
  }
802
935
  //@endif
803
936
 
@@ -831,19 +964,24 @@ SC.CoreView.reopen(
831
964
  didTransitionIn: function () {
832
965
  var state = this.get('viewState');
833
966
 
967
+ //@if (debug)
968
+ if (SC.LOG_VIEW_STATES) {
969
+ SC.Logger.log('%c%@ — didTransitionIn()'.fmt(this), SC.LOG_VIEW_STATES_STYLE[this.get('viewState')]);
970
+ }
971
+ //@endif
972
+
834
973
  if (state === SC.CoreView.ATTACHED_SHOWING ||
835
974
  state === SC.CoreView.ATTACHED_BUILDING_IN) {
836
975
  this._teardownTransition();
837
976
 
838
- // Notify.
839
- if (this.didShowInDocument) { this.didShowInDocument(); }
977
+ // Update states after *will* and before *did* notifications!
978
+ this._gotoAttachedShownState();
840
979
 
980
+ // Notify *did* (bottom-up from children to parent).
981
+ if (this.didShowInDocument) { this.didShowInDocument(); }
841
982
  if (state === SC.CoreView.ATTACHED_SHOWING) {
842
983
  this._callOnChildViews('_parentDidShowInDocument');
843
984
  }
844
-
845
- // Route.
846
- this._gotoAttachedShownState();
847
985
  }
848
986
  },
849
987
 
@@ -858,6 +996,12 @@ SC.CoreView.reopen(
858
996
  didTransitionOut: function () {
859
997
  var state = this.get('viewState');
860
998
 
999
+ //@if (debug)
1000
+ if (SC.LOG_VIEW_STATES) {
1001
+ SC.Logger.log('%c%@ — didTransitionOut()'.fmt(this), SC.LOG_VIEW_STATES_STYLE[this.get('viewState')]);
1002
+ }
1003
+ //@endif
1004
+
861
1005
  if (state === SC.CoreView.ATTACHED_BUILDING_OUT) {
862
1006
  this._teardownTransition();
863
1007
 
@@ -872,30 +1016,29 @@ SC.CoreView.reopen(
872
1016
  owningView._executeDoDetach();
873
1017
 
874
1018
  // Clean up.
875
- delete this._owningView;
1019
+ this._owningView = null;
876
1020
  }
877
1021
  } else if (state === SC.CoreView.ATTACHED_HIDING) {
878
1022
  this._teardownTransition();
879
1023
 
880
- // Clear out any child views that are transitioning before we hide.
1024
+ // Notify *will* (top-down from parent to children).
881
1025
  this._callOnChildViews('_parentWillHideInDocument');
882
1026
 
883
1027
  // Note that visibility update is NOT conditional for this state.
884
1028
  this._doUpdateVisibleStyle();
885
1029
 
886
- // Notify.
887
- if (this.didHideInDocument) { this.didHideInDocument(); }
1030
+ // Update states after *will* and before *did* notifications!
1031
+ this._gotoAttachedHiddenState();
888
1032
 
1033
+ // Notify *did* (bottom-up from children to parent).
889
1034
  this._callOnChildViews('_parentDidHideInDocument');
890
-
891
- // Route.
892
- this._gotoAttachedHiddenState();
1035
+ if (this.didHideInDocument) { this.didHideInDocument(); }
893
1036
  }
894
1037
  },
895
1038
 
896
1039
  /** @private The 'adopted' event. */
897
1040
  _adopted: function () {
898
- // This has been moved to the _notifyAttached event.
1041
+ // This has been moved to the _notifyDidAttach event.
899
1042
  // this.notifyPropertyChange('frame');
900
1043
  },
901
1044
 
@@ -909,8 +1052,7 @@ SC.CoreView.reopen(
909
1052
  /** @private The 'rendered' event. */
910
1053
  _rendered: function () {
911
1054
  var displayProperties,
912
- len, idx,
913
- mixins = this.didCreateLayerMixin;
1055
+ len, idx;
914
1056
 
915
1057
  // Register display property observers.
916
1058
  displayProperties = this.get('displayProperties');
@@ -918,18 +1060,13 @@ SC.CoreView.reopen(
918
1060
  this.addObserver(displayProperties[idx], this, this.displayDidChange);
919
1061
  }
920
1062
 
1063
+ // Begin observing isVisible & isFirstResponder.
1064
+ this.addObserver('isVisible', this, this._isVisibleDidChange);
1065
+ this.addObserver('isFirstResponder', this, this._isFirstResponderDidChange);
1066
+
921
1067
  // TODO: we should be able to fix this with states
922
1068
  // if (this.get('useStaticLayout')) this.viewDidResize();
923
1069
 
924
- // Send notice that the layer was created.
925
- if (this.didCreateLayer) { this.didCreateLayer(); }
926
- if (mixins) {
927
- len = mixins.length;
928
- for (idx = 0; idx < len; ++idx) {
929
- mixins[idx].call(this);
930
- }
931
- }
932
-
933
1070
  // var childView, childViews = this.get('childViews');
934
1071
  // for (var i = childViews.length - 1; i >= 0; i--) {
935
1072
  // childView = childViews[i];
@@ -956,9 +1093,8 @@ SC.CoreView.reopen(
956
1093
  // childView._rendered();
957
1094
  // }
958
1095
 
959
- // Begin observing isVisible & isFirstResponder.
960
- this.addObserver('isVisible', this, this._isVisibleDidChange);
961
- this.addObserver('isFirstResponder', this, this._isFirstResponderDidChange);
1096
+ // Notify.
1097
+ this._notifyDidRender();
962
1098
  },
963
1099
 
964
1100
  // ------------------------------------------------------------------------
@@ -1039,7 +1175,7 @@ SC.CoreView.reopen(
1039
1175
  _cancelTransition: function () {
1040
1176
  // Cancel conflicting transitions.
1041
1177
  this.cancelAnimation();
1042
- this._teardownTransition();
1178
+ // this._teardownTransition();
1043
1179
  },
1044
1180
 
1045
1181
  /** @private */
@@ -1053,22 +1189,10 @@ SC.CoreView.reopen(
1053
1189
  this._visibleStyleNeedsUpdate = false;
1054
1190
  },
1055
1191
 
1056
- /** @private */
1192
+ /** @private Destroys the layer and updates the state. */
1057
1193
  _executeDoDestroyLayer: function () {
1058
1194
  var displayProperties,
1059
- idx, len,
1060
- mixins;
1061
-
1062
- // Notify.
1063
- if (this.willDestroyLayer) { this.willDestroyLayer(); }
1064
-
1065
- mixins = this.willDestroyLayerMixin;
1066
- if (mixins) {
1067
- len = mixins.length;
1068
- for (idx = 0; idx < len; ++idx) {
1069
- mixins[idx].call(this);
1070
- }
1071
- }
1195
+ idx, len;
1072
1196
 
1073
1197
  // Remove the layer reference.
1074
1198
  this.set('layer', null);
@@ -1083,27 +1207,23 @@ SC.CoreView.reopen(
1083
1207
  this.removeObserver('isVisible', this, this._isVisibleDidChange);
1084
1208
  this.removeObserver('isFirstResponder', this, this._isFirstResponderDidChange);
1085
1209
 
1086
- // Route.
1210
+ // Update states after *will* and before *did* notifications!
1087
1211
  this._gotoUnrenderedState();
1088
1212
  },
1089
1213
 
1090
- /** @private Detach the view. */
1214
+ /** @private Detaches the view and updates the state. */
1091
1215
  _executeDoDetach: function () {
1092
- // Give child views a chance to clean up any transitions and to notify.
1216
+ // Notify *will* (top-down from parent to children).
1217
+ this._notifyWillDetach();
1093
1218
  this._callOnChildViews('_parentWillRemoveFromDocument');
1094
1219
 
1095
1220
  // Detach the layer.
1096
1221
  var node = this.get('layer');
1097
1222
  node.parentNode.removeChild(node);
1098
1223
 
1099
- // Notify.
1100
- this._notifyDetached();
1101
-
1102
- // Give child views a chance to clean up any transitions and to notify.
1103
- this._callOnChildViews('_parentDidRemoveFromDocument');
1104
-
1105
- // Route.
1224
+ // Update states after *will* and before *did* notifications!
1106
1225
  this._gotoUnattachedState();
1226
+ this._callOnChildViews('_parentDidRemoveFromDocument');
1107
1227
  },
1108
1228
 
1109
1229
  /** @private */
@@ -1189,8 +1309,22 @@ SC.CoreView.reopen(
1189
1309
  this.$().toggleClass('focus', isFirstResponder);
1190
1310
  },
1191
1311
 
1312
+ _notifyDidRender: function () {
1313
+ var mixins = this.didCreateLayerMixin,
1314
+ idx, len;
1315
+
1316
+ // Send notice that the layer was created.
1317
+ if (this.didCreateLayer) { this.didCreateLayer(); }
1318
+ if (mixins) {
1319
+ len = mixins.length;
1320
+ for (idx = 0; idx < len; ++idx) {
1321
+ mixins[idx].call(this);
1322
+ }
1323
+ }
1324
+ },
1325
+
1192
1326
  /** @private Notify on attached. */
1193
- _notifyAttached: function () {
1327
+ _notifyDidAttach: function () {
1194
1328
  // If we don't have the layout module then we don't know the frame until appended to the document.
1195
1329
  this.notifyPropertyChange('frame');
1196
1330
 
@@ -1199,12 +1333,24 @@ SC.CoreView.reopen(
1199
1333
  },
1200
1334
 
1201
1335
  /** @private Notify on detaching. */
1202
- _notifyDetaching: function () {
1336
+ _notifyWillDetach: function () {
1203
1337
  if (this.willRemoveFromDocument) { this.willRemoveFromDocument(); }
1204
1338
  },
1205
1339
 
1206
- /** @private Notify on detached. */
1207
- _notifyDetached: function () {
1340
+ /** @private Notify before destroying layer. */
1341
+ _notifyWillDestroyLayer: function () {
1342
+ var idx, len,
1343
+ mixins;
1344
+
1345
+ mixins = this.willDestroyLayerMixin;
1346
+ if (mixins) {
1347
+ len = mixins.length;
1348
+ for (idx = 0; idx < len; ++idx) {
1349
+ mixins[idx].call(this);
1350
+ }
1351
+ }
1352
+
1353
+ if (this.willDestroyLayer) { this.willDestroyLayer(); }
1208
1354
  },
1209
1355
 
1210
1356
  /** @private Routes according to parent did append. */
@@ -1212,8 +1358,11 @@ SC.CoreView.reopen(
1212
1358
  // Run any queued updates.
1213
1359
  this._executeQueuedUpdates();
1214
1360
 
1215
- this._notifyAttached();
1361
+ // Update states after *will* and before *did* notifications!
1216
1362
  this._routeOnAttached();
1363
+
1364
+ // Notify.
1365
+ this._notifyDidAttach();
1217
1366
  },
1218
1367
 
1219
1368
  /** @private Updates according to parent did cancel build out. */
@@ -1223,14 +1372,16 @@ SC.CoreView.reopen(
1223
1372
 
1224
1373
  if (state === SC.CoreView.ATTACHED_BUILDING_OUT_BY_PARENT) {
1225
1374
  if (transitionIn) {
1226
- this._transitionIn();
1375
+ // this.invokeNext(function () {
1376
+ this._transitionIn();
1377
+ // });
1227
1378
 
1228
- // Route.
1379
+ // Update states after *will* and before *did* notifications!
1229
1380
  this._gotoAttachedBuildingInState();
1230
1381
  } else {
1231
1382
  this._cancelTransition();
1232
1383
 
1233
- // Route.
1384
+ // Update states after *will* and before *did* notifications!
1234
1385
  this._gotoAttachedShownState();
1235
1386
  }
1236
1387
  } else if (state === SC.CoreView.ATTACHED_BUILDING_OUT || state &
@@ -1242,10 +1393,9 @@ SC.CoreView.reopen(
1242
1393
 
1243
1394
  /** @private Updates according to parent did render. */
1244
1395
  _parentDidRender: function () {
1245
- // Route first.
1396
+ // Update states after *will* and before *did* notifications!
1246
1397
  this._gotoUnattachedByParentState();
1247
1398
 
1248
- // Notify rendered.
1249
1399
  this._rendered();
1250
1400
  },
1251
1401
 
@@ -1261,25 +1411,28 @@ SC.CoreView.reopen(
1261
1411
  case SC.CoreView.ATTACHED_BUILDING_OUT:
1262
1412
  case SC.CoreView.ATTACHED_BUILDING_OUT_BY_PARENT:
1263
1413
  // There's no need to continue to further child views.
1264
- return false;
1414
+ // return false;
1265
1415
  case SC.CoreView.ATTACHED_HIDDEN:
1266
1416
  case SC.CoreView.ATTACHED_HIDDEN_BY_PARENT:
1267
1417
  case SC.CoreView.ATTACHED_HIDING:
1268
- // Notify.
1269
- this._notifyDetaching();
1418
+ // Notify *will* (top-down from parent to children).
1419
+ // this._notifyWillDetach();
1270
1420
 
1271
1421
  return false;
1272
1422
  case SC.CoreView.ATTACHED_SHOWING:
1273
1423
  case SC.CoreView.ATTACHED_BUILDING_IN:
1274
1424
  case SC.CoreView.ATTACHED_SHOWN:
1275
- // Notify.
1276
- this._notifyDetaching();
1425
+ // Notify *will* (top-down from parent to children).
1426
+ // this._notifyWillDetach();
1277
1427
 
1278
1428
  if (transitionOut) {
1279
1429
  this._owningView = owningView;
1280
- this._transitionOut(owningView);
1281
1430
 
1282
- // Route.
1431
+ // this.invokeNext(function () {
1432
+ this._transitionOut(false, owningView);
1433
+ // });
1434
+
1435
+ // Update states after *will* and before *did* notifications!
1283
1436
  this._gotoAttachedBuildingOutByParentState();
1284
1437
  }
1285
1438
  return true;
@@ -1297,12 +1450,19 @@ SC.CoreView.reopen(
1297
1450
  case SC.CoreView.UNATTACHED_BY_PARENT:
1298
1451
  // There's no need to continue to further child views.
1299
1452
  return false;
1300
- case SC.CoreView.ATTACHED_BUILDING_IN:
1453
+ // Cancel any outstanding isVisible transitions and mark for visibility update.
1301
1454
  case SC.CoreView.ATTACHED_SHOWING:
1302
1455
  case SC.CoreView.ATTACHED_HIDING:
1456
+ this._cancelTransition();
1457
+ this._teardownTransition();
1458
+ this._visibleStyleNeedsUpdate = true;
1459
+ break;
1460
+ // Cancel any other outstanding transitions.
1461
+ case SC.CoreView.ATTACHED_BUILDING_IN:
1303
1462
  case SC.CoreView.ATTACHED_BUILDING_OUT:
1304
1463
  case SC.CoreView.ATTACHED_BUILDING_OUT_BY_PARENT:
1305
1464
  this._cancelTransition();
1465
+ this._teardownTransition();
1306
1466
  break;
1307
1467
  case SC.CoreView.ATTACHED_HIDDEN:
1308
1468
  case SC.CoreView.ATTACHED_HIDDEN_BY_PARENT:
@@ -1311,6 +1471,9 @@ SC.CoreView.reopen(
1311
1471
  default:
1312
1472
  // Attached and not in a transitionary state.
1313
1473
  }
1474
+
1475
+ // Notify *will*.
1476
+ this._notifyWillDetach();
1314
1477
  },
1315
1478
 
1316
1479
  /** @private Routes according to parent did detach. */
@@ -1318,7 +1481,7 @@ SC.CoreView.reopen(
1318
1481
  var state = this.get('viewState');
1319
1482
 
1320
1483
  if (state & SC.CoreView.IS_ATTACHED) {
1321
- this._notifyDetached();
1484
+ // Update states after *will* and before *did* notifications!
1322
1485
  this._gotoUnattachedByParentState();
1323
1486
  } else {
1324
1487
  // There's no need to continue to further child views.
@@ -1348,11 +1511,11 @@ SC.CoreView.reopen(
1348
1511
  default:
1349
1512
  }
1350
1513
 
1351
- // Notify.
1352
- if (this.didHideInDocument) { this.didHideInDocument(); }
1353
-
1354
- // Route.
1514
+ // Update states after *will* and before *did* notifications!
1355
1515
  this._gotoAttachedHiddenByParentState();
1516
+
1517
+ // Notify *did* (bottom-up from children to parent).
1518
+ if (this.didHideInDocument) { this.didHideInDocument(); }
1356
1519
  },
1357
1520
 
1358
1521
  /** @private Routes according to parent will hide. */
@@ -1369,15 +1532,17 @@ SC.CoreView.reopen(
1369
1532
  return false;
1370
1533
  case SC.CoreView.ATTACHED_HIDING: // FAST PATH!
1371
1534
  // Clear out any child views that are transitioning before we hide.
1372
- this._callOnChildViews('_parentWillHideInDocument');
1535
+ // Notify *will* (top-down from parent to children).
1536
+ // this._callOnChildViews('_parentWillHideInDocument');
1537
+
1538
+ // // Update states after *will* and before *did* notifications!
1539
+ // this._gotoAttachedHiddenState();
1373
1540
 
1541
+ // Cancel our hiding transition.
1374
1542
  this._cancelTransition();
1375
1543
 
1376
1544
  // We didn't quite hide in time so indicate that visibility needs update next time we display.
1377
- this._visibleStyleNeedsUpdate = true;
1378
-
1379
- // Route.
1380
- this._gotoAttachedHiddenState();
1545
+ // this._visibleStyleNeedsUpdate = true;
1381
1546
 
1382
1547
  return false;
1383
1548
  case SC.CoreView.ATTACHED_BUILDING_IN: // FAST PATH!
@@ -1394,7 +1559,7 @@ SC.CoreView.reopen(
1394
1559
  // Attached and not in a transitionary state.
1395
1560
  }
1396
1561
 
1397
- // Notify.
1562
+ // Notify *will* (top-down from parent to children).
1398
1563
  if (this.willHideInDocument) { this.willHideInDocument(); }
1399
1564
  },
1400
1565
 
@@ -1403,10 +1568,10 @@ SC.CoreView.reopen(
1403
1568
  var state = this.get('viewState');
1404
1569
 
1405
1570
  if (state === SC.CoreView.ATTACHED_HIDDEN_BY_PARENT) {
1406
- // Route.
1571
+ // Update states after *will* and before *did* notifications!
1407
1572
  this._gotoAttachedShownState();
1408
1573
 
1409
- // Notify.
1574
+ // Notify *did* (bottom-up from children to parent).
1410
1575
  if (this.didShowInDocument) { this.didShowInDocument(); }
1411
1576
  } else {
1412
1577
  // There's no need to continue to further child views.
@@ -1421,7 +1586,7 @@ SC.CoreView.reopen(
1421
1586
  if (state === SC.CoreView.ATTACHED_HIDDEN_BY_PARENT) {
1422
1587
  this._executeQueuedUpdates();
1423
1588
 
1424
- // Notify.
1589
+ // Notify *will* (top-dow`n from parent to children).
1425
1590
  if (this.willShowInDocument) { this.willShowInDocument(); }
1426
1591
  } else {
1427
1592
  // There's no need to continue to further child views.
@@ -1442,8 +1607,8 @@ SC.CoreView.reopen(
1442
1607
  this.set('layout', this._preTransitionLayout);
1443
1608
 
1444
1609
  // Clean up.
1445
- delete this._preTransitionLayout;
1446
- delete this._preTransitionFrame;
1610
+ this._preTransitionLayout = null;
1611
+ this._preTransitionFrame = null;
1447
1612
  },
1448
1613
 
1449
1614
  /** @private Attempts to run a transition hide, ensuring any incoming transitions are stopped in place. */
@@ -1499,20 +1664,11 @@ SC.CoreView.reopen(
1499
1664
  },
1500
1665
 
1501
1666
  /** @private Attempts to run a transition out, ensuring any incoming transitions are stopped in place. */
1502
- _transitionOut: function (owningView) {
1503
- var state = this.get('viewState'),
1504
- transitionOut = this.get('transitionOut'),
1505
- options = this.get('transitionOutOptions') || {},
1506
- inPlace = false;
1667
+ _transitionOut: function (inPlace, owningView) {
1668
+ var transitionOut = this.get('transitionOut'),
1669
+ options = this.get('transitionOutOptions') || {};
1507
1670
 
1508
- switch (state) {
1509
- case SC.CoreView.ATTACHED_SHOWING:
1510
- case SC.CoreView.ATTACHED_HIDING:
1511
- case SC.CoreView.ATTACHED_BUILDING_IN:
1512
- this.cancelAnimation(SC.LayoutState.CURRENT);
1513
- inPlace = true;
1514
- break;
1515
- default:
1671
+ if (!inPlace) {
1516
1672
  this._setupTransition();
1517
1673
  }
1518
1674
 
@@ -1557,13 +1713,15 @@ SC.CoreView.reopen(
1557
1713
  // Views without a parent are not limited by a parent's current state.
1558
1714
  isParentShown = parentView ? parentView.get('viewState') & SC.CoreView.IS_SHOWN : true;
1559
1715
 
1560
- // Route.
1716
+ // Update states after *will* and before *did* notifications!
1561
1717
  if (this.get('isVisible')) {
1562
1718
  if (isParentShown) {
1563
1719
  // Route.
1564
1720
  var transitionIn = this.get('transitionIn');
1565
1721
  if (transitionIn) {
1566
- this._transitionIn();
1722
+ // this.invokeNext(function () {
1723
+ this._transitionIn();
1724
+ // });
1567
1725
 
1568
1726
  this._gotoAttachedBuildingInState();
1569
1727
  } else {