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.
- checksums.yaml +8 -8
- data/VERSION.yml +1 -1
- data/lib/frameworks/sproutcore/CHANGELOG.md +14 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/controllers/array.js +9 -1
- data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/pane_statechart.js +7 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/controllers/array/array_case.js +14 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layout.js +103 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutChildViews.js +4 -4
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutDidChange.js +4 -1
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/viewDidResize.js +5 -5
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout.js +17 -6
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/statechart.js +62 -8
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view.js +14 -2
- data/lib/frameworks/sproutcore/frameworks/datastore/system/store.js +26 -5
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/integration/many_array.js +9 -1
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/nested_records/data_store.js +6 -2
- data/lib/frameworks/sproutcore/frameworks/desktop/mixins/split_child.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/desktop/panes/picker.js +0 -2
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/list/render.js +56 -54
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/scroll/methods.js +221 -171
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/split/methods.js +261 -315
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/split/split_child.js +137 -122
- data/lib/frameworks/sproutcore/frameworks/desktop/views/collection.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/desktop/views/scroll.js +10 -7
- data/lib/frameworks/sproutcore/frameworks/desktop/views/split.js +5 -4
- data/lib/frameworks/sproutcore/frameworks/foundation/mixins/content_display.js +14 -14
- data/lib/frameworks/sproutcore/frameworks/foundation/mixins/content_value_support.js +123 -98
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/content_display.js +18 -6
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/inline_text_field/api.js +9 -11
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/views/container/transition_test.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/foundation/views/container.js +15 -16
- data/lib/frameworks/sproutcore/frameworks/foundation/views/inline_text_field.js +11 -0
- data/lib/frameworks/sproutcore/frameworks/runtime/mixins/enumerable.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/runtime/system/binding.js +3 -3
- data/lib/frameworks/sproutcore/frameworks/runtime/tests/system/binding.js +170 -153
- data/lib/frameworks/sproutcore/frameworks/table/views/table.js +105 -101
- data/lib/frameworks/sproutcore/frameworks/table/views/table_head.js +0 -7
- data/lib/frameworks/sproutcore/frameworks/table/views/table_header.js +46 -56
- data/lib/frameworks/sproutcore/frameworks/table/views/table_row.js +0 -6
- data/lib/frameworks/sproutcore/frameworks/template_view/tests/views/template/collection.js +12 -4
- data/lib/frameworks/sproutcore/frameworks/template_view/views/bindable_span.js +3 -2
- data/lib/frameworks/sproutcore/frameworks/template_view/views/template_collection.js +11 -8
- data/lib/frameworks/sproutcore/tests/phantomjs_runner.phantomjs +0 -1
- metadata +3 -3
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/inline_text_field/beginEditing.js +0 -235
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ZmUxOTcxMGViYzE0OWVlYmJiMzlhNTUwMzk1M2I5ZDM1NzFiYWMzOA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
M2VkMDZmODFjODExNDE4ZDY1NzQzYzVlNTU3NzdlZmE0MTU3NmQzMw==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
OWM1OGJhNDk5OWFiNmVlOWM4YjZjMzk3OWExYzU1NjliODUxMDZmZjYxMjUz
|
10
|
+
NDE2ODZiN2M5ZGQ3NzdmYTg1YWU5NjEwY2NkMWYzYjdkNDcyM2MyZGY5ODg3
|
11
|
+
NDEwZGFmMjMyMGQzMTNkMGFiNDMyYzBhNDBlNWQwYzAxZWFiZGY=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NjYxYzdhZmYyMDI4N2FiN2UyZDJkNTlhNTBkMjJmYmM5MjI4ZmJkNDg3OTdh
|
14
|
+
ZjhhYzcwNzg0MzgzOGI4M2FjNGY4NzNhZTBiOTA2YTJkMjA0Y2YzOTMxOTE4
|
15
|
+
ZmQxMTU2ZDg0YzI3NjkyMTFjMDFkZGFkOGM0M2Q3NjU2NTMyOGQ=
|
data/VERSION.yml
CHANGED
@@ -7,6 +7,8 @@ CHANGE LOG
|
|
7
7
|
### CHANGES & FEATURES
|
8
8
|
|
9
9
|
* Improves and adds hundreds of lines of documentation.
|
10
|
+
* Removes a developer warning when animating with a duration of 0, which can be valid if the duration is calculated. In any case, animating a duration of 0 has always been supported by SC.View.prototype.animate.
|
11
|
+
* Improves the regular expression used by SC.RenderContext to escape strings so that HTML entities like ' or à are preserved.
|
10
12
|
* Set SC.DEFAULT_CURSOR to 'default' instead of 'auto'.
|
11
13
|
* Improves the ability of the SC.browser experimental name testing to succeed by adding a test value that can be used.
|
12
14
|
* Masks all debug statements from SC.Binding using @if(debug).
|
@@ -332,6 +334,18 @@ Also added better documentation for using dataSourceDidFetchQuery.
|
|
332
334
|
|
333
335
|
### BUG FIXES
|
334
336
|
|
337
|
+
* Fixes a problem which kept firstObject and lastObject referenced from an array controller from updating on replace. Also fixes a problem updating lastObject on an enumerable when replacing the last items and shrinking the collection.
|
338
|
+
* Fixes a problem when using an SC.SplitView as a split child.
|
339
|
+
* Fixes a bug that updating the parent record data hash failed to update the nested record hashes as well.
|
340
|
+
* Fixes a problem with SC.ScrollView that required an additional frame change notification to work previously.
|
341
|
+
* Fixes a problem where childViews incorrectly called viewDidResize one extra time when appended to the DOM. The views will already have run viewDidResize once on being adopted by a parentView.
|
342
|
+
* Fixes a miscalculation of isFixedPosition that resulted in incorrect values when short form layouts were used (ex. specifying { width: 10, height: 10 } only which implies top: 0 and left: 0). This would have caused such views to return false for hasAcceleratedLayer even though they had set wantsAcceleratedLayer to true.
|
343
|
+
* Prevents needless view updates when displayDidChange is called on an unrendered view. Normally, the actual update code handles the check to see if the view is rendered and can be updated, but if displayDidChange comes before a render, we would end up rendering and then updating. Now it checks to see if the view is rendered before attempting to update it at all.
|
344
|
+
* Fixes a potentially huge memory leak when views that mix in SC.ContentValueSupport (or via SC.Control) will not remove all the content value observers from the content object when the view is destroyed. One result is that every time you scrolled a list of SC.ListItemViews back and forth it was appending more and more observers to the content.
|
345
|
+
* Gives SC.InlineTextFieldView a default layout size of 0x0 so that it doesn't alter the scrollTop/scrollLeft of a parent view layer that allows overflow.
|
346
|
+
* Fixed position of picker panes when the anchor has a frame origin of 0,0.
|
347
|
+
* Fixes the initialization of SC.ContainerView when the contentView is already set.
|
348
|
+
* Fixes typo in SC.Binding.transform causing transforms to be added to parent.
|
335
349
|
* Fixes inability to specify the window padding on a PickerPane to a value other than the default.
|
336
350
|
* Fixes escaped overflowTitle of SC.SegmentedView that showed '»' and invalid text of overflowToolTip that showed 'More…'. Also removes unnecessary escaping of `title` attributes on buttons and labels, because the browser doesn't render HTML inside of a `title` and removes invalid `alt` attribute on button divs.
|
337
351
|
* Fixes SC.ArrayController so that firstObject, firstSelectableObject and lastObject update properly when swapping out the content. This also ensures that when allowsEmptySelection is false, that the selection changes to the new first object when the content is swapped.
|
@@ -428,6 +428,15 @@ SC.ArrayController = SC.Controller.extend(SC.Array, SC.SelectionSupport,
|
|
428
428
|
_scac_arrayContentDidChange: function (start, removed, added) {
|
429
429
|
this._scac_cached = NO;
|
430
430
|
this.arrayContentDidChange(start, removed, added);
|
431
|
+
|
432
|
+
// If the start & length are provided, we can also indicate if the firstObject
|
433
|
+
// or lastObject properties changed, thus making them independently observable.
|
434
|
+
if (!SC.none(start)) {
|
435
|
+
if (start === 0) this.notifyPropertyChange('firstObject');
|
436
|
+
var length = added + removed;
|
437
|
+
if (!SC.none(length) && start + length >= this.get('length') - 1) this.notifyPropertyChange('lastObject');
|
438
|
+
}
|
439
|
+
|
431
440
|
if (this._kvo_enumerable_property_chains) {
|
432
441
|
var addedObjects = this.slice(start, start + added);
|
433
442
|
this.setupEnumerablePropertyChains(addedObjects);
|
@@ -441,7 +450,6 @@ SC.ArrayController = SC.Controller.extend(SC.Array, SC.SelectionSupport,
|
|
441
450
|
*/
|
442
451
|
_scac_contentDidChange: function () {
|
443
452
|
this._scac_cached = NO; // invalidate observable content
|
444
|
-
|
445
453
|
var content = this.get('content'),
|
446
454
|
lastContent = this._scac_content,
|
447
455
|
didChange = this._scac_arrayContentDidChange,
|
@@ -28,6 +28,13 @@ SC.Pane.reopen({
|
|
28
28
|
// handle intercept if needed
|
29
29
|
this._addIntercept();
|
30
30
|
|
31
|
+
// If the layout is flexible (dependent on the window size), then the view
|
32
|
+
// will resize when appended.
|
33
|
+
if (!this.get('isFixedSize')) {
|
34
|
+
// We call viewDidResize so that it calls parentViewDidResize on all child views.
|
35
|
+
this.viewDidResize();
|
36
|
+
}
|
37
|
+
|
31
38
|
sc_super();
|
32
39
|
},
|
33
40
|
|
data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/controllers/array/array_case.js
CHANGED
@@ -183,6 +183,20 @@ test("The computed properties firstObject, firstSelectableObject & lastObject sh
|
|
183
183
|
equals(controller.get('lastObject'), newObject, 'lastObject should be the new last object in content');
|
184
184
|
});
|
185
185
|
|
186
|
+
test("The computed properties firstObject, firstSelectableObject & lastObject should update when content items change.", function(){
|
187
|
+
equals(controller.get('firstObject'), content[0], 'first object should be the first object in content');
|
188
|
+
equals(controller.get('firstSelectableObject'), content[0], 'first selectable object should be the first object in content');
|
189
|
+
equals(controller.get('lastObject'), content[4], 'lastObject should be the last object in content');
|
190
|
+
|
191
|
+
// Change the items.
|
192
|
+
var newObject = TestObject.create({ title: "BLAH" });
|
193
|
+
controller.replace(0, 5, [newObject]);
|
194
|
+
|
195
|
+
equals(controller.get('firstObject'), newObject, 'first object should be the new first object in content');
|
196
|
+
equals(controller.get('firstSelectableObject'), newObject, 'first selectable object should be the new first object in content');
|
197
|
+
equals(controller.get('lastObject'), newObject, 'lastObject should be the new last object in content');
|
198
|
+
});
|
199
|
+
|
186
200
|
test("array orderBy using String", function(){
|
187
201
|
var testController = SC.ArrayController.create({
|
188
202
|
content: content,
|
@@ -0,0 +1,103 @@
|
|
1
|
+
// ==========================================================================
|
2
|
+
// Project: SproutCore - JavaScript Application Framework
|
3
|
+
// Copyright: ©2006-2011 Strobe Inc. and contributors.
|
4
|
+
// ©2008-2011 Apple Inc. All rights reserved.
|
5
|
+
// License: Licensed under MIT license (see license.js)
|
6
|
+
// ==========================================================================
|
7
|
+
|
8
|
+
/*global module, test, equals, ok */
|
9
|
+
|
10
|
+
var view;
|
11
|
+
|
12
|
+
/** Test isFixedLayout via isFixedSize and isFixedPosition properties. */
|
13
|
+
module("SC.View.prototype.isFixedLayout", {
|
14
|
+
|
15
|
+
setup: function () {
|
16
|
+
// Create a basic view.
|
17
|
+
view = SC.View.create({});
|
18
|
+
},
|
19
|
+
|
20
|
+
teardown: function () {
|
21
|
+
// Clean up.
|
22
|
+
view.destroy();
|
23
|
+
view = null;
|
24
|
+
}
|
25
|
+
|
26
|
+
});
|
27
|
+
|
28
|
+
test("Test isFixedSize for various layouts.", function () {
|
29
|
+
ok(!view.get('isFixedSize'), "The default layout doesn't correspond to a fixed size.");
|
30
|
+
|
31
|
+
SC.run(function () { view.set('layout', { width: 100 }); });
|
32
|
+
ok(!view.get('isFixedSize'), "A width alone doesn't correspond to a fixed size.");
|
33
|
+
|
34
|
+
SC.run(function () { view.set('layout', { height: 100 }); });
|
35
|
+
ok(!view.get('isFixedSize'), "A height alone doesn't correspond to a fixed size.");
|
36
|
+
|
37
|
+
SC.run(function () { view.set('layout', { width: 100, height: 100 }); });
|
38
|
+
ok(view.get('isFixedSize'), "A width & height corresponds to a fixed size.");
|
39
|
+
});
|
40
|
+
|
41
|
+
test("Test isFixedPosition for various layouts.", function () {
|
42
|
+
ok(view.get('isFixedPosition'), "The default layout corresponds to a fixed position.");
|
43
|
+
|
44
|
+
SC.run(function () { view.set('layout', { left: 0 }); });
|
45
|
+
ok(view.get('isFixedPosition'), "A left: 0 (implied top, bottom, right) corresponds to a fixed position.");
|
46
|
+
|
47
|
+
SC.run(function () { view.set('layout', { top: 0 }); });
|
48
|
+
ok(view.get('isFixedPosition'), "A top: 0 (implied left, bottom, right) corresponds to a fixed position.");
|
49
|
+
|
50
|
+
SC.run(function () { view.set('layout', { left: 0, top: 0 }); });
|
51
|
+
ok(view.get('isFixedPosition'), "A left: 0, top: 0 corresponds to a fixed position.");
|
52
|
+
|
53
|
+
SC.run(function () { view.set('layout', { left: 50 }); });
|
54
|
+
ok(view.get('isFixedPosition'), "A left: 50 corresponds to a fixed position.");
|
55
|
+
|
56
|
+
SC.run(function () { view.set('layout', { top: 50 }); });
|
57
|
+
ok(view.get('isFixedPosition'), "A top: 50 corresponds to a fixed position.");
|
58
|
+
|
59
|
+
SC.run(function () { view.set('layout', { left: 50, top: 50 }); });
|
60
|
+
ok(view.get('isFixedPosition'), "A left: 50, top: 50 corresponds to a fixed position.");
|
61
|
+
|
62
|
+
SC.run(function () { view.set('layout', { right: 0 }); });
|
63
|
+
ok(view.get('isFixedPosition'), "A right: 0 (implied left) corresponds to a fixed position.");
|
64
|
+
|
65
|
+
SC.run(function () { view.set('layout', { bottom: 0 }); });
|
66
|
+
ok(view.get('isFixedPosition'), "A bottom: 0 (implied top) corresponds to a fixed position.");
|
67
|
+
|
68
|
+
SC.run(function () { view.set('layout', { right: 50 }); });
|
69
|
+
ok(view.get('isFixedPosition'), "A right: 50 (implied left) corresponds to a fixed position.");
|
70
|
+
|
71
|
+
SC.run(function () { view.set('layout', { bottom: 50 }); });
|
72
|
+
ok(view.get('isFixedPosition'), "A bottom: 50 (implied top) corresponds to a fixed position.");
|
73
|
+
|
74
|
+
SC.run(function () { view.set('layout', { width: 100 }); });
|
75
|
+
ok(view.get('isFixedPosition'), "A width: 100 (implied left) corresponds to a fixed position.");
|
76
|
+
|
77
|
+
SC.run(function () { view.set('layout', { height: 100 }); });
|
78
|
+
ok(view.get('isFixedPosition'), "A height: 100 (implied top) corresponds to a fixed position.");
|
79
|
+
|
80
|
+
SC.run(function () { view.set('layout', { right: 0, width: 100 }); });
|
81
|
+
ok(!view.get('isFixedPosition'), "A right: 0, width: 100 (overridden left) doesn't correspond to a fixed position.");
|
82
|
+
|
83
|
+
SC.run(function () { view.set('layout', { bottom: 0, height: 100 }); });
|
84
|
+
ok(!view.get('isFixedPosition'), "A bottom: 0, height: 100 (overridden top) doesn't correspond to a fixed position.");
|
85
|
+
|
86
|
+
SC.run(function () { view.set('layout', { centerX: 0, width: 100 }); });
|
87
|
+
ok(!view.get('isFixedPosition'), "A centerX: 0, width: 100 (overridden left) doesn't correspond to a fixed position.");
|
88
|
+
|
89
|
+
SC.run(function () { view.set('layout', { centerY: 0, height: 100 }); });
|
90
|
+
ok(!view.get('isFixedPosition'), "A centerY: 0, height: 100 (overridden top) doesn't correspond to a fixed position.");
|
91
|
+
|
92
|
+
SC.run(function () { view.set('layout', { left: 0.2 }); });
|
93
|
+
ok(!view.get('isFixedPosition'), "A left: 0.2 (percentage left) doesn't correspond to a fixed position.");
|
94
|
+
|
95
|
+
SC.run(function () { view.set('layout', { top: 0.2 }); });
|
96
|
+
ok(!view.get('isFixedPosition'), "A top: 0.2 (percentage top) doesn't correspond to a fixed position.");
|
97
|
+
|
98
|
+
SC.run(function () { view.set('layout', { left: SC.LAYOUT_AUTO }); });
|
99
|
+
ok(!view.get('isFixedPosition'), "A left: SC.LAYOUT_AUTO (auto left) doesn't correspond to a fixed position.");
|
100
|
+
|
101
|
+
SC.run(function () { view.set('layout', { top: SC.LAYOUT_AUTO }); });
|
102
|
+
ok(!view.get('isFixedPosition'), "A top: SC.LAYOUT_AUTO (auto top) doesn't correspond to a fixed position.");
|
103
|
+
});
|
data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutChildViews.js
CHANGED
@@ -41,7 +41,7 @@ test("calls renderLayout() on child views on views that need layout if they have
|
|
41
41
|
//
|
42
42
|
module("SC.View#updateLayout");
|
43
43
|
|
44
|
-
test("if view has layout, calls
|
44
|
+
test("if view has layout, calls _doUpdateLayoutStyle", function() {
|
45
45
|
|
46
46
|
// NOTE: renderLayout() is also called when a view's
|
47
47
|
// layer is first created. We use isTesting below to
|
@@ -49,7 +49,7 @@ test("if view has layout, calls _executeDoUpdateLayout", function() {
|
|
49
49
|
// are actually doing layout.
|
50
50
|
var callCount = 0, isTesting = NO ;
|
51
51
|
var view = SC.View.create({
|
52
|
-
|
52
|
+
_doUpdateLayoutStyle: function() {
|
53
53
|
callCount++;
|
54
54
|
}
|
55
55
|
});
|
@@ -58,10 +58,10 @@ test("if view has layout, calls _executeDoUpdateLayout", function() {
|
|
58
58
|
ok(view.get('layer'), 'precond - should have a layer');
|
59
59
|
|
60
60
|
view.updateLayout();
|
61
|
-
equals(callCount, 0, 'should not call
|
61
|
+
equals(callCount, 0, 'should not call _doUpdateLayoutStyle() because the view isn\'t shown');
|
62
62
|
|
63
63
|
view.updateLayout(true);
|
64
|
-
equals(callCount, 1, 'should call
|
64
|
+
equals(callCount, 1, 'should call _doUpdateLayoutStyle() because we force it');
|
65
65
|
|
66
66
|
// Clean up.
|
67
67
|
view.destroy();
|
data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutDidChange.js
CHANGED
@@ -25,7 +25,9 @@ test("notifies layoutStyle & frame change", function () {
|
|
25
25
|
equals(layoutStyleCallCount, 0, 'should not trigger observers for layoutStyle');
|
26
26
|
|
27
27
|
// Attach to the document.
|
28
|
-
|
28
|
+
var parent = SC.Pane.create();
|
29
|
+
parent.append();
|
30
|
+
parent.appendChild(view);
|
29
31
|
|
30
32
|
equals(frameCallCount, 2, 'should trigger observers for frame when attached to the document');
|
31
33
|
equals(layoutStyleCallCount, 0, 'should still not trigger observers for layoutStyle');
|
@@ -39,6 +41,7 @@ test("notifies layoutStyle & frame change", function () {
|
|
39
41
|
|
40
42
|
// Clean up.
|
41
43
|
view.destroy();
|
44
|
+
parent.destroy();
|
42
45
|
});
|
43
46
|
|
44
47
|
test("invokes layoutDidChangeFor() on layoutView each time it is called", function () {
|
@@ -166,28 +166,28 @@ test("When parentViewDidResize is called on a view, it should only notify on fra
|
|
166
166
|
view.viewDidResize.reset(); view.frameCallCount = 0;
|
167
167
|
parentView.adjust({ width: 60, height: 60 });
|
168
168
|
view.viewDidResize.expect(0);
|
169
|
-
equals(view.frameCallCount, 1, 'should notify frame changed when isFixedPosition: %@ and isFixedSize: %@'.fmt(view.get('isFixedPosition'), view.get('isFixedSize')));
|
169
|
+
equals(view.frameCallCount, 1, 'right align: should notify frame changed when isFixedPosition: %@ and isFixedSize: %@'.fmt(view.get('isFixedPosition'), view.get('isFixedSize')));
|
170
170
|
|
171
171
|
// try with bottom align
|
172
|
-
view.set('layout', {
|
172
|
+
view.set('layout', { left: 10, bottom: 10, height: 10, width: 10 });
|
173
173
|
view.viewDidResize.reset(); view.frameCallCount = 0;
|
174
174
|
parentView.adjust({ width: 50, height: 50 });
|
175
175
|
view.viewDidResize.expect(0);
|
176
|
-
equals(view.frameCallCount, 1, 'should notify frame changed when isFixedPosition: %@ and isFixedSize: %@'.fmt(view.get('isFixedPosition'), view.get('isFixedSize')));
|
176
|
+
equals(view.frameCallCount, 1, 'bottom align: should notify frame changed when isFixedPosition: %@ and isFixedSize: %@'.fmt(view.get('isFixedPosition'), view.get('isFixedSize')));
|
177
177
|
|
178
178
|
// try with center horizontal align
|
179
179
|
view.set('layout', { centerX: 10, top: 10, height: 10, width: 10 });
|
180
180
|
view.viewDidResize.reset(); view.frameCallCount = 0;
|
181
181
|
parentView.adjust({ width: 40, height: 40 });
|
182
182
|
view.viewDidResize.expect(0);
|
183
|
-
equals(view.frameCallCount, 1, 'should notify frame changed when isFixedPosition: %@ and isFixedSize: %@'.fmt(view.get('isFixedPosition'), view.get('isFixedSize')));
|
183
|
+
equals(view.frameCallCount, 1, 'centerX: should notify frame changed when isFixedPosition: %@ and isFixedSize: %@'.fmt(view.get('isFixedPosition'), view.get('isFixedSize')));
|
184
184
|
|
185
185
|
// try with center vertical align
|
186
186
|
view.set('layout', { left: 10, centerY: 10, height: 10, width: 10 });
|
187
187
|
view.viewDidResize.reset(); view.frameCallCount = 0;
|
188
188
|
parentView.adjust({ width: 30, height: 30 });
|
189
189
|
view.viewDidResize.expect(0);
|
190
|
-
equals(view.frameCallCount, 1, 'should notify frame changed when isFixedPosition: %@ and isFixedSize: %@'.fmt(view.get('isFixedPosition'), view.get('isFixedSize')));
|
190
|
+
equals(view.frameCallCount, 1, 'centerY: should notify frame changed when isFixedPosition: %@ and isFixedSize: %@'.fmt(view.get('isFixedPosition'), view.get('isFixedSize')));
|
191
191
|
});
|
192
192
|
|
193
193
|
// ..........................................................
|
@@ -276,13 +276,24 @@ SC.View.reopen(
|
|
276
276
|
*/
|
277
277
|
isFixedPosition: function () {
|
278
278
|
var layout = this.get('layout'),
|
279
|
-
|
279
|
+
hasLeft,
|
280
|
+
hasTop,
|
281
|
+
ret;
|
280
282
|
|
281
283
|
// Position is fixed if it has left + top !== SC.LAYOUT_AUTO
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
284
|
+
hasLeft = layout.left !== undefined;
|
285
|
+
if (!hasLeft) {
|
286
|
+
// Check for implied left. If there is a width, then there can't be a right or centerX.
|
287
|
+
hasLeft = layout.width === undefined || (layout.width !== undefined && layout.right === undefined && layout.centerX === undefined);
|
288
|
+
}
|
289
|
+
|
290
|
+
hasTop = layout.top !== undefined;
|
291
|
+
if (!hasTop) {
|
292
|
+
// Check for implied top. If there is a height, then there can't be a bottom or centerY.
|
293
|
+
hasTop = layout.height === undefined || (layout.height !== undefined && layout.bottom === undefined && layout.centerY === undefined);
|
294
|
+
}
|
295
|
+
|
296
|
+
ret = (hasLeft && hasTop && layout.left !== SC.LAYOUT_AUTO && layout.top !== SC.LAYOUT_AUTO);
|
286
297
|
|
287
298
|
// The position may appear fixed, but only if none of the values are percentages.
|
288
299
|
if (ret) {
|
@@ -1220,7 +1231,7 @@ SC.View.reopen(
|
|
1220
1231
|
/** @private Override: Notify on attached (avoids notify of frame changed). */
|
1221
1232
|
_notifyAttached: function () {
|
1222
1233
|
// If we are using static layout then we don't know the frame until appended to the document.
|
1223
|
-
if (this.get('useStaticLayout')
|
1234
|
+
if (this.get('useStaticLayout')) {
|
1224
1235
|
// We call viewDidResize so that it calls parentViewDidResize on all child views.
|
1225
1236
|
this.viewDidResize();
|
1226
1237
|
}
|
@@ -1,5 +1,10 @@
|
|
1
1
|
sc_require("views/view/base");
|
2
2
|
|
3
|
+
// When in debug mode, core developers can log the view state.
|
4
|
+
//@if (debug)
|
5
|
+
SC.LOG_VIEW_STATES = false;
|
6
|
+
//@endif
|
7
|
+
|
3
8
|
|
4
9
|
SC.CoreView.mixin(
|
5
10
|
/** @scope SC.CoreView */ {
|
@@ -260,6 +265,12 @@ SC.CoreView.reopen(
|
|
260
265
|
var curParentView = this.get('parentView'),
|
261
266
|
handled = true;
|
262
267
|
|
268
|
+
//@if (debug)
|
269
|
+
if (SC.LOG_VIEW_STATES) {
|
270
|
+
SC.Logger.log('%@:%@ — _doAdopt(%@, %@)'.fmt(this, this.get('viewState'), parentView, beforeView));
|
271
|
+
}
|
272
|
+
//@endif
|
273
|
+
|
263
274
|
if (curParentView && curParentView !== parentView) {
|
264
275
|
//@if(debug)
|
265
276
|
// This should be avoided, because using the same view instance without explicitly orphaning it first is a dangerous practice.
|
@@ -295,7 +306,6 @@ SC.CoreView.reopen(
|
|
295
306
|
// Notify adopted (on self and all child views).
|
296
307
|
this._adopted();
|
297
308
|
|
298
|
-
|
299
309
|
switch (this.get('viewState')) {
|
300
310
|
case SC.CoreView.UNRENDERED:
|
301
311
|
switch (parentViewState) {
|
@@ -353,6 +363,12 @@ SC.CoreView.reopen(
|
|
353
363
|
transitionIn = this.get('transitionIn'),
|
354
364
|
parentView;
|
355
365
|
|
366
|
+
//@if (debug)
|
367
|
+
if (SC.LOG_VIEW_STATES) {
|
368
|
+
SC.Logger.log('%@:%@ — _doAttach(%@, %@)'.fmt(this, state, parentNode, nextNode));
|
369
|
+
}
|
370
|
+
//@endif
|
371
|
+
|
356
372
|
switch (state) {
|
357
373
|
case SC.CoreView.ATTACHED_HIDING: // FAST PATH!
|
358
374
|
case SC.CoreView.ATTACHED_HIDDEN: // FAST PATH!
|
@@ -434,6 +450,12 @@ SC.CoreView.reopen(
|
|
434
450
|
_doDestroyLayer: function () {
|
435
451
|
var handled = true;
|
436
452
|
|
453
|
+
//@if (debug)
|
454
|
+
if (SC.LOG_VIEW_STATES) {
|
455
|
+
SC.Logger.log('%@:%@ — _doDestroyLayer()'.fmt(this, this.get('viewState')));
|
456
|
+
}
|
457
|
+
//@endif
|
458
|
+
|
437
459
|
if (this.get('_isRendered') && !this.get('isAttached')) {
|
438
460
|
// Remove our reference to the layer (our self and all our child views).
|
439
461
|
this._executeDoDestroyLayer();
|
@@ -450,6 +472,12 @@ SC.CoreView.reopen(
|
|
450
472
|
var state = this.get('viewState'),
|
451
473
|
transitionOut = this.get('transitionOut');
|
452
474
|
|
475
|
+
//@if (debug)
|
476
|
+
if (SC.LOG_VIEW_STATES) {
|
477
|
+
SC.Logger.log('%@:%@ — _doDetach()'.fmt(this, state));
|
478
|
+
}
|
479
|
+
//@endif
|
480
|
+
|
453
481
|
switch (state) {
|
454
482
|
case SC.CoreView.UNRENDERED: // FAST PATH!
|
455
483
|
case SC.CoreView.UNATTACHED: // FAST PATH!
|
@@ -540,6 +568,12 @@ SC.CoreView.reopen(
|
|
540
568
|
var state = this.get('viewState'),
|
541
569
|
transitionHide = this.get('transitionHide');
|
542
570
|
|
571
|
+
//@if (debug)
|
572
|
+
if (SC.LOG_VIEW_STATES) {
|
573
|
+
SC.Logger.log('%@:%@ — _doHide()'.fmt(this, state));
|
574
|
+
}
|
575
|
+
//@endif
|
576
|
+
|
543
577
|
switch (state) {
|
544
578
|
case SC.CoreView.UNRENDERED: // FAST PATH!
|
545
579
|
case SC.CoreView.ATTACHED_HIDDEN: // FAST PATH!
|
@@ -603,6 +637,12 @@ SC.CoreView.reopen(
|
|
603
637
|
var parentView = this.get('parentView'),
|
604
638
|
handled = true;
|
605
639
|
|
640
|
+
//@if (debug)
|
641
|
+
if (SC.LOG_VIEW_STATES) {
|
642
|
+
SC.Logger.log('%@:%@ — _doOrphan()'.fmt(this, this.get('viewState')));
|
643
|
+
}
|
644
|
+
//@endif
|
645
|
+
|
606
646
|
if (parentView) {
|
607
647
|
var childViews = parentView.get('childViews'),
|
608
648
|
idx = childViews.indexOf(this);
|
@@ -623,10 +663,15 @@ SC.CoreView.reopen(
|
|
623
663
|
},
|
624
664
|
|
625
665
|
/** @private Render this view action. */
|
626
|
-
|
627
666
|
_doRender: function () {
|
628
667
|
var state = this.get('viewState');
|
629
668
|
|
669
|
+
//@if (debug)
|
670
|
+
if (SC.LOG_VIEW_STATES) {
|
671
|
+
SC.Logger.log('%@:%@ — _doRender()'.fmt(this, state));
|
672
|
+
}
|
673
|
+
//@endif
|
674
|
+
|
630
675
|
switch (state) {
|
631
676
|
case SC.CoreView.ATTACHED_SHOWING: // FAST PATHS!
|
632
677
|
case SC.CoreView.ATTACHED_SHOWN:
|
@@ -646,7 +691,7 @@ SC.CoreView.reopen(
|
|
646
691
|
this.renderToContext(context);
|
647
692
|
this.set('layer', context.element());
|
648
693
|
|
649
|
-
// Route.
|
694
|
+
// Route first.
|
650
695
|
this._gotoUnattachedState();
|
651
696
|
|
652
697
|
// Notify rendered (on self and all child views).
|
@@ -679,6 +724,12 @@ SC.CoreView.reopen(
|
|
679
724
|
isParentShown = parentView ? parentView.get('viewState') & SC.CoreView.IS_SHOWN : true,
|
680
725
|
transitionShow = this.get('transitionShow');
|
681
726
|
|
727
|
+
//@if (debug)
|
728
|
+
if (SC.LOG_VIEW_STATES) {
|
729
|
+
SC.Logger.log('%@:%@ — _doShow()'.fmt(this, state));
|
730
|
+
}
|
731
|
+
//@endif
|
732
|
+
|
682
733
|
switch (state) {
|
683
734
|
case SC.CoreView.ATTACHED_SHOWN: // FAST PATH!
|
684
735
|
case SC.CoreView.ATTACHED_SHOWING: // FAST PATH!
|
@@ -744,8 +795,11 @@ SC.CoreView.reopen(
|
|
744
795
|
var isVisibleInWindow = this.get('isVisibleInWindow'),
|
745
796
|
handled = true;
|
746
797
|
|
747
|
-
|
748
|
-
|
798
|
+
//@if (debug)
|
799
|
+
if (SC.LOG_VIEW_STATES) {
|
800
|
+
SC.Logger.log('%@:%@ — _doUpdateContent(%@)'.fmt(this, this.get('viewState'), force));
|
801
|
+
}
|
802
|
+
//@endif
|
749
803
|
|
750
804
|
if (this.get('_isRendered')) {
|
751
805
|
if (isVisibleInWindow || force) {
|
@@ -1188,11 +1242,11 @@ SC.CoreView.reopen(
|
|
1188
1242
|
|
1189
1243
|
/** @private Updates according to parent did render. */
|
1190
1244
|
_parentDidRender: function () {
|
1245
|
+
// Route first.
|
1246
|
+
this._gotoUnattachedByParentState();
|
1247
|
+
|
1191
1248
|
// Notify rendered.
|
1192
1249
|
this._rendered();
|
1193
|
-
|
1194
|
-
// Route
|
1195
|
-
this._gotoUnattachedByParentState();
|
1196
1250
|
},
|
1197
1251
|
|
1198
1252
|
/** @private Starts building out view if appropriate. */
|
@@ -281,8 +281,20 @@ SC.CoreView.reopen(
|
|
281
281
|
@returns {SC.View} receiver
|
282
282
|
*/
|
283
283
|
displayDidChange: function () {
|
284
|
-
|
285
|
-
|
284
|
+
//@if (debug)
|
285
|
+
if (SC.LOG_VIEW_STATES) {
|
286
|
+
SC.Logger.log('%@:%@ — displayDidChange()'.fmt(this, this.get('viewState')));
|
287
|
+
}
|
288
|
+
//@endif
|
289
|
+
|
290
|
+
// Don't run _doUpdateContent needlessly, because the view may render
|
291
|
+
// before it is invoked, which would result in a needless update.
|
292
|
+
if (this.get('_isRendered')) {
|
293
|
+
// Legacy.
|
294
|
+
this.set('layerNeedsUpdate', true);
|
295
|
+
|
296
|
+
this.invokeOnce(this._doUpdateContent);
|
297
|
+
}
|
286
298
|
|
287
299
|
return this;
|
288
300
|
},
|
@@ -393,12 +393,33 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
|
|
393
393
|
if (!editables) editables = this.editables = [];
|
394
394
|
editables[storeKey] = 1 ; // use number for dense array support
|
395
395
|
|
396
|
-
|
397
|
-
this.
|
398
|
-
|
399
|
-
|
396
|
+
// Update the child record hashes in place.
|
397
|
+
if (!SC.none(this.parentRecords) ) {
|
398
|
+
var children = this.parentRecords[storeKey] || {},
|
399
|
+
childHash;
|
400
|
+
|
401
|
+
for (var key in children) {
|
402
|
+
|
403
|
+
if (children.hasOwnProperty(key)) {
|
404
|
+
|
405
|
+
if (hash) {
|
406
|
+
var childPath = children[key];
|
407
|
+
childPath = childPath.split('.');
|
408
|
+
if (childPath.length > 1) {
|
409
|
+
childHash = hash[childPath[0]][childPath[1]];
|
410
|
+
} else {
|
411
|
+
childHash = hash[childPath[0]];
|
412
|
+
}
|
400
413
|
|
401
|
-
|
414
|
+
this.writeDataHash(key, childHash, status);
|
415
|
+
} else {
|
416
|
+
this.writeDataHash(key, null, status);
|
417
|
+
}
|
418
|
+
}
|
419
|
+
}
|
420
|
+
}
|
421
|
+
|
422
|
+
return this;
|
402
423
|
},
|
403
424
|
|
404
425
|
/**
|
@@ -41,7 +41,14 @@ module("SC.Record.toMany array with data source", {
|
|
41
41
|
}
|
42
42
|
});
|
43
43
|
|
44
|
-
test("when retrieving records with toMany association, it should call retrieveRecords once instead of calling retrieveRecord multiple times"
|
44
|
+
test("when retrieving records with toMany association, it should call retrieveRecords once instead of calling retrieveRecord multiple times");
|
45
|
+
/** WON'T FIX AT THIS TIME.
|
46
|
+
|
47
|
+
Yes, iterating a toMany attribute will call retrieveRecord for each individual index, but we cannot change this. If we tried to buffer all calls to retrieveRecord then we will break the existing contract that retrieveRecord and retrieveRecords will return immediately with storeKeys if the data source is going to handle it. Plus there are alternatives. The custom datasource could use invokeOnce and a temporary cache to buffer all calls to retrieveRecord in order to build a single request out of multiple ids. This is the most feasible, because it's highly dependent on the datasource/backend configuration. The other alternative is that the backend should return the related records when the main record is requested in a single request (again, highly dependent on the datasource/backend configuration).
|
48
|
+
|
49
|
+
To do it within SproutCore itself would mean a big change along the lines of how every app works with the store and so it will certainly have to wait until a major version.
|
50
|
+
|
51
|
+
, function() {
|
45
52
|
var store = SC.Store.create().from("MyDataSource");
|
46
53
|
SC.RunLoop.begin();
|
47
54
|
store.loadRecords(MyApp.Project, [
|
@@ -61,3 +68,4 @@ test("when retrieving records with toMany association, it should call retrieveRe
|
|
61
68
|
// retrieveRecords should be called only once
|
62
69
|
same(store.get('dataSource').get('retrieveRecordsArguments').length, 1);
|
63
70
|
});
|
71
|
+
*/
|
data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/nested_records/data_store.js
CHANGED
@@ -181,8 +181,7 @@ test("Use in Nested Store", function () {
|
|
181
181
|
});
|
182
182
|
|
183
183
|
test("Store#pushRetrieve for parent updates the child records", function () {
|
184
|
-
var parent
|
185
|
-
nr = parent.get('contents').firstObject(),
|
184
|
+
var parent, nr,
|
186
185
|
newDataHash = {
|
187
186
|
type: 'Directory',
|
188
187
|
name: 'Dir 1 Changed',
|
@@ -208,6 +207,11 @@ test("Store#pushRetrieve for parent updates the child records", function () {
|
|
208
207
|
]
|
209
208
|
};
|
210
209
|
|
210
|
+
SC.run(function () {
|
211
|
+
parent = store.materializeRecord(storeKeys[0]);
|
212
|
+
nr = parent.get('contents').firstObject();
|
213
|
+
});
|
214
|
+
|
211
215
|
ok(nr, "Got nested record");
|
212
216
|
equals(nr.get('name'), 'Dir 2', "Dir id:2 has correct name");
|
213
217
|
|
@@ -20,7 +20,7 @@ SC.NeedsSplitParent = {
|
|
20
20
|
* @property SC.SplitView
|
21
21
|
*/
|
22
22
|
splitView: function () {
|
23
|
-
var view = this;
|
23
|
+
var view = this.get('parentView');
|
24
24
|
while (view && !view.isSplitView) view = view.get('parentView');
|
25
25
|
return view;
|
26
26
|
}.property('parentView').cacheable(),
|