sproutcore 1.10.1 → 1.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +8 -8
- data/CHANGELOG +13 -0
- data/VERSION.yml +1 -1
- data/lib/frameworks/sproutcore/CHANGELOG.md +69 -31
- data/lib/frameworks/sproutcore/frameworks/core_foundation/controllers/array.js +14 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/controllers/object.js +14 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/event.js +7 -2
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/platform.js +13 -9
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/root_responder.js +57 -23
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/enabled_states_test.js +24 -6
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/animation.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/enabled.js +63 -13
- data/lib/frameworks/sproutcore/frameworks/datastore/models/record.js +3 -3
- data/lib/frameworks/sproutcore/frameworks/datastore/models/single_attribute.js +7 -1
- data/lib/frameworks/sproutcore/frameworks/datastore/system/many_array.js +28 -5
- data/lib/frameworks/sproutcore/frameworks/datastore/system/query.js +15 -0
- data/lib/frameworks/sproutcore/frameworks/datastore/system/record_array.js +30 -3
- data/lib/frameworks/sproutcore/frameworks/datastore/system/store.js +23 -1
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/many_attribute.js +135 -89
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/single_attribute.js +12 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/panes/picker.js +18 -6
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/picker/ui.js +58 -20
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/date_field/methods.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/select/methods.js +15 -1
- data/lib/frameworks/sproutcore/frameworks/desktop/views/button.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/desktop/views/popup_button.js +10 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/views/scroll.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/desktop/views/select.js +24 -23
- data/lib/frameworks/sproutcore/frameworks/desktop/views/split.js +4 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/select_view/views/popup_button.js +10 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/delegates/inline_text_field.js +4 -4
- data/lib/frameworks/sproutcore/frameworks/foundation/mixins/auto_mixin.js +33 -16
- data/lib/frameworks/sproutcore/frameworks/foundation/mixins/content_value_support.js +14 -6
- data/lib/frameworks/sproutcore/frameworks/foundation/mixins/control.js +23 -18
- data/lib/frameworks/sproutcore/frameworks/foundation/system/user_defaults.js +4 -4
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/delegates/inline_text_field/inline_text_field.js +1 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/auto_mixin_tests.js +78 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/auto_resize_test.js +45 -1
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/content_value_support/content.js +112 -58
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/system/image_queue.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/views/container/transition_test.js +141 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/views/text_field/methods.js +27 -2
- data/lib/frameworks/sproutcore/frameworks/foundation/tests/views/text_field/ui.js +631 -593
- data/lib/frameworks/sproutcore/frameworks/foundation/transitions/swap_fade_color_transition.js +5 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/transitions/swap_move_in_transition.js +5 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/transitions/swap_reveal_transition.js +68 -1
- data/lib/frameworks/sproutcore/frameworks/foundation/views/container.js +128 -49
- data/lib/frameworks/sproutcore/frameworks/foundation/views/field.js +33 -8
- data/lib/frameworks/sproutcore/frameworks/foundation/views/text_field.js +209 -187
- data/lib/frameworks/sproutcore/frameworks/runtime/core.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/runtime/mixins/observable.js +7 -0
- data/lib/frameworks/sproutcore/frameworks/runtime/system/binding.js +34 -4
- data/lib/frameworks/sproutcore/frameworks/runtime/system/object.js +0 -2
- data/lib/frameworks/sproutcore/frameworks/runtime/tests/system/binding.js +68 -9
- data/lib/frameworks/sproutcore/frameworks/testing/system/runner.js +2 -1
- data/lib/sproutcore/rack/builder.rb +45 -25
- data/sproutcore.gemspec +1 -0
- metadata +17 -2
@@ -15,23 +15,23 @@ module("SC.ManyAttribute core methods", {
|
|
15
15
|
MyApp = SC.Object.create({
|
16
16
|
store: SC.Store.create()
|
17
17
|
});
|
18
|
-
|
18
|
+
|
19
19
|
MyApp.Foo = SC.Record.extend({
|
20
|
-
|
20
|
+
|
21
21
|
// test simple reading of a pass-through prop
|
22
22
|
firstName: SC.Record.attr(String),
|
23
23
|
|
24
24
|
// test mapping to another internal key
|
25
25
|
otherName: SC.Record.attr(String, { key: "firstName" }),
|
26
|
-
|
26
|
+
|
27
27
|
// test mapping Date
|
28
28
|
date: SC.Record.attr(Date),
|
29
|
-
|
29
|
+
|
30
30
|
// used to test default value
|
31
31
|
defaultValue: SC.Record.attr(String, {
|
32
32
|
defaultValue: "default"
|
33
33
|
}),
|
34
|
-
|
34
|
+
|
35
35
|
// test toMany relationships
|
36
36
|
fooMany: SC.Record.toMany('MyApp.Foo'),
|
37
37
|
|
@@ -44,85 +44,85 @@ module("SC.ManyAttribute core methods", {
|
|
44
44
|
barToMany: SC.Record.toMany('MyApp.Bar', {
|
45
45
|
inverse: 'fooToMany', isMaster: YES, orderBy: 'name'
|
46
46
|
}),
|
47
|
-
|
47
|
+
|
48
48
|
// test many-to-one relationships with inverse
|
49
49
|
barToOne: SC.Record.toMany('MyApp.Bar', {
|
50
50
|
inverse: 'fooToOne', isMaster: NO
|
51
51
|
})
|
52
|
-
|
52
|
+
|
53
53
|
});
|
54
|
-
|
54
|
+
|
55
55
|
MyApp.Bar = SC.Record.extend({
|
56
|
-
|
56
|
+
|
57
57
|
// test many-to-many
|
58
58
|
fooToMany: SC.Record.toMany('MyApp.Foo', {
|
59
59
|
inverse: 'barToMany', isMaster: NO
|
60
60
|
}),
|
61
|
-
|
61
|
+
|
62
62
|
// test many-to-one
|
63
63
|
fooToOne: SC.Record.toOne('MyApp.Foo', {
|
64
64
|
inverse: 'barToOne', isMaster: YES
|
65
65
|
})
|
66
66
|
});
|
67
|
-
|
67
|
+
|
68
68
|
storeKeys = MyApp.store.loadRecords(MyApp.Foo, [
|
69
|
-
{ guid: 1,
|
70
|
-
firstName: "John",
|
69
|
+
{ guid: 1,
|
70
|
+
firstName: "John",
|
71
71
|
lastName: "Doe",
|
72
72
|
barToMany: ['bar1'],
|
73
|
-
barToOne: ['bar1', 'bar2']
|
73
|
+
barToOne: ['bar1', 'bar2']
|
74
74
|
},
|
75
|
-
|
76
|
-
{ guid: 2,
|
77
|
-
firstName: "Jane",
|
75
|
+
|
76
|
+
{ guid: 2,
|
77
|
+
firstName: "Jane",
|
78
78
|
lastName: "Doe",
|
79
79
|
barToMany: ['bar1', 'bar2'],
|
80
|
-
barToOne: []
|
80
|
+
barToOne: []
|
81
81
|
},
|
82
|
-
|
83
|
-
{ guid: 3,
|
84
|
-
firstName: "Emily",
|
85
|
-
lastName: "Parker",
|
82
|
+
|
83
|
+
{ guid: 3,
|
84
|
+
firstName: "Emily",
|
85
|
+
lastName: "Parker",
|
86
86
|
fooMany: [1,2],
|
87
87
|
barToMany: ['bar2'],
|
88
|
-
barToOne: []
|
88
|
+
barToOne: []
|
89
89
|
},
|
90
|
-
|
90
|
+
|
91
91
|
{ guid: 4,
|
92
92
|
firstName: "Johnny",
|
93
93
|
lastName: "Cash",
|
94
94
|
fooIds: [1,2]
|
95
95
|
}
|
96
96
|
]);
|
97
|
-
|
97
|
+
|
98
98
|
MyApp.store.loadRecords(MyApp.Bar, [
|
99
99
|
{ guid: "bar1", name: "A", fooToMany: [1,2], fooToOne: 1 },
|
100
100
|
{ guid: "bar2", name: "Z", fooToMany: [2,3], fooToOne: 1 },
|
101
101
|
{ guid: "bar3", name: "C" }
|
102
102
|
]);
|
103
|
-
|
103
|
+
|
104
104
|
foo1 = rec = MyApp.store.find(MyApp.Foo, 1);
|
105
105
|
foo2 = rec2 = MyApp.store.find(MyApp.Foo, 2);
|
106
106
|
foo3 = rec3 = MyApp.store.find(MyApp.Foo, 3);
|
107
107
|
rec4 = MyApp.store.find(MyApp.Foo, 4);
|
108
108
|
equals(rec.storeKey, storeKeys[0], 'should find record');
|
109
|
-
|
109
|
+
|
110
110
|
bar1 = MyApp.store.find(MyApp.Bar, "bar1");
|
111
111
|
bar2 = MyApp.store.find(MyApp.Bar, 'bar2');
|
112
112
|
bar3 = MyApp.store.find(MyApp.Bar, 'bar3');
|
113
|
-
|
113
|
+
|
114
114
|
SC.RunLoop.end();
|
115
115
|
},
|
116
|
-
|
116
|
+
|
117
117
|
teardown: function() {
|
118
|
-
MyApp = rec = rec2 = rec3 =
|
118
|
+
MyApp = rec = rec2 = rec3 =
|
119
119
|
foo1 = foo2 = foo3 = bar1 = bar2 = null;
|
120
120
|
}
|
121
121
|
});
|
122
122
|
|
123
123
|
// ..........................................................
|
124
124
|
// READING
|
125
|
-
//
|
125
|
+
//
|
126
126
|
|
127
127
|
test("pass-through should return builtin value" ,function() {
|
128
128
|
equals(rec.get('firstName'), 'John', 'reading prop should get attr value');
|
@@ -141,10 +141,10 @@ test("getting toMany relationship should map guid to real records when using dif
|
|
141
141
|
equals(rec4.get('fooManyKeyed').objectAt(0), rec, 'should get rec1 instance for rec4.fooManyKeyed');
|
142
142
|
equals(rec4.get('fooManyKeyed').objectAt(1), rec2, 'should get rec2 instance for rec4.fooManyKeyed');
|
143
143
|
});
|
144
|
-
|
144
|
+
|
145
145
|
test("getting toMany relation should not change record state", function() {
|
146
146
|
equals(rec3.get('status'), SC.Record.READY_CLEAN, 'precond - status should be READY_CLEAN');
|
147
|
-
|
147
|
+
|
148
148
|
var recs = rec3.get('fooMany');
|
149
149
|
ok(recs, 'rec3.get(fooMany) should return records');
|
150
150
|
equals(rec3.get('status'), SC.Record.READY_CLEAN, 'getting toMany should not change state');
|
@@ -152,41 +152,41 @@ test("getting toMany relation should not change record state", function() {
|
|
152
152
|
|
153
153
|
test("reading toMany in chained store", function() {
|
154
154
|
var recs1, recs2, store, rec3a;
|
155
|
-
|
155
|
+
|
156
156
|
recs1 = rec3.get('fooMany');
|
157
157
|
store = MyApp.store.chain();
|
158
|
-
|
158
|
+
|
159
159
|
rec3a = store.find(rec3);
|
160
160
|
recs2 = rec3a.get('fooMany');
|
161
|
-
|
161
|
+
|
162
162
|
same(recs2.getEach('storeKey'), recs1.getEach('storeKey'), 'returns arrays from chained and parent should be same');
|
163
163
|
ok(recs2 !== recs1, 'returned arrays should not be same instance');
|
164
|
-
|
164
|
+
|
165
165
|
});
|
166
166
|
|
167
167
|
test("reading a null relation", function() {
|
168
|
-
|
168
|
+
|
169
169
|
// note: rec1 hash has NO array
|
170
170
|
equals(rec.readAttribute('fooMany'), null, 'rec1.fooMany attr should be null');
|
171
|
-
|
171
|
+
|
172
172
|
var ret = rec.get('fooMany');
|
173
|
-
equals(ret.get('length'), 0, 'rec1.get(fooMany).length should be 0');
|
173
|
+
equals(ret.get('length'), 0, 'rec1.get(fooMany).length should be 0');
|
174
174
|
same(ret.getEach('storeKey'), [], 'rec1.get(fooMany) should return empty array');
|
175
175
|
});
|
176
176
|
|
177
177
|
// ..........................................................
|
178
178
|
// WRITING
|
179
|
-
//
|
179
|
+
//
|
180
180
|
|
181
181
|
test("writing to a to-many relationship should update set guids", function() {
|
182
182
|
var rec3 = MyApp.store.find(MyApp.Foo, 3);
|
183
183
|
equals(rec3.get('id'), 3, 'precond - should find record 3');
|
184
184
|
equals(rec3.get('fooMany').objectAt(0), rec, 'should get rec1 instance for rec3.fooMany');
|
185
|
-
|
185
|
+
|
186
186
|
SC.RunLoop.begin();
|
187
187
|
rec3.set('fooMany', [rec2, rec4]);
|
188
188
|
SC.RunLoop.end();
|
189
|
-
|
189
|
+
|
190
190
|
equals(rec3.get('fooMany').objectAt(0), rec2, 'should get rec2 instance for rec3.fooMany');
|
191
191
|
equals(rec3.get('fooMany').objectAt(1), rec4, 'should get rec4 instance for rec3.fooMany');
|
192
192
|
});
|
@@ -207,25 +207,27 @@ test("pushing an object to a to-many relationship attribute should update set gu
|
|
207
207
|
var rec3 = MyApp.store.find(MyApp.Foo, 3);
|
208
208
|
equals(rec3.get('id'), 3, 'precond - should find record 3');
|
209
209
|
equals(rec3.get('fooMany').length(), 2, 'should be 2 foo instances related');
|
210
|
-
|
211
|
-
|
212
|
-
|
210
|
+
|
211
|
+
SC.run(function () {
|
212
|
+
rec3.get('fooMany').pushObject(rec4);
|
213
|
+
});
|
214
|
+
|
213
215
|
equals(rec3.get('fooMany').length(), 3, 'should be 3 foo instances related');
|
214
|
-
|
216
|
+
|
215
217
|
equals(rec3.get('fooMany').objectAt(0), rec, 'should get rec instance for rec3.fooMany');
|
216
218
|
equals(rec3.get('fooMany').objectAt(1), rec2, 'should get rec2 instance for rec3.fooMany');
|
217
219
|
equals(rec3.get('fooMany').objectAt(2), rec4, 'should get rec4 instance for rec3.fooMany');
|
218
220
|
});
|
219
|
-
|
221
|
+
|
220
222
|
test("modifying a toMany array should mark the record as changed", function() {
|
221
223
|
var recs = rec3.get('fooMany');
|
222
224
|
equals(rec3.get('status'), SC.Record.READY_CLEAN, 'precond - rec3.status should be READY_CLEAN');
|
223
225
|
ok(!!rec4, 'precond - rec4 should be defined');
|
224
|
-
|
226
|
+
|
225
227
|
SC.RunLoop.begin();
|
226
228
|
recs.pushObject(rec4);
|
227
229
|
SC.RunLoop.end();
|
228
|
-
|
230
|
+
|
229
231
|
equals(rec3.get('status'), SC.Record.READY_DIRTY, 'record status should have changed to dirty');
|
230
232
|
|
231
233
|
});
|
@@ -233,9 +235,11 @@ test("modifying a toMany array should mark the record as changed", function() {
|
|
233
235
|
test("Modifying a toMany array using replace", function() {
|
234
236
|
var recs = rec.get('barToOne'),
|
235
237
|
objectForRemoval = recs.objectAt(1);
|
236
|
-
|
237
|
-
|
238
|
-
|
238
|
+
|
239
|
+
SC.run(function () {
|
240
|
+
recs.replace(1, 1, null); // the object should be removed
|
241
|
+
});
|
242
|
+
|
239
243
|
ok(objectForRemoval !== recs.objectAt(1), "record should not be present after a replace");
|
240
244
|
equals(bar2.get('fooToOne'), null, "record should have notified attribute of change");
|
241
245
|
});
|
@@ -245,49 +249,75 @@ test("modifying a toMany array within a nested store", function() {
|
|
245
249
|
|
246
250
|
var child = MyApp.store.chain() ; // get a chained store
|
247
251
|
var parentFooMany = rec3.get('fooMany'); // base foo many
|
248
|
-
|
249
|
-
var childRec3 = child.find(rec3);
|
252
|
+
|
253
|
+
var childRec3 = child.find(rec3);
|
250
254
|
var childFooMany = childRec3.get('fooMany'); // get the nested fooMany
|
251
|
-
|
255
|
+
|
252
256
|
// save store keys before modifying for easy testing
|
253
257
|
var expected = parentFooMany.getEach('storeKey');
|
254
|
-
|
258
|
+
|
255
259
|
// now trying modifying...
|
256
260
|
var childRec4 = child.find(rec4);
|
257
261
|
equals(childFooMany.get('length'), 2, 'precond - childFooMany should be like parent');
|
258
|
-
|
262
|
+
|
263
|
+
SC.run(function () {
|
264
|
+
childFooMany.pushObject(childRec4);
|
265
|
+
});
|
259
266
|
equals(childFooMany.get('length'), 3, 'childFooMany should have 1 more item');
|
260
|
-
|
267
|
+
|
261
268
|
SC.RunLoop.end(); // allow notifications to process, if there were any...
|
262
|
-
|
269
|
+
|
263
270
|
same(parentFooMany.getEach('storeKey'), expected, 'parent.fooMany should not have changed yet');
|
264
271
|
equals(rec3.get('status'), SC.Record.READY_CLEAN, 'parent rec3 should still be READY_CLEAN');
|
265
|
-
|
272
|
+
|
266
273
|
expected = childFooMany.getEach('storeKey'); // update for after commit
|
267
274
|
|
268
275
|
SC.RunLoop.begin();
|
269
276
|
child.commitChanges();
|
270
277
|
SC.RunLoop.end();
|
271
|
-
|
278
|
+
|
272
279
|
// NOTE: not getting fooMany from parent again also tests changing an array
|
273
280
|
// underneath. Does it clear caches, etc?
|
274
281
|
equals(parentFooMany.get('length'), 3, 'parent.fooMany length should have changed');
|
275
282
|
same(parentFooMany.getEach('storeKey'), expected, 'parent.fooMany should now have changed form child store');
|
276
283
|
equals(rec3.get('status'), SC.Record.READY_DIRTY, 'parent rec3 should now be READY_DIRTY');
|
277
|
-
|
284
|
+
|
278
285
|
});
|
279
286
|
|
280
287
|
test("should be able to modify an initially empty record", function() {
|
281
|
-
|
288
|
+
|
282
289
|
same(rec.get('fooMany').getEach('storeKey'), [], 'precond - fooMany should be empty');
|
283
|
-
|
290
|
+
SC.run(function () {
|
291
|
+
rec.get('fooMany').pushObject(rec4);
|
292
|
+
});
|
284
293
|
same(rec.get('fooMany').getEach('storeKey'), [rec4.get('storeKey')], 'after edit should have new array');
|
285
294
|
});
|
286
295
|
|
287
296
|
|
297
|
+
test("Adding an unsaved record should throw an Error", function() {
|
298
|
+
var foo;
|
299
|
+
|
300
|
+
SC.run(function () {
|
301
|
+
foo = MyApp.store.createRecord(MyApp.Foo, {
|
302
|
+
firstName: "John",
|
303
|
+
lastName: "Doe",
|
304
|
+
barToMany: ['bar1']
|
305
|
+
});
|
306
|
+
});
|
307
|
+
|
308
|
+
try {
|
309
|
+
SC.run(function () {
|
310
|
+
bar1.get('fooToMany').pushObject(foo);
|
311
|
+
});
|
312
|
+
ok(false, "Attempting to assign an unsaved record resulted in an error.");
|
313
|
+
} catch (x) {
|
314
|
+
ok(true, "Attempting to assign an unsaved record resulted in an error.");
|
315
|
+
}
|
316
|
+
});
|
317
|
+
|
288
318
|
// ..........................................................
|
289
319
|
// MANY-TO-MANY RELATIONSHIPS
|
290
|
-
//
|
320
|
+
//
|
291
321
|
|
292
322
|
function checkAllClean() {
|
293
323
|
SC.A(arguments).forEach(function(r) {
|
@@ -299,38 +329,44 @@ test("removing a record from a many-to-many", function() {
|
|
299
329
|
ok(foo1.get('barToMany').indexOf(bar1) >= 0, 'PRECOND - foo1.barToMany should contain bar1');
|
300
330
|
ok(bar1.get('fooToMany').indexOf(foo1) >= 0, 'PRECOND - bar1.fooToMany should contain foo1');
|
301
331
|
checkAllClean(foo1, bar1);
|
302
|
-
|
303
|
-
|
332
|
+
|
333
|
+
SC.run(function () {
|
334
|
+
foo1.get('barToMany').removeObject(bar1);
|
335
|
+
});
|
304
336
|
|
305
337
|
ok(foo1.get('barToMany').indexOf(bar1) < 0, 'foo1.barToMany should NOT contain bar1');
|
306
338
|
ok(bar1.get('fooToMany').indexOf(foo1) < 0, 'bar1.fooToMany should NOT contain foo1');
|
307
339
|
|
308
340
|
equals(foo1.get('status'), SC.Record.READY_DIRTY, 'foo1.status should be READY_DIRTY');
|
309
341
|
equals(bar1.get('status'), SC.Record.READY_CLEAN, 'bar1.status should be READY_CLEAN');
|
310
|
-
|
342
|
+
|
311
343
|
});
|
312
344
|
|
313
345
|
test("removing a record from a many-to-many; other side", function() {
|
314
346
|
ok(foo1.get('barToMany').indexOf(bar1) >= 0, 'PRECOND - foo1.barToMany should contain bar1');
|
315
347
|
ok(bar1.get('fooToMany').indexOf(foo1) >= 0, 'PRECOND - bar1.fooToMany should contain foo1');
|
316
348
|
checkAllClean(foo1, bar1);
|
317
|
-
|
318
|
-
|
349
|
+
|
350
|
+
SC.run(function () {
|
351
|
+
bar1.get('fooToMany').removeObject(foo1);
|
352
|
+
});
|
319
353
|
|
320
354
|
ok(foo1.get('barToMany').indexOf(bar1) < 0, 'foo1.barToMany should NOT contain bar1');
|
321
355
|
ok(bar1.get('fooToMany').indexOf(foo1) < 0, 'bar1.fooToMany should NOT contain foo1');
|
322
356
|
|
323
357
|
equals(foo1.get('status'), SC.Record.READY_DIRTY, 'foo1.status should be READY_DIRTY');
|
324
358
|
equals(bar1.get('status'), SC.Record.READY_CLEAN, 'bar1.status should be READY_CLEAN');
|
325
|
-
|
359
|
+
|
326
360
|
});
|
327
361
|
|
328
362
|
test("adding a record to a many-to-many; bar side", function() {
|
329
363
|
ok(foo2.get('barToMany').indexOf(bar3) < 0, 'PRECOND - foo1.barToMany should NOT contain bar1');
|
330
364
|
ok(bar3.get('fooToMany').indexOf(foo2) < 0, 'PRECOND - bar3.fooToMany should NOT contain foo1');
|
331
365
|
checkAllClean(foo2, bar3);
|
332
|
-
|
333
|
-
|
366
|
+
|
367
|
+
SC.run(function () {
|
368
|
+
bar3.get('fooToMany').pushObject(foo2);
|
369
|
+
});
|
334
370
|
|
335
371
|
// v-- since bar3 is added through inverse, it should follow orderBy
|
336
372
|
equals(foo2.get('barToMany').indexOf(bar3), 1, 'foo1.barToMany should contain bar1');
|
@@ -345,8 +381,10 @@ test("adding a record to a many-to-many; foo side", function() {
|
|
345
381
|
ok(foo2.get('barToMany').indexOf(bar3) < 0, 'PRECOND - foo1.barToMany should NOT contain bar3');
|
346
382
|
ok(bar3.get('fooToMany').indexOf(foo2) < 0, 'PRECOND - bar3.fooToMany should NOT contain foo1');
|
347
383
|
checkAllClean(foo2, bar3);
|
348
|
-
|
349
|
-
|
384
|
+
|
385
|
+
SC.run(function () {
|
386
|
+
foo2.get('barToMany').pushObject(bar3);
|
387
|
+
});
|
350
388
|
|
351
389
|
ok(foo2.get('barToMany').indexOf(bar3) >= 0, 'foo1.barToMany should contain bar3');
|
352
390
|
ok(bar3.get('fooToMany').indexOf(foo2) >= 0, 'bar1.fooToMany should contain foo3');
|
@@ -357,21 +395,23 @@ test("adding a record to a many-to-many; foo side", function() {
|
|
357
395
|
|
358
396
|
// ..........................................................
|
359
397
|
// ONE-TO-MANY RELATIONSHIPS
|
360
|
-
//
|
398
|
+
//
|
361
399
|
|
362
400
|
test("removing a record from a one-to-many", function() {
|
363
401
|
ok(foo1.get('barToOne').indexOf(bar1) >= 0, 'PRECOND - foo1.barToOne should contain bar1');
|
364
402
|
equals(bar1.get('fooToOne'), foo1, 'PRECOND - bar1.fooToOne should eq foo1');
|
365
403
|
checkAllClean(foo1, bar1);
|
366
|
-
|
367
|
-
|
404
|
+
|
405
|
+
SC.run(function () {
|
406
|
+
foo1.get('barToOne').removeObject(bar1);
|
407
|
+
});
|
368
408
|
|
369
409
|
ok(foo1.get('barToOne').indexOf(bar1) < 0, 'foo1.barToOne should NOT contain bar1');
|
370
410
|
equals(bar1.get('fooToOne'), null, 'bar1.fooToOne should eq null');
|
371
411
|
|
372
412
|
equals(foo1.get('status'), SC.Record.READY_CLEAN, 'foo1.status should be READY_CLEAN');
|
373
413
|
equals(bar1.get('status'), SC.Record.READY_DIRTY, 'bar1.status should be READY_DIRTY');
|
374
|
-
|
414
|
+
|
375
415
|
});
|
376
416
|
|
377
417
|
|
@@ -379,15 +419,17 @@ test("removing a record from a one-to-many; other-side", function() {
|
|
379
419
|
ok(foo1.get('barToOne').indexOf(bar1) >= 0, 'PRECOND - foo1.barToOne should contain bar1');
|
380
420
|
equals(bar1.get('fooToOne'), foo1, 'PRECOND - bar1.fooToOne should eq foo1');
|
381
421
|
checkAllClean(foo1, bar1);
|
382
|
-
|
383
|
-
|
422
|
+
|
423
|
+
SC.run(function () {
|
424
|
+
bar1.set('fooToOne', null);
|
425
|
+
});
|
384
426
|
|
385
427
|
ok(foo1.get('barToOne').indexOf(bar1) < 0, 'foo1.barToOne should NOT contain bar1');
|
386
428
|
equals(bar1.get('fooToOne'), null, 'bar1.fooToOne should eq null');
|
387
429
|
|
388
430
|
equals(foo1.get('status'), SC.Record.READY_CLEAN, 'foo1.status should be READY_CLEAN');
|
389
431
|
equals(bar1.get('status'), SC.Record.READY_DIRTY, 'bar1.status should be READY_DIRTY');
|
390
|
-
|
432
|
+
|
391
433
|
});
|
392
434
|
|
393
435
|
|
@@ -395,15 +437,17 @@ test("add a record to a one-to-many; many-side", function() {
|
|
395
437
|
ok(foo1.get('barToOne').indexOf(bar3) < 0, 'PRECOND - foo1.barToOne should NOT contain bar3');
|
396
438
|
equals(bar3.get('fooToOne'), null, 'PRECOND - bar3.fooToOne should eq null');
|
397
439
|
checkAllClean(foo1, bar1);
|
398
|
-
|
399
|
-
|
440
|
+
|
441
|
+
SC.run(function () {
|
442
|
+
foo1.get('barToOne').pushObject(bar3);
|
443
|
+
});
|
400
444
|
|
401
445
|
ok(foo1.get('barToOne').indexOf(bar3) >= 0, 'foo1.barToOne should contain bar3');
|
402
446
|
equals(bar3.get('fooToOne'), foo1, 'bar3.fooToOne should eq foo1');
|
403
447
|
|
404
448
|
equals(foo1.get('status'), SC.Record.READY_CLEAN, 'foo1.status should be READY_CLEAN');
|
405
449
|
equals(bar3.get('status'), SC.Record.READY_DIRTY, 'bar3.status should be READY_DIRTY');
|
406
|
-
|
450
|
+
|
407
451
|
});
|
408
452
|
|
409
453
|
|
@@ -411,13 +455,15 @@ test("add a record to a one-to-many; one-side", function() {
|
|
411
455
|
ok(foo1.get('barToOne').indexOf(bar3) < 0, 'PRECOND - foo1.barToOne should NOT contain bar3');
|
412
456
|
equals(bar3.get('fooToOne'), null, 'PRECOND - bar3.fooToOne should eq null');
|
413
457
|
checkAllClean(foo1, bar1);
|
414
|
-
|
415
|
-
|
458
|
+
|
459
|
+
SC.run(function () {
|
460
|
+
bar3.set('fooToOne', foo1);
|
461
|
+
});
|
416
462
|
|
417
463
|
ok(foo1.get('barToOne').indexOf(bar3) >= 0, 'foo1.barToOne should contain bar3');
|
418
464
|
equals(bar3.get('fooToOne'), foo1, 'bar3.fooToOne should eq foo1');
|
419
465
|
|
420
466
|
equals(foo1.get('status'), SC.Record.READY_CLEAN, 'foo1.status should be READY_CLEAN');
|
421
467
|
equals(bar3.get('status'), SC.Record.READY_DIRTY, 'bar3.status should be READY_DIRTY');
|
422
|
-
|
468
|
+
|
423
469
|
});
|
@@ -297,6 +297,18 @@ test("adding toOne pointing to non existing class should throw error", function(
|
|
297
297
|
same(message, 'Attempted to create toOne attribute with undefined recordType. Did you forget to sc_require a dependency?');
|
298
298
|
});
|
299
299
|
|
300
|
+
test("Adding an unsaved record should throw an Error", function() {
|
301
|
+
var bar1 = MyApp.store.find(MyApp.Bar, 'bar1'),
|
302
|
+
foo = MyApp.store.createRecord(MyApp.Foo, {});
|
303
|
+
|
304
|
+
try {
|
305
|
+
bar1.set('foo', foo);
|
306
|
+
ok(false, "Attempting to assign an unsaved record resulted in an error.");
|
307
|
+
} catch (x) {
|
308
|
+
ok(true, "Attempting to assign an unsaved record resulted in an error.");
|
309
|
+
}
|
310
|
+
});
|
311
|
+
|
300
312
|
test("adding toMany pointing to non existing class should throw error", function() {
|
301
313
|
var message;
|
302
314
|
try {
|
@@ -405,6 +405,11 @@ SC.PickerPane = SC.PalettePane.extend(
|
|
405
405
|
*/
|
406
406
|
windowPadding: null,
|
407
407
|
|
408
|
+
/* @private Observe the frame for changes so that we can reposition if necessary. */
|
409
|
+
borderFrameDidChange: function () {
|
410
|
+
this.positionPane(true);
|
411
|
+
},
|
412
|
+
|
408
413
|
/**
|
409
414
|
Displays a new picker pane.
|
410
415
|
|
@@ -430,6 +435,10 @@ SC.PickerPane = SC.PalettePane.extend(
|
|
430
435
|
this.endPropertyChanges();
|
431
436
|
this.positionPane();
|
432
437
|
this._hideOverflow();
|
438
|
+
|
439
|
+
// Start observing the frame for changes.
|
440
|
+
this.addObserver('borderFrame', this.borderFrameDidChange);
|
441
|
+
|
433
442
|
return this.append();
|
434
443
|
},
|
435
444
|
|
@@ -443,11 +452,11 @@ SC.PickerPane = SC.PalettePane.extend(
|
|
443
452
|
useAnchorCached = useAnchorCached && this.get('anchorCached');
|
444
453
|
|
445
454
|
var anchor = useAnchorCached ? this.get('anchorCached') : this.get('anchorElement'),
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
455
|
+
frame = this.get('borderFrame'),
|
456
|
+
preferType = this.get('preferType'),
|
457
|
+
preferMatrix = this.get('preferMatrix'),
|
458
|
+
layout = this.get('layout'),
|
459
|
+
origin;
|
451
460
|
|
452
461
|
// usually an anchorElement will be passed. The ideal position is just
|
453
462
|
// below the anchor + default or custom offset according to preferType.
|
@@ -492,7 +501,6 @@ SC.PickerPane = SC.PalettePane.extend(
|
|
492
501
|
frame.halfHeight = parseInt(frame.height * 0.5, 0);
|
493
502
|
|
494
503
|
origin = this.fitPositionToScreen(origin, frame, anchor);
|
495
|
-
|
496
504
|
this.adjust({
|
497
505
|
width: origin.width,
|
498
506
|
height: origin.height,
|
@@ -1083,6 +1091,10 @@ SC.PickerPane = SC.PalettePane.extend(
|
|
1083
1091
|
this._withdrawOverflowRequest();
|
1084
1092
|
}
|
1085
1093
|
this._removeScrollObservers();
|
1094
|
+
|
1095
|
+
// Stop observing the frame for changes.
|
1096
|
+
this.removeObserver('borderFrame', this.borderFrameDidChange);
|
1097
|
+
|
1086
1098
|
return sc_super();
|
1087
1099
|
},
|
1088
1100
|
|