sproutcore 1.10.1 → 1.10.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -29,12 +29,21 @@ SC.CoreView.mixin(
|
|
29
29
|
|
30
30
|
/**
|
31
31
|
The view is enabled itself, but is effectively disabled in the pane due to
|
32
|
-
a disabled
|
32
|
+
a disabled ancestor.
|
33
33
|
|
34
34
|
@static
|
35
35
|
@constant
|
36
36
|
*/
|
37
|
-
DISABLED_BY_PARENT: 0x12 // 18
|
37
|
+
DISABLED_BY_PARENT: 0x12, // 18
|
38
|
+
|
39
|
+
/**
|
40
|
+
The view is disabled itself and is also disabled in the pane due to
|
41
|
+
a disabled ancestor.
|
42
|
+
|
43
|
+
@static
|
44
|
+
@constant
|
45
|
+
*/
|
46
|
+
DISABLED_AND_BY_PARENT: 0x13 // 19
|
38
47
|
|
39
48
|
});
|
40
49
|
|
@@ -112,11 +121,16 @@ SC.View.reopen(
|
|
112
121
|
|
113
122
|
/** @private */
|
114
123
|
_doEnable: function () {
|
115
|
-
var handled = true
|
124
|
+
var handled = true,
|
125
|
+
enabledState = this.get('enabledState');
|
116
126
|
|
117
|
-
if (
|
127
|
+
if (enabledState === SC.CoreView.DISABLED) {
|
128
|
+
// If the view itself is disabled, then we can enable it.
|
118
129
|
this._callOnChildViews('_parentDidEnableInPane');
|
119
130
|
this._gotoEnabledState();
|
131
|
+
} else if (enabledState === SC.CoreView.DISABLED_AND_BY_PARENT) {
|
132
|
+
// The view is no longer disabled itself, but still disabled by an ancestor.
|
133
|
+
this._gotoDisabledByParentState();
|
120
134
|
} else {
|
121
135
|
handled = false;
|
122
136
|
}
|
@@ -126,15 +140,20 @@ SC.View.reopen(
|
|
126
140
|
|
127
141
|
/** @private */
|
128
142
|
_doDisable: function () {
|
129
|
-
var handled = true
|
143
|
+
var handled = true,
|
144
|
+
enabledState = this.get('enabledState');
|
130
145
|
|
131
|
-
|
146
|
+
// If the view is not itself disabled, then we can disable it.
|
147
|
+
if (enabledState === SC.CoreView.ENABLED) {
|
132
148
|
if (this.get('isFirstResponder')) {
|
133
149
|
this.resignFirstResponder();
|
134
150
|
}
|
135
151
|
|
136
152
|
this._callOnChildViews('_parentDidDisableInPane');
|
137
153
|
this._gotoDisabledState();
|
154
|
+
} else if (enabledState === SC.CoreView.DISABLED_BY_PARENT) {
|
155
|
+
// The view is now disabled itself and disabled by an ancestor.
|
156
|
+
this._gotoDisabledAndByParentState();
|
138
157
|
} else {
|
139
158
|
handled = false;
|
140
159
|
}
|
@@ -146,6 +165,14 @@ SC.View.reopen(
|
|
146
165
|
// Methods
|
147
166
|
//
|
148
167
|
|
168
|
+
/** @private */
|
169
|
+
init: function (original) {
|
170
|
+
original();
|
171
|
+
|
172
|
+
// If the view is pre-configured as disabled, then go to the proper initial state.
|
173
|
+
if (!this.get('isEnabled')) { this._doDisable(); }
|
174
|
+
}.enhance(),
|
175
|
+
|
149
176
|
/** @private
|
150
177
|
Observes the isEnabled property and resigns first responder if set to NO.
|
151
178
|
This will avoid cases where, for example, a disabled text field retains
|
@@ -206,10 +233,18 @@ SC.View.reopen(
|
|
206
233
|
|
207
234
|
/** @private */
|
208
235
|
_parentDidEnableInPane: function () {
|
209
|
-
var
|
236
|
+
var enabledState = this.get('enabledState');
|
210
237
|
|
211
|
-
if (
|
212
|
-
|
238
|
+
if (this.get('shouldInheritEnabled')) {
|
239
|
+
|
240
|
+
if (enabledState === SC.CoreView.DISABLED_BY_PARENT) { // Was enabled before.
|
241
|
+
this._gotoEnabledState();
|
242
|
+
} else if (enabledState === SC.CoreView.DISABLED_AND_BY_PARENT) { // Was disabled before.
|
243
|
+
this._gotoDisabledState();
|
244
|
+
|
245
|
+
// There's no need to continue to further child views.
|
246
|
+
return false;
|
247
|
+
}
|
213
248
|
} else {
|
214
249
|
// There's no need to continue to further child views.
|
215
250
|
return false;
|
@@ -218,10 +253,19 @@ SC.View.reopen(
|
|
218
253
|
|
219
254
|
/** @private */
|
220
255
|
_parentDidDisableInPane: function () {
|
221
|
-
var
|
256
|
+
var enabledState = this.get('enabledState');
|
257
|
+
|
258
|
+
if (this.get('shouldInheritEnabled')) {
|
222
259
|
|
223
|
-
|
224
|
-
|
260
|
+
if (enabledState === SC.CoreView.ENABLED) { // Was enabled.
|
261
|
+
this._gotoDisabledByParentState();
|
262
|
+
} else if (enabledState === SC.CoreView.DISABLED) { // Was disabled.
|
263
|
+
this._gotoDisabledAndByParentState();
|
264
|
+
} else { // Was already disabled by ancestor.
|
265
|
+
|
266
|
+
// There's no need to continue to further child views.
|
267
|
+
return false;
|
268
|
+
}
|
225
269
|
} else {
|
226
270
|
// There's no need to continue to further child views.
|
227
271
|
return false;
|
@@ -249,7 +293,13 @@ SC.View.reopen(
|
|
249
293
|
},
|
250
294
|
|
251
295
|
/** @private */
|
252
|
-
|
296
|
+
_gotoDisabledAndByParentState: function () {
|
297
|
+
// Update the state.
|
298
|
+
this.set('enabledState', SC.CoreView.DISABLED_AND_BY_PARENT);
|
299
|
+
},
|
300
|
+
|
301
|
+
/** @private */
|
302
|
+
_gotoDisabledByParentState: function () {
|
253
303
|
// Update the state.
|
254
304
|
this.set('enabledState', SC.CoreView.DISABLED_BY_PARENT);
|
255
305
|
}
|
@@ -42,13 +42,13 @@ SC.Record = SC.Object.extend(
|
|
42
42
|
|
43
43
|
//@if(debug)
|
44
44
|
/* BEGIN DEBUG ONLY PROPERTIES AND METHODS */
|
45
|
+
|
45
46
|
/** @private
|
46
47
|
Creates string representation of record, with status.
|
47
48
|
|
48
49
|
@returns {String}
|
49
50
|
*/
|
50
|
-
|
51
|
-
toString: function() {
|
51
|
+
toString: function () {
|
52
52
|
// We won't use 'readOnlyAttributes' here because accessing them directly
|
53
53
|
// avoids a SC.clone() -- we'll be careful not to edit anything.
|
54
54
|
var attrs = this.get('store').readDataHash(this.get('storeKey'));
|
@@ -61,7 +61,7 @@ SC.Record = SC.Object.extend(
|
|
61
61
|
@returns {String}
|
62
62
|
*/
|
63
63
|
|
64
|
-
statusString: function() {
|
64
|
+
statusString: function () {
|
65
65
|
var ret = [], status = this.get('status');
|
66
66
|
|
67
67
|
for(var prop in SC.Record) {
|
@@ -59,10 +59,16 @@ SC.SingleAttribute = SC.RecordAttribute.extend(
|
|
59
59
|
if (newRec !== undefined && this.get('isEditable')) {
|
60
60
|
|
61
61
|
// can only take other records or null
|
62
|
+
//@if(debug)
|
62
63
|
if (newRec && !SC.kindOf(newRec, SC.Record)) {
|
63
|
-
throw new Error("%@ is not an instance of SC.Record".fmt(newRec));
|
64
|
+
throw new Error("Developer Error: %@ is not an instance of SC.Record.".fmt(newRec));
|
64
65
|
}
|
65
66
|
|
67
|
+
if (newRec && SC.none(newRec.get('id'))) {
|
68
|
+
throw new Error("Developer Error: Attempted to add a record without a primary key to a to-one relationship. Relationships require that the id always be specified. The record, \"%@\", must be assigned an id (i.e. be saved) before it can be used in the '%@' relationship.".fmt(newRec, attrKey));
|
69
|
+
}
|
70
|
+
//@endif
|
71
|
+
|
66
72
|
inverseKey = this.get('inverse');
|
67
73
|
if (inverseKey) oldRec = this._scsa_call(record, key);
|
68
74
|
|
@@ -23,6 +23,20 @@
|
|
23
23
|
SC.ManyArray = SC.Object.extend(SC.Enumerable, SC.Array,
|
24
24
|
/** @scope SC.ManyArray.prototype */ {
|
25
25
|
|
26
|
+
//@if(debug)
|
27
|
+
/* BEGIN DEBUG ONLY PROPERTIES AND METHODS */
|
28
|
+
|
29
|
+
/* @private */
|
30
|
+
toString: function () {
|
31
|
+
var readOnlyStoreIds = this.get('readOnlyStoreIds'),
|
32
|
+
length = this.get('length');
|
33
|
+
|
34
|
+
return "%@({\n ids: [%@],\n length: %@,\n … })".fmt(this.constructor.toString(), readOnlyStoreIds, length);
|
35
|
+
},
|
36
|
+
|
37
|
+
/* END DEBUG ONLY PROPERTIES AND METHODS */
|
38
|
+
//@endif
|
39
|
+
|
26
40
|
/**
|
27
41
|
`recordType` will tell what type to transform the record to when
|
28
42
|
materializing the record.
|
@@ -222,10 +236,11 @@ SC.ManyArray = SC.Object.extend(SC.Enumerable, SC.Array,
|
|
222
236
|
records, which can be converted to `storeId`s.
|
223
237
|
*/
|
224
238
|
replace: function(idx, amt, recs) {
|
225
|
-
|
239
|
+
//@if(debug)
|
226
240
|
if (!this.get('isEditable')) {
|
227
|
-
throw new Error("%@.%@[] is not editable".fmt(this.get('record'), this.get('propertyName')));
|
241
|
+
throw new Error("Developer Error: %@.%@[] is not editable.".fmt(this.get('record'), this.get('propertyName')));
|
228
242
|
}
|
243
|
+
//@endif
|
229
244
|
|
230
245
|
var storeIds = this.get('editableStoreIds'),
|
231
246
|
len = recs ? (recs.get ? recs.get('length') : recs.length) : 0,
|
@@ -235,12 +250,20 @@ SC.ManyArray = SC.Object.extend(SC.Enumerable, SC.Array,
|
|
235
250
|
|
236
251
|
// map to store keys
|
237
252
|
ids = [] ;
|
238
|
-
for(i=0;i<len;i++)
|
253
|
+
for(i=0;i<len;i++) {
|
254
|
+
//@if(debug)
|
255
|
+
if (SC.none(recs.objectAt(i).get('id'))) {
|
256
|
+
throw new Error("Developer Error: Attempted to add a record without a primary key to a to-many relationship. Relationships require that the id always be specified. The record, \"%@\", must be assigned an id (i.e. be saved) before it can be used in the '%@' relationship.".fmt(recs.objectAt(i), pname));
|
257
|
+
}
|
258
|
+
//@endif
|
259
|
+
|
260
|
+
ids[i] = recs.objectAt(i).get('id');
|
261
|
+
}
|
239
262
|
|
240
263
|
// if we have an inverse - collect the list of records we are about to
|
241
264
|
// remove
|
242
265
|
inverse = this.get('inverse');
|
243
|
-
if (inverse && amt>0) {
|
266
|
+
if (inverse && amt > 0) {
|
244
267
|
toRemove = SC.ManyArray._toRemove;
|
245
268
|
if (toRemove) SC.ManyArray._toRemove = null; // reuse if possible
|
246
269
|
else toRemove = [];
|
@@ -456,4 +479,4 @@ SC.ManyArray = SC.Object.extend(SC.Enumerable, SC.Array,
|
|
456
479
|
this.recordPropertyDidChange();
|
457
480
|
}
|
458
481
|
|
459
|
-
})
|
482
|
+
});
|
@@ -139,6 +139,21 @@ sc_require('models/record');
|
|
139
139
|
SC.Query = SC.Object.extend(SC.Copyable, SC.Freezable,
|
140
140
|
/** @scope SC.Query.prototype */ {
|
141
141
|
|
142
|
+
//@if(debug)
|
143
|
+
/* BEGIN DEBUG ONLY PROPERTIES AND METHODS */
|
144
|
+
|
145
|
+
/* @private */
|
146
|
+
toString: function () {
|
147
|
+
var conditions = this.get('conditions'),
|
148
|
+
location = this.get('location'),
|
149
|
+
parameters = this.get('parameters');
|
150
|
+
|
151
|
+
return "%@.%@({ conditions: '%@', parameters: %@, … })".fmt(this.constructor.toString(), location, conditions, SC.inspect(parameters));
|
152
|
+
},
|
153
|
+
|
154
|
+
/* END DEBUG ONLY PROPERTIES AND METHODS */
|
155
|
+
//@endif
|
156
|
+
|
142
157
|
// ..........................................................
|
143
158
|
// PROPERTIES
|
144
159
|
//
|
@@ -56,6 +56,35 @@ sc_require('models/record');
|
|
56
56
|
SC.RecordArray = SC.Object.extend(SC.Enumerable, SC.Array,
|
57
57
|
/** @scope SC.RecordArray.prototype */ {
|
58
58
|
|
59
|
+
//@if(debug)
|
60
|
+
/* BEGIN DEBUG ONLY PROPERTIES AND METHODS */
|
61
|
+
|
62
|
+
/* @private */
|
63
|
+
toString: function () {
|
64
|
+
var statusString = this.statusString(),
|
65
|
+
storeKeys = this.get('storeKeys'),
|
66
|
+
query = this.get('query'),
|
67
|
+
length = this.get('length');
|
68
|
+
|
69
|
+
return "%@({\n query: %@,\n storeKeys: [%@],\n length: %@,\n … }) %@".fmt(this.constructor.toString(), query, storeKeys, length, statusString);
|
70
|
+
},
|
71
|
+
|
72
|
+
/** @private */
|
73
|
+
statusString: function() {
|
74
|
+
var ret = [], status = this.get('status');
|
75
|
+
|
76
|
+
for (var prop in SC.Record) {
|
77
|
+
if (prop.match(/[A-Z_]$/) && SC.Record[prop] === status) {
|
78
|
+
ret.push(prop);
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
return ret.join(" ");
|
83
|
+
},
|
84
|
+
|
85
|
+
/* END DEBUG ONLY PROPERTIES AND METHODS */
|
86
|
+
//@endif
|
87
|
+
|
59
88
|
/**
|
60
89
|
The store that owns this record array. All record arrays must have a
|
61
90
|
store to function properly.
|
@@ -676,9 +705,7 @@ SC.RecordArray = SC.Object.extend(SC.Enumerable, SC.Array,
|
|
676
705
|
_storeKeysDidChange: function() {
|
677
706
|
var storeKeys = this.get('storeKeys');
|
678
707
|
|
679
|
-
var prev = this._prevStoreKeys, oldLen, newLen
|
680
|
-
f = this._storeKeysContentDidChange,
|
681
|
-
fs = this._storeKeysStateDidChange;
|
708
|
+
var prev = this._prevStoreKeys, oldLen, newLen;
|
682
709
|
|
683
710
|
if (storeKeys === prev) { return; } // nothing to do
|
684
711
|
|
@@ -1057,7 +1057,11 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
|
|
1057
1057
|
@returns {SC.Record} Returns a record instance.
|
1058
1058
|
*/
|
1059
1059
|
materializeRecord: function (storeKey) {
|
1060
|
-
var records = this.records,
|
1060
|
+
var records = this.records,
|
1061
|
+
//@if(debug)
|
1062
|
+
updatingRecords = this.updatingRecords,
|
1063
|
+
//@endif
|
1064
|
+
ret, recordType, attrs;
|
1061
1065
|
|
1062
1066
|
// look up in cached records
|
1063
1067
|
if (!records) records = this.records = {}; // load cached records
|
@@ -1071,8 +1075,26 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
|
|
1071
1075
|
attrs = this._TMP_REC_ATTRS ;
|
1072
1076
|
attrs.storeKey = storeKey ;
|
1073
1077
|
attrs.store = this ;
|
1078
|
+
|
1079
|
+
//@if(debug)
|
1080
|
+
// Add some developer support to prevent a tough to diagnose bug that if
|
1081
|
+
// materializeRecord is called during the creation of a record, the store
|
1082
|
+
// will inadvertently create a duplicate record instance not because the
|
1083
|
+
// actual instance won't have been cached to this.records yet.
|
1084
|
+
if (!this.updatingRecords) { updatingRecords = this.updatingRecords = {}; }
|
1085
|
+
if (updatingRecords[storeKey]) {
|
1086
|
+
throw new Error("Developer Error: The record of type, %@, with storeKey, %@, was materialized a second time before the first call had finished. This will result in two separate instances of the same object being created and should be fixed. A likely cause is using `.observes` code in the record class, which can cause the record to be retrieved somehow while it is still being created.".fmt(recordType, storeKey));
|
1087
|
+
}
|
1088
|
+
|
1089
|
+
updatingRecords[storeKey] = storeKey;
|
1090
|
+
//@endif
|
1091
|
+
|
1074
1092
|
ret = records[storeKey] = recordType.create(attrs);
|
1075
1093
|
|
1094
|
+
//@if(debug)
|
1095
|
+
updatingRecords[storeKey] = null;
|
1096
|
+
//@endif
|
1097
|
+
|
1076
1098
|
return ret ;
|
1077
1099
|
},
|
1078
1100
|
|