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
@@ -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
|
|