sproutcore 1.10.0.rc.2 → 1.10.0.rc.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +8 -8
  2. data/VERSION.yml +1 -1
  3. data/lib/frameworks/sproutcore/CHANGELOG.md +14 -0
  4. data/lib/frameworks/sproutcore/frameworks/core_foundation/controllers/array.js +9 -1
  5. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/pane_statechart.js +7 -0
  6. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/controllers/array/array_case.js +14 -0
  7. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layout.js +103 -0
  8. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutChildViews.js +4 -4
  9. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutDidChange.js +4 -1
  10. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/viewDidResize.js +5 -5
  11. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout.js +17 -6
  12. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/statechart.js +62 -8
  13. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view.js +14 -2
  14. data/lib/frameworks/sproutcore/frameworks/datastore/system/store.js +26 -5
  15. data/lib/frameworks/sproutcore/frameworks/datastore/tests/integration/many_array.js +9 -1
  16. data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/nested_records/data_store.js +6 -2
  17. data/lib/frameworks/sproutcore/frameworks/desktop/mixins/split_child.js +1 -1
  18. data/lib/frameworks/sproutcore/frameworks/desktop/panes/picker.js +0 -2
  19. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/list/render.js +56 -54
  20. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/scroll/methods.js +221 -171
  21. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/split/methods.js +261 -315
  22. data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/split/split_child.js +137 -122
  23. data/lib/frameworks/sproutcore/frameworks/desktop/views/collection.js +1 -1
  24. data/lib/frameworks/sproutcore/frameworks/desktop/views/scroll.js +10 -7
  25. data/lib/frameworks/sproutcore/frameworks/desktop/views/split.js +5 -4
  26. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/content_display.js +14 -14
  27. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/content_value_support.js +123 -98
  28. data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/content_display.js +18 -6
  29. data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/inline_text_field/api.js +9 -11
  30. data/lib/frameworks/sproutcore/frameworks/foundation/tests/views/container/transition_test.js +2 -2
  31. data/lib/frameworks/sproutcore/frameworks/foundation/views/container.js +15 -16
  32. data/lib/frameworks/sproutcore/frameworks/foundation/views/inline_text_field.js +11 -0
  33. data/lib/frameworks/sproutcore/frameworks/runtime/mixins/enumerable.js +1 -1
  34. data/lib/frameworks/sproutcore/frameworks/runtime/system/binding.js +3 -3
  35. data/lib/frameworks/sproutcore/frameworks/runtime/tests/system/binding.js +170 -153
  36. data/lib/frameworks/sproutcore/frameworks/table/views/table.js +105 -101
  37. data/lib/frameworks/sproutcore/frameworks/table/views/table_head.js +0 -7
  38. data/lib/frameworks/sproutcore/frameworks/table/views/table_header.js +46 -56
  39. data/lib/frameworks/sproutcore/frameworks/table/views/table_row.js +0 -6
  40. data/lib/frameworks/sproutcore/frameworks/template_view/tests/views/template/collection.js +12 -4
  41. data/lib/frameworks/sproutcore/frameworks/template_view/views/bindable_span.js +3 -2
  42. data/lib/frameworks/sproutcore/frameworks/template_view/views/template_collection.js +11 -8
  43. data/lib/frameworks/sproutcore/tests/phantomjs_runner.phantomjs +0 -1
  44. metadata +3 -3
  45. data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/inline_text_field/beginEditing.js +0 -235
@@ -33,21 +33,30 @@ SC.ContentValueSupport = {
33
33
  hasContentValueSupport: YES,
34
34
 
35
35
  /** @private */
36
- initMixin: function() {
36
+ initMixin: function () {
37
37
  // setup content observing if needed.
38
38
  this._control_contentKeysDidChange();
39
39
  },
40
-
40
+
41
+ /** @private */
42
+ destroyMixin: function () {
43
+ // Remove old observers on self.
44
+ this._cleanup_old_observers();
45
+
46
+ // Remove old observers on content.
47
+ this._cleanup_old_content_observers();
48
+ },
49
+
41
50
  /**
42
51
  The value represented by this control.
43
-
52
+
44
53
  Most controls represent a value of some type, such as a number, string
45
54
  or image URL. This property should hold that value. It is bindable
46
55
  and observable. Changing this value will immediately change the
47
- appearance of the control. Likewise, editing the control
56
+ appearance of the control. Likewise, editing the control
48
57
  will immediately change this value.
49
-
50
- If instead of setting a single value on a control, you would like to
58
+
59
+ If instead of setting a single value on a control, you would like to
51
60
  set a content object and have the control display a single property
52
61
  of that control, then you should use the content property instead.
53
62
 
@@ -55,23 +64,23 @@ SC.ContentValueSupport = {
55
64
  @default null
56
65
  */
57
66
  value: null,
58
-
67
+
59
68
  /**
60
69
  The content object represented by this control.
61
-
62
- Often you need to use a control to display some single aspect of an
70
+
71
+ Often you need to use a control to display some single aspect of an
63
72
  object, especially if you are using the control as an item view in a
64
73
  collection view.
65
-
74
+
66
75
  In those cases, you can set the content and contentValueKey for the
67
76
  control. This will cause the control to observe the content object for
68
- changes to the value property and then set the value of that property
77
+ changes to the value property and then set the value of that property
69
78
  on the "value" property of this object.
70
-
71
- Note that unless you are using this control as part of a form or
79
+
80
+ Note that unless you are using this control as part of a form or
72
81
  collection view, then it would be better to instead bind the value of
73
82
  the control directly to a controller property.
74
-
83
+
75
84
  @type SC.Object
76
85
  @default null
77
86
  */
@@ -92,42 +101,42 @@ SC.ContentValueSupport = {
92
101
  _default_contentKeys: {
93
102
  contentValueKey: 'value'
94
103
  },
95
-
104
+
96
105
  /**
97
- The property on the content object that would want to represent the
106
+ The property on the content object that would want to represent the
98
107
  value of this control. This property should only be set before the
99
108
  content object is first set. If you have a displayDelegate, then
100
109
  you can also use the contentValueKey of the displayDelegate.
101
-
110
+
102
111
  @type String
103
112
  @default null
104
113
  */
105
114
  contentValueKey: null,
106
-
115
+
107
116
  /**
108
- Invoked whenever any property on the content object changes.
109
-
117
+ Invoked whenever any property on the content object changes.
118
+
110
119
  The default implementation will update the value property of the view
111
120
  if the contentValueKey property has changed. You can override this
112
121
  method to implement whatever additional changes you would like.
113
-
114
- The key will typically contain the name of the property that changed or
122
+
123
+ The key will typically contain the name of the property that changed or
115
124
  '*' if the content object itself has changed. You should generally do
116
125
  a total reset if '*' is changed.
117
-
126
+
118
127
  @param {Object} target the content object
119
128
  @param {String} key the property that changes
120
129
  @returns {void}
121
130
  @test in content
122
131
  */
123
- contentPropertyDidChange: function(target, key) {
132
+ contentPropertyDidChange: function (target, key) {
124
133
  var contentKeys = this.get('contentKeys');
125
134
 
126
- if(contentKeys) {
135
+ if (contentKeys) {
127
136
  var contentKey;
128
137
 
129
- for(contentKey in contentKeys) {
130
- if(key === '*' || key === this.getDelegateProperty(contentKey, this, this.get('displayDelegate'), contentKeys)) return this.updatePropertyFromContent(contentKeys[contentKey], key, contentKey, target);
138
+ for (contentKey in contentKeys) {
139
+ if (key === '*' || key === this.getDelegateProperty(contentKey, this, this.get('displayDelegate'), contentKeys)) return this.updatePropertyFromContent(contentKeys[contentKey], key, contentKey, target);
131
140
  }
132
141
  }
133
142
 
@@ -137,65 +146,65 @@ SC.ContentValueSupport = {
137
146
  },
138
147
 
139
148
  /**
140
- Helper method you can use from your own implementation of
149
+ Helper method you can use from your own implementation of
141
150
  contentPropertyDidChange(). This method will look up the content key to
142
151
  extract a property and then update the property if needed. If you do
143
- not pass the content key or the content object, they will be computed
152
+ not pass the content key or the content object, they will be computed
144
153
  for you. It is more efficient, however, for you to compute these values
145
154
  yourself if you expect this method to be called frequently.
146
-
155
+
147
156
  @param {String} prop local property to update
148
157
  @param {String} key the contentproperty that changed
149
158
  @param {String} contentKey the local property that contains the key
150
159
  @param {Object} content
151
160
  @returns {SC.Control} receiver
152
161
  */
153
- updatePropertyFromContent: function(prop, key, contentKey, content) {
162
+ updatePropertyFromContent: function (prop, key, contentKey, content) {
154
163
  var del, v;
155
164
 
156
- if (contentKey === undefined) contentKey = "content"+prop.capitalize()+"Key";
157
-
165
+ if (contentKey === undefined) contentKey = "content" + prop.capitalize() + "Key";
166
+
158
167
  // prefer our own definition of contentKey
159
- if(this[contentKey]) contentKey = this.get(contentKey);
168
+ if (this[contentKey]) contentKey = this.get(contentKey);
160
169
  // if we don't have one defined check the delegate
161
- else if((del = this.get('displayDelegate')) && (v = del[contentKey])) contentKey = del.get ? del.get(contentKey) : v;
170
+ else if ((del = this.get('displayDelegate')) && (v = del[contentKey])) contentKey = del.get ? del.get(contentKey) : v;
162
171
  // if we have no key we can't do anything so just short circuit out
163
172
  else return this;
164
173
 
165
174
  // only bother setting value if the observer triggered for the correct key
166
175
  if (key === '*' || key === contentKey) {
167
176
  if (content === undefined) content = this.get('content');
168
-
169
- if(content) v = content.get ? content.get(contentKey) : content[contentKey];
177
+
178
+ if (content) v = content.get ? content.get(contentKey) : content[contentKey];
170
179
  else v = null;
171
180
 
172
- this.setIfChanged(prop, v) ;
181
+ this.setIfChanged(prop, v);
173
182
  }
174
-
175
- return this ;
183
+
184
+ return this;
176
185
  },
177
-
186
+
178
187
  /**
179
188
  Relays changes to the value back to the content object if you are using
180
189
  a content object.
181
-
190
+
182
191
  This observer is triggered whenever the value changes. It will only do
183
192
  something if it finds you are using the content property and
184
193
  contentValueKey and the new value does not match the old value of the
185
- content object.
186
-
194
+ content object.
195
+
187
196
  If you are using contentValueKey in some other way than typically
188
197
  implemented by this mixin, then you may want to override this method as
189
198
  well.
190
-
199
+
191
200
  @returns {void}
192
201
  */
193
- updateContentWithValueObserver: function(target, key) {
202
+ updateContentWithValueObserver: function (target, key) {
194
203
  var reverseContentKeys = this._reverseContentKeys;
195
204
 
196
205
  // if everything changed, iterate through and update them all
197
- if(!key || key === '*') {
198
- for(key in reverseContentKeys) {
206
+ if (!key || key === '*') {
207
+ for (key in reverseContentKeys) {
199
208
  this.updateContentWithValueObserver(this, key);
200
209
  }
201
210
  }
@@ -217,7 +226,7 @@ SC.ContentValueSupport = {
217
226
 
218
227
  // avoid re-writing inherited props
219
228
  else if (content[contentKey] !== value) {
220
- content[contentKey] = value ;
229
+ content[contentKey] = value;
221
230
  }
222
231
  },
223
232
 
@@ -230,56 +239,34 @@ SC.ContentValueSupport = {
230
239
  _old_contentKeys: null,
231
240
 
232
241
  /** @private
233
- Observes when a content object has changed and handles notifying
242
+ Observes when a content object has changed and handles notifying
234
243
  changes to the value of the content object.
235
244
 
236
245
  Optimized for the default case of only observing contentValueKey. If you use
237
246
  a custom value for contentKeys it will switch to using a CoreSet to track
238
247
  observed keys.
239
248
  */
240
- _control_contentDidChange: function(target, key) {
249
+ _control_contentDidChange: function (target, key) {
241
250
  var content = this.get('content'),
242
251
  contentKeys = this.get('contentKeys'), contentKey,
243
- old = this._control_content,
244
252
  oldKeys = this._old_contentValueKeys,
245
- oldType = SC.typeOf(oldKeys),
246
253
  f = this.contentPropertyDidChange;
247
254
 
248
255
  // remove an observer from the old content if necessary
249
- if (old && old.removeObserver && oldKeys) {
250
- // default case
251
- if(oldType === SC.T_STRING) {
252
- old.removeObserver(oldKeys, this, f);
253
-
254
- oldKeys = null;
255
- }
256
-
257
- // set case
258
- else {
259
- var i, len = oldKeys.get('length');
260
-
261
- for(i = 0; i < len; i++) {
262
- contentKey = oldKeys[i];
263
-
264
- old.removeObserver(contentKey, this, f);
265
- }
266
-
267
- oldKeys.clear();
268
- }
269
- }
256
+ this._cleanup_old_content_observers();
270
257
 
271
258
  // add observer to new content if necessary.
272
259
  if (content && content.addObserver) {
273
260
  // set case
274
- if(contentKeys) {
261
+ if (contentKeys) {
275
262
  // lazily create the key set
276
- if(!oldKeys) oldKeys = SC.CoreSet.create();
263
+ if (!oldKeys) oldKeys = SC.CoreSet.create();
277
264
 
278
265
  // add observers to each key
279
- for(contentKey in contentKeys) {
266
+ for (contentKey in contentKeys) {
280
267
  contentKey = this.getDelegateProperty(contentKey, this, this.get('displayDelegate'));
281
268
 
282
- if(contentKey) {
269
+ if (contentKey) {
283
270
  content.addObserver(contentKey, this, f);
284
271
 
285
272
  oldKeys.add(contentKey);
@@ -291,11 +278,11 @@ SC.ContentValueSupport = {
291
278
  else {
292
279
  contentKey = this.getDelegateProperty('contentValueKey', this, this.get('displayDelegate'));
293
280
 
294
- if(contentKey) {
281
+ if (contentKey) {
295
282
  content.addObserver(contentKey, this, f);
296
283
 
297
284
  // if we had a set before, continue using it
298
- if(oldKeys) oldKeys.add(contentKey);
285
+ if (oldKeys) oldKeys.add(contentKey);
299
286
  // otherwise just use a string
300
287
  else oldKeys = contentKey;
301
288
  }
@@ -303,40 +290,31 @@ SC.ContentValueSupport = {
303
290
  }
304
291
 
305
292
  // update previous values
306
- this._control_content = content ;
293
+ this._control_content = content;
307
294
  this._old_contentValueKeys = oldKeys;
308
295
 
309
296
  // notify that value did change.
310
297
  key = (!key || key === 'content') ? '*' : this.get(key);
311
- if(key) this.contentPropertyDidChange(content, key) ;
298
+ if (key) this.contentPropertyDidChange(content, key);
312
299
  }.observes('content'),
313
300
 
314
- // holds the previous value of contentKeys
315
- _old_contentKeys: null,
316
-
317
301
  /** @private
318
302
  Observes changes to contentKeys and sets up observers on the local keys to
319
303
  update the observers on the content object.
320
304
  */
321
- _control_contentKeysDidChange: function() {
305
+ _control_contentKeysDidChange: function () {
322
306
  var key, reverse = {},
323
307
  // if no hash is present, use the default contentValueKey -> value
324
- contentKeys = this.get('contentKeys') || this._default_contentKeys, contentKey,
325
- oldContentKeys = this._old_contentKeys,
308
+ contentKeys = this.get('contentKeys') || this._default_contentKeys,
309
+ contentKey,
326
310
  f = this._control_contentDidChange,
327
311
  reverseF = this.updateContentWithValueObserver;
328
312
 
329
- // remove old observers
330
- for(key in oldContentKeys) {
331
- contentKey = oldContentKeys[key];
332
-
333
- this.removeObserver(contentKey, this, reverseF);
334
-
335
- this.removeObserver(key, this, f);
336
- }
313
+ // Remove old observers.
314
+ this._cleanup_old_observers();
337
315
 
338
316
  // add new observers
339
- for(key in contentKeys) {
317
+ for (key in contentKeys) {
340
318
  contentKey = contentKeys[key];
341
319
 
342
320
  // build reverse mapping to update content with value
@@ -356,6 +334,53 @@ SC.ContentValueSupport = {
356
334
 
357
335
  // call the other observer now to update all the observers
358
336
  this._control_contentDidChange();
359
- }.observes('contentKeys')
337
+ }.observes('contentKeys'),
338
+
339
+ /** @private */
340
+ _cleanup_old_content_observers: function () {
341
+ var old = this._control_content,
342
+ oldKeys = this._old_contentValueKeys,
343
+ oldType = SC.typeOf(oldKeys),
344
+ f = this.contentPropertyDidChange,
345
+ contentKey;
346
+
347
+ if (old && old.removeObserver && oldKeys) {
348
+ // default case
349
+ if (oldType === SC.T_STRING) {
350
+ old.removeObserver(oldKeys, this, f);
351
+
352
+ oldKeys = null;
353
+ }
354
+
355
+ // set case
356
+ else {
357
+ var i, len = oldKeys.get('length');
358
+
359
+ for (i = 0; i < len; i++) {
360
+ contentKey = oldKeys[i];
361
+
362
+ old.removeObserver(contentKey, this, f);
363
+ }
364
+
365
+ oldKeys.clear();
366
+ }
367
+ }
368
+ },
369
+
370
+ /** @private */
371
+ _cleanup_old_observers: function () {
372
+ var oldContentKeys = this._old_contentKeys,
373
+ f = this._control_contentDidChange,
374
+ reverseF = this.updateContentWithValueObserver,
375
+ contentKey, key;
376
+
377
+ // remove old observers
378
+ for (key in oldContentKeys) {
379
+ contentKey = oldContentKeys[key];
380
+
381
+ this.removeObserver(contentKey, this, reverseF);
382
+ this.removeObserver(key, this, f);
383
+ }
384
+ }
360
385
  };
361
386
 
@@ -4,10 +4,10 @@
4
4
  // ©2008-2011 Apple Inc. All rights reserved.
5
5
  // License: Licensed under MIT license (see license.js)
6
6
  // ==========================================================================
7
- var view, contentA, contentB;
7
+ var view, pane, contentA, contentB;
8
8
 
9
9
  module('ContentDisplay', {
10
- setup: function() {
10
+ setup: function () {
11
11
  contentA = SC.Object.create({
12
12
  foo: 'foo.A',
13
13
  bar: 'bar.A'
@@ -18,32 +18,43 @@ module('ContentDisplay', {
18
18
  bar: 'bar.B'
19
19
  });
20
20
 
21
+ pane = SC.Pane.create();
21
22
  view = SC.View.create(SC.ContentDisplay, {
22
23
  contentDisplayProperties: ['foo', 'bar'],
23
24
  content: contentA
24
25
  });
26
+ pane.appendChild(view);
27
+ pane.append();
28
+ },
25
29
 
26
- view.set('layerNeedsUpdate', NO);
30
+ teardown: function () {
31
+ pane.destroy();
32
+ contentA.destroy();
33
+ contentB.destroy();
34
+ pane = view = contentA = contentB = null;
27
35
  }
28
36
  });
29
37
 
30
38
  test('should dirty layer when content changes', function () {
31
39
  SC.run(function () {
32
40
  view.set('content', contentB);
41
+
42
+ ok(view.get('layerNeedsUpdate'), "The view's layerNeedsUpdate should be true.");
33
43
  });
34
- ok(view.get('layerNeedsUpdate'));
35
44
  });
36
45
 
37
46
  test('should dirty layer when any of contentDisplayProperties change', function () {
38
47
  SC.run(function () {
39
48
  contentA.set('foo', 'newFoo');
49
+
50
+ ok(view.get('layerNeedsUpdate'), "The view's layerNeedsUpdate should be true.");
40
51
  });
41
- ok(view.get('layerNeedsUpdate'));
42
52
  });
43
53
 
44
54
  test('should stop observing old content when content changes', function () {
45
55
  ok(contentA.hasObserverFor('*'));
46
56
  view.set('content', contentB);
57
+
47
58
  ok(!contentA.hasObserverFor('*'));
48
59
  });
49
60
 
@@ -52,8 +63,9 @@ test('should begin observing new content when content changes', function () {
52
63
  view.set('layerNeedsUpdate', NO);
53
64
  SC.run(function () {
54
65
  contentB.set('bar', 'newBar');
66
+
67
+ ok(view.get('layerNeedsUpdate'), "The view's layerNeedsUpdate should be true.");
55
68
  });
56
- ok(view.get('layerNeedsUpdate'));
57
69
  });
58
70
 
59
71
  test('should stop observing content when destroyed', function () {
@@ -7,18 +7,19 @@
7
7
 
8
8
  /*global module test htmlbody ok equals same stop start Q$ */
9
9
 
10
- var field;
10
+ var field, view;
11
11
 
12
12
  /**
13
13
  Track the public functions and properties of the class. This will serve as an early warning
14
14
  when functions that people may depend on disappear between versions to ensure that we don't
15
15
  break promised support without proper deprecations.
16
-
16
+
17
17
  tylerkeating: This is probably redundant since each of these functions and properties should
18
18
  be individually tested elsewhere.
19
19
  */
20
20
  module("Test the public functions and properties of SC.InlineTextFieldView", {
21
21
  setup: function() {
22
+ view = SC.View.create(SC.InlineEditable, {});
22
23
  field = SC.InlineTextFieldView.create({});
23
24
  },
24
25
 
@@ -27,15 +28,6 @@ module("Test the public functions and properties of SC.InlineTextFieldView", {
27
28
  }
28
29
  });
29
30
 
30
-
31
- test("contains all public class functions",
32
- function() {
33
- ok(SC.typeOf(SC.InlineTextFieldView['beginEditing']) === SC.T_FUNCTION, "should respond to beginEditing()");
34
- ok(SC.typeOf(SC.InlineTextFieldView['commitEditing']) === SC.T_FUNCTION, "should respond to commitEditing()");
35
- ok(SC.typeOf(SC.InlineTextFieldView['discardEditing']) === SC.T_FUNCTION, "should respond to discardEditing()");
36
- });
37
-
38
-
39
31
  test("contains all public functions",
40
32
  function() {
41
33
  ok(field.respondsTo('beginEditing'), "should respond to beginEditing()");
@@ -45,6 +37,12 @@ function() {
45
37
  ok(field.respondsTo('cancel'), "should respond to cancel()");
46
38
  });
47
39
 
40
+ test("a view with SC.InlineEditable mixin contains all public functions",
41
+ function() {
42
+ ok(view.respondsTo('beginEditing'), "should respond to beginEditing()");
43
+ ok(view.respondsTo('commitEditing'), "should respond to commitEditing()");
44
+ ok(view.respondsTo('discardEditing'), "should respond to discardEditing()");
45
+ });
48
46
 
49
47
  test("contains all public properties",
50
48
  function() {
@@ -62,7 +62,7 @@ test("Test that the isTransitioning property of container view updates according
62
62
  window.stop(2000);
63
63
 
64
64
  SC.run(function () {
65
- containerView.set('transition', SC.ContainerView.PUSH);
65
+ containerView.set('transitionSwap', SC.ContainerView.PUSH);
66
66
  containerView.set('nowShowing', view2);
67
67
  });
68
68
 
@@ -112,7 +112,7 @@ test("Test that the container view calls the proper transition plugin methods.",
112
112
  didBuildOutFromView: function () { didBuildOutFromViewCalled++; }
113
113
  };
114
114
 
115
- containerView.set('transition', plugin);
115
+ containerView.set('transitionSwap', plugin);
116
116
  containerView.set('nowShowing', view2);
117
117
  equals(willBuildInToViewCalled, 1, "willBuildInToViewCalled() should have been called this many times");
118
118
  equals(willBuildOutFromViewCalled, 1, "willBuildOutFromViewCalled() should have been called this many times");
@@ -169,15 +169,25 @@ SC.ContainerView = SC.View.extend(
169
169
  // Methods
170
170
  //
171
171
 
172
- /** @private
173
- When a container view awakes, it will try to find the nowShowing, if
174
- there is one, and set it as content if necessary.
175
- */
176
- awake: function () {
172
+ /** @private */
173
+ init: function () {
174
+ var view;
175
+
177
176
  sc_super();
178
177
 
179
178
  if (this.get('nowShowing')) {
179
+ // If nowShowing is directly set, invoke the instantiation of
180
+ // it as well.
180
181
  this.nowShowingDidChange();
182
+ } else {
183
+ // If contentView is directly set, then swap it into nowShowing so that it
184
+ // is properly instantiated and ready for swapping.
185
+ // Fixes: https://github.com/sproutcore/sproutcore/issues/1069
186
+ view = this.get('contentView');
187
+
188
+ if (view) {
189
+ this.set('nowShowing', view);
190
+ }
181
191
  }
182
192
  },
183
193
 
@@ -208,17 +218,6 @@ SC.ContainerView = SC.View.extend(
208
218
  return ret;
209
219
  }.property('parentView', 'frame').cacheable(),
210
220
 
211
- /** @private */
212
- createChildViews: function () {
213
- // if contentView is defined, then create the content
214
- var view = this.get('contentView');
215
-
216
- if (view) {
217
- view = this.contentView = this.createChildView(view);
218
- this.childViews = [view];
219
- }
220
- },
221
-
222
221
  /** @private
223
222
  Invoked whenever the content property changes. This method will simply
224
223
  call replaceContent. Override replaceContent to change how the view is
@@ -96,6 +96,17 @@ SC.InlineTextFieldView = SC.TextFieldView.extend(SC.InlineEditor,
96
96
  */
97
97
  _topOffsetForFirefoxCursorFix: 0,
98
98
 
99
+ /**
100
+ The default size of the inline text field is 0 x 0 so that when it is
101
+ appended, but before it is positioned it doesn't fill the parent view
102
+ entirely.
103
+
104
+ This is important, because if the parent view layer allows overflow,
105
+ we could inadvertently alter the scrollTop or scrollLeft properties
106
+ of the layer.
107
+ */
108
+ layout: { height: 0, width: 0 },
109
+
99
110
  /*
100
111
  * @private
101
112
  * @method
@@ -838,7 +838,7 @@ SC.Reducers = /** @scope SC.Reducers.prototype */ {
838
838
  // or lastObject properties changed, thus making them independently observable.
839
839
  if (!SC.none(start)) {
840
840
  if (start === 0) this.notifyPropertyChange('firstObject');
841
- if (!SC.none(length) && start + length === this.get('length') - 1) this.notifyPropertyChange('lastObject');
841
+ if (!SC.none(length) && start + length >= this.get('length') - 1) this.notifyPropertyChange('lastObject');
842
842
  }
843
843
 
844
844
  this.notifyPropertyChange('[]');
@@ -598,7 +598,7 @@ SC.Binding = /** @scope SC.Binding.prototype */{
598
598
  while ((queue = this._connectQueue).length > 0) {
599
599
  this._connectQueue = this._alternateConnectQueue;
600
600
  this._alternateConnectQueue = queue;
601
- while (binding = queue.pop()) binding._connect();
601
+ while ((binding = queue.pop())) { binding._connect(); }
602
602
  }
603
603
 
604
604
  // loop through the changed queue...
@@ -617,7 +617,7 @@ SC.Binding = /** @scope SC.Binding.prototype */{
617
617
  // next, apply any bindings in the current queue. This may cause
618
618
  // additional bindings to trigger, which will end up in the new active
619
619
  // queue.
620
- while (binding = queue.pop()) binding.applyBindingValue();
620
+ while ((binding = queue.pop())) { binding.applyBindingValue(); }
621
621
 
622
622
  // now loop back and see if there are additional changes pending in the
623
623
  // active queue. Repeat this until all bindings that need to trigger
@@ -821,7 +821,7 @@ SC.Binding = /** @scope SC.Binding.prototype */{
821
821
  var t = binding._transforms;
822
822
 
823
823
  // clone the transform array if this comes from the parent
824
- if (t && (t === binding.parentBinding._transform)) {
824
+ if (t && (t === binding.parentBinding._transforms)) {
825
825
  t = binding._transforms = t.slice();
826
826
  }
827
827