sproutcore 1.10.0 → 1.10.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/VERSION.yml +1 -1
- data/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
|
|