sproutcore 1.10.0 → 1.10.1
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/VERSION.yml +1 -1
- data/bin/sc-phantom +13 -0
- data/lib/Buildfile +3 -0
- data/lib/buildtasks/manifest.rake +3 -0
- data/lib/frameworks/sproutcore/CHANGELOG.md +24 -1
- data/lib/frameworks/sproutcore/frameworks/bootstrap/system/browser.js +1 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/root_responder.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/designer/views/designer_drop_target.js +1 -2
- data/lib/frameworks/sproutcore/frameworks/designer/views/high_light.js +1 -2
- data/lib/frameworks/sproutcore/frameworks/designer/views/page_item_view.js +1 -2
- data/lib/frameworks/sproutcore/frameworks/designer/views/selection_handles.js +1 -2
- data/lib/frameworks/sproutcore/frameworks/desktop/panes/menu.js +4 -3
- data/lib/frameworks/sproutcore/frameworks/desktop/resources/progress.css +4 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/system/drag.js +44 -35
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/menu/ui.js +167 -91
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/collection/touch.js +215 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/grid/drag_and_drop.js +7 -2
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/list/drag_and_drop.js +7 -1
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/views/stacked/ui_comments.js +26 -24
- data/lib/frameworks/sproutcore/frameworks/desktop/views/collection.js +9 -18
- data/lib/frameworks/sproutcore/frameworks/desktop/views/grid.js +25 -20
- data/lib/frameworks/sproutcore/frameworks/desktop/views/list.js +29 -29
- data/lib/frameworks/sproutcore/frameworks/desktop/views/menu_item.js +107 -106
- data/lib/frameworks/sproutcore/frameworks/desktop/views/menu_scroll.js +120 -134
- data/lib/frameworks/sproutcore/frameworks/desktop/views/scroll.js +14 -7
- data/lib/frameworks/sproutcore/frameworks/desktop/views/stacked.js +2 -1
- data/lib/frameworks/sproutcore/frameworks/foundation/mixins/content_value_support.js +4 -4
- data/lib/frameworks/sproutcore/frameworks/foundation/system/module.js +197 -196
- data/lib/frameworks/sproutcore/frameworks/foundation/views/inline_text_field.js +7 -0
- data/lib/frameworks/sproutcore/frameworks/routing/system/routes.js +22 -10
- data/lib/frameworks/sproutcore/frameworks/routing/tests/system/routes.js +43 -0
- data/lib/frameworks/sproutcore/frameworks/runtime/core.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/runtime/system/object.js +2 -3
- data/lib/frameworks/sproutcore/frameworks/runtime/system/run_loop.js +14 -14
- data/lib/frameworks/sproutcore/frameworks/statechart/system/statechart.js +90 -79
- data/lib/frameworks/sproutcore/frameworks/statechart/tests/event_handling/advanced/event_queuing.js +104 -0
- data/lib/frameworks/sproutcore/frameworks/table/views/table.js +3 -0
- data/lib/frameworks/sproutcore/frameworks/template_view/handlebars.js +2 -1
- data/lib/frameworks/sproutcore/themes/ace/resources/collection/normal/grid.css +17 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/menu/menu.css +1 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/menu/menu.png +0 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/menu/menu@2x.png +0 -0
- data/lib/frameworks/sproutcore/themes/ace/resources/panel/panel.css +2 -2
- data/lib/frameworks/sproutcore/themes/empty_theme/theme.js +1 -1
- data/lib/sproutcore/tools.rb +2 -1
- data/lib/sproutcore/tools/phantom.rb +36 -0
- data/sproutcore.gemspec +1 -1
- data/vendor/chance/lib/chance/instance.rb +5 -2
- metadata +11 -4
@@ -107,6 +107,13 @@ SC.InlineTextFieldView = SC.TextFieldView.extend(SC.InlineEditor,
|
|
107
107
|
*/
|
108
108
|
layout: { height: 0, width: 0 },
|
109
109
|
|
110
|
+
/*
|
111
|
+
@private
|
112
|
+
|
113
|
+
Prevents the view from taking part in child view layout plugins.
|
114
|
+
*/
|
115
|
+
useAbsoluteLayout: YES,
|
116
|
+
|
110
117
|
/*
|
111
118
|
* @private
|
112
119
|
* @method
|
@@ -198,7 +198,18 @@ SC.routes = SC.Object.create(
|
|
198
198
|
@type {String}
|
199
199
|
*/
|
200
200
|
location: function(key, value) {
|
201
|
+
var lsk;
|
201
202
|
this._skipRoute = NO;
|
203
|
+
if (value !== undefined) {
|
204
|
+
// The 'location' and 'informLocation' properties essentially
|
205
|
+
// represent a single property, but with different behavior
|
206
|
+
// when setting the value. Because of this, we manually
|
207
|
+
// update the cached value for the opposite property to
|
208
|
+
// ensure they remain in sync. You shouldn't do this in
|
209
|
+
// your own code unless you REALLY know what you are doing.
|
210
|
+
lsk = this.informLocation.lastSetValueKey;
|
211
|
+
if (lsk && this._kvo_cache) this._kvo_cache[lsk] = value;
|
212
|
+
}
|
202
213
|
return this._extractLocation(key, value);
|
203
214
|
}.property(),
|
204
215
|
|
@@ -207,17 +218,18 @@ SC.routes = SC.Object.create(
|
|
207
218
|
you want to just change the location w/out triggering the routes
|
208
219
|
*/
|
209
220
|
informLocation: function(key, value){
|
221
|
+
var lsk;
|
210
222
|
this._skipRoute = YES;
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
223
|
+
if (value !== undefined) {
|
224
|
+
// The 'location' and 'informLocation' properties essentially
|
225
|
+
// represent a single property, but with different behavior
|
226
|
+
// when setting the value. Because of this, we manually
|
227
|
+
// update the cached value for the opposite property to
|
228
|
+
// ensure they remain in sync. You shouldn't do this in
|
229
|
+
// your own code unless you REALLY know what you are doing.
|
230
|
+
lsk = this.location.lastSetValueKey;
|
231
|
+
if (lsk && this._kvo_cache) this._kvo_cache[lsk] = value;
|
232
|
+
}
|
221
233
|
return this._extractLocation(key, value);
|
222
234
|
}.property(),
|
223
235
|
|
@@ -150,6 +150,49 @@ test('Already escaped route', function() {
|
|
150
150
|
routeWorks('%C3%A9%C3%A0%20%C3%A7%C3%B9%20%C3%9F%E2%82%AC', 'already escaped');
|
151
151
|
});
|
152
152
|
|
153
|
+
module('SC.routes informLocation', {
|
154
|
+
|
155
|
+
teardown: function() {
|
156
|
+
SC.routes.set('informLocation', null);
|
157
|
+
}
|
158
|
+
|
159
|
+
});
|
160
|
+
|
161
|
+
test('informLocation updates location', function() {
|
162
|
+
SC.routes.set('informLocation', 'simple');
|
163
|
+
stop();
|
164
|
+
|
165
|
+
setTimeout(function() {
|
166
|
+
equals(SC.routes.get('location'), 'simple');
|
167
|
+
start();
|
168
|
+
}, 300);
|
169
|
+
});
|
170
|
+
|
171
|
+
test('informLocation and location invalidate each others caches', function() {
|
172
|
+
SC.routes.set('location', '');
|
173
|
+
stop();
|
174
|
+
|
175
|
+
setTimeout(function() {
|
176
|
+
equals(SC.routes.get('location'), '');
|
177
|
+
SC.routes.set('informLocation', 'simple');
|
178
|
+
|
179
|
+
setTimeout(function() {
|
180
|
+
equals(SC.routes.get('location'), 'simple');
|
181
|
+
SC.routes.set('location', '');
|
182
|
+
|
183
|
+
setTimeout(function() {
|
184
|
+
equals(SC.routes.get('location'), '');
|
185
|
+
SC.routes.set('informLocation', 'simple');
|
186
|
+
|
187
|
+
setTimeout(function() {
|
188
|
+
equals(SC.routes.get('location'), 'simple');
|
189
|
+
start();
|
190
|
+
}, 300);
|
191
|
+
}, 300);
|
192
|
+
}, 300);
|
193
|
+
}, 300);
|
194
|
+
});
|
195
|
+
|
153
196
|
module('SC.routes defined routes', {
|
154
197
|
|
155
198
|
setup: function() {
|
@@ -948,8 +948,7 @@ SC.mixin(SC.Object.prototype, SC.Observable);
|
|
948
948
|
through all the top-level properties looking for classes. When it finds
|
949
949
|
one, it saves the class path name.
|
950
950
|
*/
|
951
|
-
function
|
952
|
-
|
951
|
+
SC.findClassNames = function () {
|
953
952
|
if (SC._object_foundObjectClassNames) return;
|
954
953
|
SC._object_foundObjectClassNames = true;
|
955
954
|
|
@@ -1051,7 +1050,7 @@ SC.kindOf = function (scObject, scClass) {
|
|
1051
1050
|
*/
|
1052
1051
|
SC._object_className = function (obj) {
|
1053
1052
|
if (SC.isReady === NO) return ''; // class names are not available until ready
|
1054
|
-
if (!obj._object_className) findClassNames();
|
1053
|
+
if (!obj._object_className) SC.findClassNames();
|
1055
1054
|
if (obj._object_className) return obj._object_className;
|
1056
1055
|
|
1057
1056
|
// if no direct classname was found, walk up class chain looking for a
|
@@ -8,6 +8,15 @@
|
|
8
8
|
sc_require('ext/function');
|
9
9
|
sc_require('private/observer_set');
|
10
10
|
|
11
|
+
|
12
|
+
// When in debug mode, users can log deferred calls (such as .invokeOnce()) by
|
13
|
+
// setting SC.LOG_DEFERRED_CALLS. We'll declare the variable explicitly to make
|
14
|
+
// life easier for people who want to enter it inside consoles that auto-
|
15
|
+
// complete.
|
16
|
+
//@if (debug)
|
17
|
+
if (!SC.LOG_DEFERRED_CALLS) SC.LOG_DEFERRED_CALLS = false;
|
18
|
+
//@endif
|
19
|
+
|
11
20
|
/**
|
12
21
|
@class
|
13
22
|
|
@@ -27,27 +36,18 @@ sc_require('private/observer_set');
|
|
27
36
|
This is how you could write your mouseup handler in jQuery:
|
28
37
|
|
29
38
|
$('#okButton').on('click', function () {
|
30
|
-
SC.
|
39
|
+
SC.run(function () {
|
31
40
|
|
32
|
-
|
41
|
+
// handle click event...
|
33
42
|
|
34
|
-
|
43
|
+
}); // allows bindings to trigger...
|
35
44
|
});
|
36
45
|
|
37
46
|
@extends SC.Object
|
38
47
|
@since SproutCore 1.0
|
39
48
|
*/
|
40
|
-
|
41
|
-
|
42
|
-
// When in debug mode, users can log deferred calls (such as .invokeOnce()) by
|
43
|
-
// setting SC.LOG_DEFERRED_CALLS. We'll declare the variable explicitly to make
|
44
|
-
// life easier for people who want to enter it inside consoles that auto-
|
45
|
-
// complete.
|
46
|
-
//@if (debug)
|
47
|
-
if (!SC.LOG_DEFERRED_CALLS) SC.LOG_DEFERRED_CALLS = false;
|
48
|
-
//@endif
|
49
|
-
|
50
|
-
SC.RunLoop = SC.Object.extend(/** @scope SC.RunLoop.prototype */ {
|
49
|
+
SC.RunLoop = SC.Object.extend(
|
50
|
+
/** @scope SC.RunLoop.prototype */ {
|
51
51
|
|
52
52
|
/**
|
53
53
|
Call this method whenver you begin executing code.
|
@@ -174,13 +174,13 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
174
174
|
/* BEGIN DEBUG ONLY PROPERTIES AND METHODS */
|
175
175
|
|
176
176
|
/** @private @property */
|
177
|
-
allowStatechartTracing: function() {
|
177
|
+
allowStatechartTracing: function () {
|
178
178
|
var key = this.get('statechartTraceKey');
|
179
179
|
return this.get(key);
|
180
180
|
}.property().cacheable(),
|
181
181
|
|
182
182
|
/** @private */
|
183
|
-
_statechartTraceDidChange: function() {
|
183
|
+
_statechartTraceDidChange: function () {
|
184
184
|
this.notifyPropertyChange('allowStatechartTracing');
|
185
185
|
},
|
186
186
|
|
@@ -201,13 +201,13 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
201
201
|
|
202
202
|
@returns {Hash}
|
203
203
|
*/
|
204
|
-
details: function() {
|
204
|
+
details: function () {
|
205
205
|
var details = {
|
206
206
|
'initialized': this.get('statechartIsInitialized')
|
207
207
|
};
|
208
208
|
|
209
209
|
if (this.get('name')) {
|
210
|
-
details
|
210
|
+
details.name = this.get('name');
|
211
211
|
}
|
212
212
|
|
213
213
|
if (!this.get('statechartIsInitialized')) {
|
@@ -215,7 +215,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
215
215
|
}
|
216
216
|
|
217
217
|
details['current-states'] = [];
|
218
|
-
this.get('currentStates').forEach(function(state) {
|
218
|
+
this.get('currentStates').forEach(function (state) {
|
219
219
|
details['current-states'].push(state.get('fullPath'));
|
220
220
|
});
|
221
221
|
|
@@ -227,12 +227,12 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
227
227
|
if (this._gotoStateActions) {
|
228
228
|
stateTransition['transition-sequence'] = [];
|
229
229
|
var actions = this._gotoStateActions,
|
230
|
-
actionToStr = function(action) {
|
230
|
+
actionToStr = function (action) {
|
231
231
|
var actionName = action.action === SC.ENTER_STATE ? "enter" : "exit";
|
232
232
|
return "%@ %@".fmt(actionName, action.state.get('fullPath'));
|
233
233
|
};
|
234
234
|
|
235
|
-
actions.forEach(function(action) {
|
235
|
+
actions.forEach(function (action) {
|
236
236
|
stateTransition['transition-sequence'].push(actionToStr(action));
|
237
237
|
});
|
238
238
|
|
@@ -265,7 +265,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
265
265
|
|
266
266
|
@see #details
|
267
267
|
*/
|
268
|
-
toStringWithDetails: function() {
|
268
|
+
toStringWithDetails: function () {
|
269
269
|
var str = "",
|
270
270
|
header = this.toString(),
|
271
271
|
details = this.get('details');
|
@@ -277,7 +277,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
277
277
|
},
|
278
278
|
|
279
279
|
/** @private */
|
280
|
-
_hashToString: function(hash, indent) {
|
280
|
+
_hashToString: function (hash, indent) {
|
281
281
|
var str = "";
|
282
282
|
|
283
283
|
for (var key in hash) {
|
@@ -298,14 +298,14 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
298
298
|
},
|
299
299
|
|
300
300
|
/** @private */
|
301
|
-
_arrayToString: function(key, array, indent) {
|
301
|
+
_arrayToString: function (key, array, indent) {
|
302
302
|
if (array.length === 0) {
|
303
303
|
return "%@%@: []".fmt(' '.mult(indent), key);
|
304
304
|
}
|
305
305
|
|
306
306
|
var str = "%@%@: [\n".fmt(' '.mult(indent), key);
|
307
307
|
|
308
|
-
array.forEach(function(item, idx) {
|
308
|
+
array.forEach(function (item, idx) {
|
309
309
|
str += "%@%@\n".fmt(' '.mult(indent + 2), item);
|
310
310
|
}, this);
|
311
311
|
|
@@ -362,7 +362,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
362
362
|
|
363
363
|
NOTE: This is only available in debug mode!
|
364
364
|
*/
|
365
|
-
statechartLogTrace: function(msg) {
|
365
|
+
statechartLogTrace: function (msg) {
|
366
366
|
SC.Logger.info("%@: %@".fmt(this.get('statechartLogPrefix'), msg));
|
367
367
|
},
|
368
368
|
|
@@ -498,18 +498,18 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
498
498
|
@see SC.StatechartDelegate
|
499
499
|
@see #delegate
|
500
500
|
*/
|
501
|
-
statechartDelegate: function() {
|
501
|
+
statechartDelegate: function () {
|
502
502
|
var del = this.get('delegate');
|
503
503
|
return this.delegateFor('isStatechartDelegate', del);
|
504
504
|
}.property('delegate'),
|
505
505
|
|
506
|
-
initMixin: function() {
|
506
|
+
initMixin: function () {
|
507
507
|
if (this.get('autoInitStatechart')) {
|
508
508
|
this.initStatechart();
|
509
509
|
}
|
510
510
|
},
|
511
511
|
|
512
|
-
destroyMixin: function() {
|
512
|
+
destroyMixin: function () {
|
513
513
|
var root = this.get('rootState');
|
514
514
|
|
515
515
|
//@if(debug)
|
@@ -527,7 +527,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
527
527
|
Initializes the statechart. By initializing the statechart, it will create all the states and register
|
528
528
|
them with the statechart. Once complete, the statechart can be used to go to states and send events to.
|
529
529
|
*/
|
530
|
-
initStatechart: function() {
|
530
|
+
initStatechart: function () {
|
531
531
|
if (this.get('statechartIsInitialized')) return;
|
532
532
|
|
533
533
|
this._gotoStateLocked = NO;
|
@@ -599,7 +599,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
599
599
|
/**
|
600
600
|
Will create a root state for the statechart
|
601
601
|
*/
|
602
|
-
createRootState: function(state, attrs) {
|
602
|
+
createRootState: function (state, attrs) {
|
603
603
|
if (!attrs) attrs = {};
|
604
604
|
state = state.create(attrs);
|
605
605
|
return state;
|
@@ -610,7 +610,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
610
610
|
|
611
611
|
@returns {Array} the current states
|
612
612
|
*/
|
613
|
-
currentStates: function() {
|
613
|
+
currentStates: function () {
|
614
614
|
return this.getPath('rootState.currentSubstates');
|
615
615
|
}.property().cacheable(),
|
616
616
|
|
@@ -619,7 +619,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
619
619
|
|
620
620
|
@return {SC.State}
|
621
621
|
*/
|
622
|
-
firstCurrentState: function() {
|
622
|
+
firstCurrentState: function () {
|
623
623
|
var cs = this.get('currentStates');
|
624
624
|
return cs ? cs.objectAt(0) : null;
|
625
625
|
}.property('currentStates').cacheable(),
|
@@ -629,7 +629,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
629
629
|
|
630
630
|
@returns {Number} the count
|
631
631
|
*/
|
632
|
-
currentStateCount: function() {
|
632
|
+
currentStateCount: function () {
|
633
633
|
return this.getPath('currentStates.length');
|
634
634
|
}.property('currentStates').cacheable(),
|
635
635
|
|
@@ -639,7 +639,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
639
639
|
@param state {State|String} the state to check
|
640
640
|
@returns {Boolean} true if the state is a current state, otherwise fals is returned
|
641
641
|
*/
|
642
|
-
stateIsCurrentState: function(state) {
|
642
|
+
stateIsCurrentState: function (state) {
|
643
643
|
return this.get('rootState').stateIsCurrentSubstate(state);
|
644
644
|
},
|
645
645
|
|
@@ -649,7 +649,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
649
649
|
|
650
650
|
@returns {Array} the currently entered states
|
651
651
|
*/
|
652
|
-
enteredStates: function() {
|
652
|
+
enteredStates: function () {
|
653
653
|
return this.getPath('rootState.enteredSubstates');
|
654
654
|
}.property().cacheable(),
|
655
655
|
|
@@ -659,7 +659,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
659
659
|
@param state {State|String} the state to check
|
660
660
|
@returns {Boolean} true if the state is a currently entered state, otherwise false is returned
|
661
661
|
*/
|
662
|
-
stateIsEntered: function(state) {
|
662
|
+
stateIsEntered: function (state) {
|
663
663
|
return this.get('rootState').stateIsEnteredSubstate(state);
|
664
664
|
},
|
665
665
|
|
@@ -669,7 +669,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
669
669
|
@param value {State|String} either a state object or the name of a state
|
670
670
|
@returns {Boolean} true if the state does belong ot the statechart, otherwise false is returned
|
671
671
|
*/
|
672
|
-
doesContainState: function(value) {
|
672
|
+
doesContainState: function (value) {
|
673
673
|
return !SC.none(this.getState(value));
|
674
674
|
},
|
675
675
|
|
@@ -679,7 +679,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
679
679
|
@param value {State|String} either a state object of the name of a state
|
680
680
|
@returns {State} if a match then the matching state is returned, otherwise null is returned
|
681
681
|
*/
|
682
|
-
getState: function(state) {
|
682
|
+
getState: function (state) {
|
683
683
|
var root = this.get('rootState');
|
684
684
|
return root === state ? root : root.getSubstate(state);
|
685
685
|
},
|
@@ -727,7 +727,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
727
727
|
@param useHistory {Boolean} Optional. Indicates whether to include using history states in the transition process
|
728
728
|
@param context {Hash} Optional. A context object that will be passed to all exited and entered states
|
729
729
|
*/
|
730
|
-
gotoState: function(state, fromCurrentState, useHistory, context) {
|
730
|
+
gotoState: function (state, fromCurrentState, useHistory, context) {
|
731
731
|
if (!this.get('statechartIsInitialized')) {
|
732
732
|
this.statechartLogError("can not go to state %@. statechart has not yet been initialized".fmt(state));
|
733
733
|
return;
|
@@ -853,7 +853,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
853
853
|
/**
|
854
854
|
Indicates if the statechart is in an active goto state process
|
855
855
|
*/
|
856
|
-
gotoStateActive: function() {
|
856
|
+
gotoStateActive: function () {
|
857
857
|
return this._gotoStateLocked;
|
858
858
|
}.property(),
|
859
859
|
|
@@ -861,14 +861,14 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
861
861
|
Indicates if the statechart is in an active goto state process
|
862
862
|
that has been suspended
|
863
863
|
*/
|
864
|
-
gotoStateSuspended: function() {
|
864
|
+
gotoStateSuspended: function () {
|
865
865
|
return this._gotoStateLocked && !!this._gotoStateSuspendedPoint;
|
866
866
|
}.property(),
|
867
867
|
|
868
868
|
/**
|
869
869
|
Resumes an active goto state transition process that has been suspended.
|
870
870
|
*/
|
871
|
-
resumeGotoState: function() {
|
871
|
+
resumeGotoState: function () {
|
872
872
|
if (!this.get('gotoStateSuspended')) {
|
873
873
|
this.statechartLogError("Can not resume goto state since it has not been suspended");
|
874
874
|
return;
|
@@ -879,7 +879,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
879
879
|
},
|
880
880
|
|
881
881
|
/** @private */
|
882
|
-
_executeGotoStateActions: function(gotoState, actions, marker, context) {
|
882
|
+
_executeGotoStateActions: function (gotoState, actions, marker, context) {
|
883
883
|
var action = null,
|
884
884
|
len = actions.length,
|
885
885
|
actionResult = null;
|
@@ -889,13 +889,13 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
889
889
|
for (; marker < len; marker += 1) {
|
890
890
|
this._currentGotoStateAction = action = actions[marker];
|
891
891
|
switch (action.action) {
|
892
|
-
|
893
|
-
|
894
|
-
|
892
|
+
case SC.EXIT_STATE:
|
893
|
+
actionResult = this._exitState(action.state, context);
|
894
|
+
break;
|
895
895
|
|
896
|
-
|
897
|
-
|
898
|
-
|
896
|
+
case SC.ENTER_STATE:
|
897
|
+
actionResult = this._enterState(action.state, action.currentState, context);
|
898
|
+
break;
|
899
899
|
}
|
900
900
|
|
901
901
|
//
|
@@ -935,16 +935,18 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
935
935
|
},
|
936
936
|
|
937
937
|
/** @private */
|
938
|
-
_cleanupStateTransition: function() {
|
938
|
+
_cleanupStateTransition: function () {
|
939
939
|
this._currentGotoStateAction = null;
|
940
940
|
this._gotoStateSuspendedPoint = null;
|
941
941
|
this._gotoStateActions = null;
|
942
942
|
this._gotoStateLocked = NO;
|
943
943
|
this._flushPendingStateTransition();
|
944
|
+
// Check the flags so we only flush if the events will actually get sent.
|
945
|
+
if (!this._sendEventLocked && !this._gotoStateLocked) { this._flushPendingSentEvents(); }
|
944
946
|
},
|
945
947
|
|
946
948
|
/** @private */
|
947
|
-
_exitState: function(state, context) {
|
949
|
+
_exitState: function (state, context) {
|
948
950
|
var parentState;
|
949
951
|
|
950
952
|
if (state.get('currentSubstates').indexOf(state) >= 0) {
|
@@ -991,12 +993,12 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
991
993
|
@param state {SC.State} the state whose enterState method is to be invoked
|
992
994
|
@param context {Hash} a context hash object to provide the enterState method
|
993
995
|
*/
|
994
|
-
exitState: function(state, context) {
|
996
|
+
exitState: function (state, context) {
|
995
997
|
return state.exitState(context);
|
996
998
|
},
|
997
999
|
|
998
1000
|
/** @private */
|
999
|
-
_enterState: function(state, current, context) {
|
1001
|
+
_enterState: function (state, current, context) {
|
1000
1002
|
var parentState = state.get('parentState');
|
1001
1003
|
if (parentState && !state.get('isConcurrentState')) parentState.set('historyState', state);
|
1002
1004
|
|
@@ -1044,7 +1046,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
1044
1046
|
@param state {SC.State} the state whose enterState method is to be invoked
|
1045
1047
|
@param context {Hash} a context hash object to provide the enterState method
|
1046
1048
|
*/
|
1047
|
-
enterState: function(state, context) {
|
1049
|
+
enterState: function (state, context) {
|
1048
1050
|
if (state.enterStateByRoute && SC.kindOf(context, SC.StateRouteHandlerContext)) {
|
1049
1051
|
return state.enterStateByRoute(context);
|
1050
1052
|
} else {
|
@@ -1089,7 +1091,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
1089
1091
|
@param fromCurrentState {SC.State|String} Optional. the current state to start the state transition process from
|
1090
1092
|
@param recursive {Boolean} Optional. whether to follow history states recursively.
|
1091
1093
|
*/
|
1092
|
-
gotoHistoryState: function(state, fromCurrentState, recursive, context) {
|
1094
|
+
gotoHistoryState: function (state, fromCurrentState, recursive, context) {
|
1093
1095
|
if (!this.get('statechartIsInitialized')) {
|
1094
1096
|
this.statechartLogError("can not go to state %@'s history state. Statechart has not yet been initialized".fmt(state));
|
1095
1097
|
return;
|
@@ -1140,7 +1142,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
1140
1142
|
@see #stateWillTryToHandleEvent
|
1141
1143
|
@see #stateDidTryToHandleEvent
|
1142
1144
|
*/
|
1143
|
-
sendEvent: function(event, arg1, arg2) {
|
1145
|
+
sendEvent: function (event, arg1, arg2) {
|
1144
1146
|
|
1145
1147
|
if (this.get('isDestroyed')) {
|
1146
1148
|
this.statechartLogError("can not send event %@. statechart is destroyed".fmt(event));
|
@@ -1148,6 +1150,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
1148
1150
|
}
|
1149
1151
|
|
1150
1152
|
var statechartHandledEvent = NO,
|
1153
|
+
result = this,
|
1151
1154
|
eventHandled = NO,
|
1152
1155
|
currentStates = this.get('currentStates').slice(),
|
1153
1156
|
checkedStates = {},
|
@@ -1155,7 +1158,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
1155
1158
|
i = 0,
|
1156
1159
|
state = null;
|
1157
1160
|
|
1158
|
-
if (this._sendEventLocked || this.
|
1161
|
+
if (this._sendEventLocked || this._gotoStateLocked) {
|
1159
1162
|
// Want to prevent any actions from being processed by the states until
|
1160
1163
|
// they have had a chance to handle the most immediate action or completed
|
1161
1164
|
// a state transition
|
@@ -1184,8 +1187,8 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
1184
1187
|
if (!state.get('isCurrentState')) continue;
|
1185
1188
|
while (!eventHandled && state) {
|
1186
1189
|
if (!checkedStates[state.get('fullPath')]) {
|
1187
|
-
|
1188
|
-
|
1190
|
+
eventHandled = state.tryToHandleEvent(event, arg1, arg2);
|
1191
|
+
checkedStates[state.get('fullPath')] = YES;
|
1189
1192
|
}
|
1190
1193
|
if (!eventHandled) state = state.get('parentState');
|
1191
1194
|
else statechartHandledEvent = YES;
|
@@ -1203,7 +1206,13 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
1203
1206
|
}
|
1204
1207
|
//@endif
|
1205
1208
|
|
1206
|
-
|
1209
|
+
// Check if the flags are unlocked. These means any pending events
|
1210
|
+
// will successfully send, so go ahead and flush. Otherwise, events
|
1211
|
+
// would become out of order since the first event would get shifted,
|
1212
|
+
// then pushed.
|
1213
|
+
if (!this._sendEventLocked && !this._gotoStateLocked) {
|
1214
|
+
result = this._flushPendingSentEvents();
|
1215
|
+
}
|
1207
1216
|
|
1208
1217
|
return statechartHandledEvent ? this : (result ? this : null);
|
1209
1218
|
},
|
@@ -1216,7 +1225,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
1216
1225
|
@param {String} event the event the state will try to handle
|
1217
1226
|
@param {String} handler the name of the method on the state that will try to handle the event
|
1218
1227
|
*/
|
1219
|
-
stateWillTryToHandleEvent: function(state, event, handler) {
|
1228
|
+
stateWillTryToHandleEvent: function (state, event, handler) {
|
1220
1229
|
this._stateHandleEventInfo = {
|
1221
1230
|
state: state,
|
1222
1231
|
event: event,
|
@@ -1233,7 +1242,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
1233
1242
|
@param {String} handler the name of the method on the state that did try to handle the event
|
1234
1243
|
@param {Boolean} handled indicates if the handler was able to handle the event
|
1235
1244
|
*/
|
1236
|
-
stateDidTryToHandleEvent: function(state, event, handler, handled) {
|
1245
|
+
stateDidTryToHandleEvent: function (state, event, handler, handled) {
|
1237
1246
|
this._stateHandleEventInfo = null;
|
1238
1247
|
},
|
1239
1248
|
|
@@ -1242,7 +1251,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
1242
1251
|
Creates a chain of states from the given state to the greatest ancestor state (the root state). Used
|
1243
1252
|
when perform state transitions.
|
1244
1253
|
*/
|
1245
|
-
_createStateChain: function(state) {
|
1254
|
+
_createStateChain: function (state) {
|
1246
1255
|
var chain = [];
|
1247
1256
|
|
1248
1257
|
while (state) {
|
@@ -1259,10 +1268,10 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
1259
1268
|
go from being exited to states being entered during the state transition process. The value
|
1260
1269
|
returned is the fist matching state between the two given state chains.
|
1261
1270
|
*/
|
1262
|
-
_findPivotState: function(stateChain1, stateChain2) {
|
1271
|
+
_findPivotState: function (stateChain1, stateChain2) {
|
1263
1272
|
if (stateChain1.length === 0 || stateChain2.length === 0) return null;
|
1264
1273
|
|
1265
|
-
var pivot = stateChain1.find(function(state, index) {
|
1274
|
+
var pivot = stateChain1.find(function (state, index) {
|
1266
1275
|
if (stateChain2.indexOf(state) >= 0) return YES;
|
1267
1276
|
});
|
1268
1277
|
|
@@ -1279,7 +1288,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
1279
1288
|
@param exitStatePath {Array} an array representing a path of states that are to be exited
|
1280
1289
|
@param stopState {State} an explicit state in which to stop the exiting process
|
1281
1290
|
*/
|
1282
|
-
_traverseStatesToExit: function(state, exitStatePath, stopState, gotoStateActions) {
|
1291
|
+
_traverseStatesToExit: function (state, exitStatePath, stopState, gotoStateActions) {
|
1283
1292
|
if (!state || state === stopState) return;
|
1284
1293
|
|
1285
1294
|
// This state has concurrent substates. Therefore we have to make sure we
|
@@ -1316,7 +1325,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
1316
1325
|
@param pivotState {State} The state pivoting when to go from exiting states to entering states
|
1317
1326
|
@param useHistory {Boolean} indicates whether to recursively follow history states
|
1318
1327
|
*/
|
1319
|
-
_traverseStatesToEnter: function(state, enterStatePath, pivotState, useHistory, gotoStateActions) {
|
1328
|
+
_traverseStatesToEnter: function (state, enterStatePath, pivotState, useHistory, gotoStateActions) {
|
1320
1329
|
if (!state) return;
|
1321
1330
|
|
1322
1331
|
// We do not want to enter states in the enter path until the pivot state has been reached. After
|
@@ -1387,7 +1396,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
1387
1396
|
@param event {String} the property name to check
|
1388
1397
|
@returns {Boolean}
|
1389
1398
|
*/
|
1390
|
-
respondsTo: function(event) {
|
1399
|
+
respondsTo: function (event) {
|
1391
1400
|
// Fast path!
|
1392
1401
|
if (this.get('isDestroyed')) {
|
1393
1402
|
this.statechartLogError("can not respond to event %@. statechart is destroyed".fmt(event));
|
@@ -1421,7 +1430,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
1421
1430
|
@param arg2 {Object} Optional
|
1422
1431
|
@returns {Boolean} YES if handled, NO if not handled
|
1423
1432
|
*/
|
1424
|
-
tryToPerform: function(event, arg1, arg2) {
|
1433
|
+
tryToPerform: function (event, arg1, arg2) {
|
1425
1434
|
if (!this.respondsTo(event)) return NO;
|
1426
1435
|
|
1427
1436
|
if (SC.typeOf(this[event]) === SC.T_FUNCTION) {
|
@@ -1461,7 +1470,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
1461
1470
|
we want to call a calculate method on the current states where the method
|
1462
1471
|
will return a value when invoked. We can handle the returned values like so:
|
1463
1472
|
|
1464
|
-
invokeStateMethod('calculate', value, function(state, result) {
|
1473
|
+
invokeStateMethod('calculate', value, function (state, result) {
|
1465
1474
|
// .. handle the result returned from calculate that was invoked
|
1466
1475
|
// on the given state
|
1467
1476
|
})
|
@@ -1483,7 +1492,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
1483
1492
|
is returned. The value is the result of the method that got invoked
|
1484
1493
|
on a state.
|
1485
1494
|
*/
|
1486
|
-
invokeStateMethod: function(methodName, args, func) {
|
1495
|
+
invokeStateMethod: function (methodName, args, func) {
|
1487
1496
|
if (methodName === 'unknownEvent') {
|
1488
1497
|
this.statechartLogError("can not invoke method unkownEvent");
|
1489
1498
|
return;
|
@@ -1496,8 +1505,10 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
1496
1505
|
arg = len > 0 ? args[len - 1] : null,
|
1497
1506
|
callback = SC.typeOf(arg) === SC.T_FUNCTION ? args.pop() : null,
|
1498
1507
|
currentStates = this.get('currentStates'),
|
1499
|
-
i = 0, state = null,
|
1500
|
-
|
1508
|
+
i = 0, state = null,
|
1509
|
+
checkedStates = {},
|
1510
|
+
method, result,
|
1511
|
+
calledStates = 0;
|
1501
1512
|
|
1502
1513
|
len = currentStates.get('length');
|
1503
1514
|
|
@@ -1524,7 +1535,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
1524
1535
|
|
1525
1536
|
Iterate over all the given concurrent states and enter them
|
1526
1537
|
*/
|
1527
|
-
_traverseConcurrentStatesToEnter: function(states, exclude, useHistory, gotoStateActions) {
|
1538
|
+
_traverseConcurrentStatesToEnter: function (states, exclude, useHistory, gotoStateActions) {
|
1528
1539
|
var i = 0,
|
1529
1540
|
len = states.length,
|
1530
1541
|
state = null;
|
@@ -1540,7 +1551,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
1540
1551
|
Called by gotoState to flush a pending state transition at the front of the
|
1541
1552
|
pending queue.
|
1542
1553
|
*/
|
1543
|
-
_flushPendingStateTransition: function() {
|
1554
|
+
_flushPendingStateTransition: function () {
|
1544
1555
|
if (!this._pendingStateTransitions) {
|
1545
1556
|
this.statechartLogError("Unable to flush pending state transition. _pendingStateTransitions is invalid");
|
1546
1557
|
return;
|
@@ -1555,7 +1566,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
1555
1566
|
Called by sendEvent to flush a pending actions at the front of the pending
|
1556
1567
|
queue
|
1557
1568
|
*/
|
1558
|
-
_flushPendingSentEvents: function() {
|
1569
|
+
_flushPendingSentEvents: function () {
|
1559
1570
|
var pending = this._pendingSentEvents.shift();
|
1560
1571
|
if (!pending) return null;
|
1561
1572
|
return this.sendEvent(pending.event, pending.arg1, pending.arg2);
|
@@ -1563,7 +1574,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
1563
1574
|
|
1564
1575
|
/** @private */
|
1565
1576
|
//@if(debug)
|
1566
|
-
_monitorIsActiveDidChange: function() {
|
1577
|
+
_monitorIsActiveDidChange: function () {
|
1567
1578
|
if (this.get('monitorIsActive') && SC.none(this.get('monitor'))) {
|
1568
1579
|
this.set('monitor', SC.StatechartMonitor.create());
|
1569
1580
|
}
|
@@ -1576,19 +1587,19 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
1576
1587
|
TODO: Come back to this and refactor the code. It works, but it
|
1577
1588
|
could certainly be improved
|
1578
1589
|
*/
|
1579
|
-
_processGotoStateArgs: function(args) {
|
1590
|
+
_processGotoStateArgs: function (args) {
|
1580
1591
|
var processedArgs = {
|
1581
|
-
|
1582
|
-
|
1583
|
-
|
1584
|
-
|
1585
|
-
|
1586
|
-
|
1587
|
-
|
1592
|
+
state: null,
|
1593
|
+
fromCurrentState: null,
|
1594
|
+
useHistory: false,
|
1595
|
+
context: null
|
1596
|
+
},
|
1597
|
+
len = null,
|
1598
|
+
value = null;
|
1588
1599
|
|
1589
1600
|
args = SC.$A(args);
|
1590
|
-
args = args.filter(function(item) {
|
1591
|
-
return
|
1601
|
+
args = args.filter(function (item) {
|
1602
|
+
return item !== undefined;
|
1592
1603
|
});
|
1593
1604
|
len = args.length;
|
1594
1605
|
|
@@ -1647,7 +1658,7 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
1647
1658
|
- There must be one or more states that can be added to the root state
|
1648
1659
|
|
1649
1660
|
*/
|
1650
|
-
_constructRootStateClass: function() {
|
1661
|
+
_constructRootStateClass: function () {
|
1651
1662
|
var rsExampleKey = 'rootStateExample',
|
1652
1663
|
rsExample = this.get(rsExampleKey),
|
1653
1664
|
initialState = this.get('initialState'),
|
@@ -1700,27 +1711,27 @@ SC.StatechartManager = /** @scope SC.StatechartManager.prototype */{
|
|
1700
1711
|
},
|
1701
1712
|
|
1702
1713
|
/** @private */
|
1703
|
-
_logStatechartCreationError: function(msg) {
|
1714
|
+
_logStatechartCreationError: function (msg) {
|
1704
1715
|
SC.Logger.error("Unable to create statechart for %@: %@.".fmt(this, msg));
|
1705
1716
|
},
|
1706
1717
|
|
1707
1718
|
/**
|
1708
1719
|
Used to log a statechart error message
|
1709
1720
|
*/
|
1710
|
-
statechartLogError: function(msg) {
|
1721
|
+
statechartLogError: function (msg) {
|
1711
1722
|
SC.Logger.error("ERROR %@: %@".fmt(this.get('statechartLogPrefix'), msg));
|
1712
1723
|
},
|
1713
1724
|
|
1714
1725
|
/**
|
1715
1726
|
Used to log a statechart warning message
|
1716
1727
|
*/
|
1717
|
-
statechartLogWarning: function(msg) {
|
1728
|
+
statechartLogWarning: function (msg) {
|
1718
1729
|
if (this.get('suppressStatechartWarnings')) return;
|
1719
1730
|
SC.Logger.warn("WARN %@: %@".fmt(this.get('statechartLogPrefix'), msg));
|
1720
1731
|
},
|
1721
1732
|
|
1722
1733
|
/** @property */
|
1723
|
-
statechartLogPrefix: function() {
|
1734
|
+
statechartLogPrefix: function () {
|
1724
1735
|
var className = SC._object_className(this.constructor),
|
1725
1736
|
name = this.get('name'), prefix;
|
1726
1737
|
|