ember-source 1.0.0.rc8 → 1.0.0
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.
Potentially problematic release.
This version of ember-source might be problematic. Click here for more details.
- checksums.yaml +6 -14
- data/VERSION +1 -1
- data/dist/ember-data-deps.js +909 -1597
- data/dist/ember-data-deps.min.js +6 -6
- data/dist/ember-data-deps.prod.js +892 -1591
- data/dist/ember-debug.js +14 -2
- data/dist/ember-runtime.js +909 -113
- data/dist/ember-runtime.min.js +6 -6
- data/dist/ember-runtime.prod.js +892 -108
- data/dist/ember-spade.js +1 -1
- data/dist/ember-template-compiler.js +3 -12
- data/dist/ember-template-compiler.min.js +3 -3
- data/dist/ember-template-compiler.prod.js +0 -9
- data/dist/ember-tests.js +1 -1
- data/dist/ember.js +1302 -1799
- data/dist/ember.min.js +10 -10
- data/dist/ember.prod.js +1260 -1785
- data/lib/ember/version.rb +6 -2
- metadata +6 -14
- data/dist/ember-old-router.js +0 -28808
- data/dist/ember-old-router.min.js +0 -21
- data/dist/ember-old-router.prod.js +0 -28605
- data/dist/ember-params.js +0 -32394
- data/dist/ember-snork.js +0 -32321
- data/dist/ember2.js +0 -32377
- data/dist/ember3.js +0 -32379
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
metadata.gz: !binary |-
|
9
|
-
MjhmOTMzMzY4N2ExNDFmZjdjNDY3YjY4YjRkOTc4ZjJmOTYxNmM1ZjVhNzMw
|
10
|
-
NGI0MzMzNDUzOGE1ZjVhZTE4ZGE4OGMxNTlkNmY2Nzk1N2IwOGUxMDNhNDM5
|
11
|
-
YjUwZTdmZWRhYzNmMWMwNjRkM2Q0MTdkM2UxMjRiMDliOTgxMWY=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
ZDBlZDA1NDE0YmJmMTM0YmU0ZDUyNDgyNzNlYWVlZDZlOTE2YTliYzNjOTQx
|
14
|
-
ZGIxNjUzNzFkZTg4ODhkZTRlYTVmZDAxYzM2Mjg3NDVhMmFhOWY0OWM1NDA2
|
15
|
-
ZjM3MWFhMTM0MzdjMDM2ZGEzMGM0NmQ2ZjBjMWFkNDg1YjViYTk=
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 940d700becd9b7df6c663da37eee9f66639f64d2
|
4
|
+
data.tar.gz: ee29f542f023254df299db55f8c1afde45a4498a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8e53c6da026a631d44262eb78338870274de95a3ff147b55c15c03943f406c181e925b1c235936a90d130acd82aaff710c246655814b100c939fc8c4771e0a53
|
7
|
+
data.tar.gz: 289304acc4db08ad5d3206ca3316d9a8c69c53c347e1eb1c332935cc79fd7aaa7d6dc9c52b146e7c8755c5fb0d3af7e72ec8df4150aeabb2835050594586618c
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.0
|
1
|
+
1.0.0
|
data/dist/ember-data-deps.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
// Version: v1.0.0
|
2
|
-
// Last commit:
|
1
|
+
// Version: v1.0.0
|
2
|
+
// Last commit: e2ea0cf (2013-08-31 23:47:39 -0700)
|
3
3
|
|
4
4
|
|
5
5
|
(function() {
|
@@ -156,10 +156,22 @@ Ember.deprecateFunc = function(message, func) {
|
|
156
156
|
};
|
157
157
|
};
|
158
158
|
|
159
|
+
|
160
|
+
// Inform the developer about the Ember Inspector if not installed.
|
161
|
+
if (!Ember.testing) {
|
162
|
+
if (typeof window !== 'undefined' && window.chrome && window.addEventListener) {
|
163
|
+
window.addEventListener("load", function() {
|
164
|
+
if (document.body && document.body.dataset && !document.body.dataset.emberExtension) {
|
165
|
+
Ember.debug('For more advanced debugging, install the Ember Inspector from https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi');
|
166
|
+
}
|
167
|
+
}, false);
|
168
|
+
}
|
169
|
+
}
|
170
|
+
|
159
171
|
})();
|
160
172
|
|
161
|
-
// Version: v1.0.0
|
162
|
-
// Last commit:
|
173
|
+
// Version: v1.0.0
|
174
|
+
// Last commit: e2ea0cf (2013-08-31 23:47:39 -0700)
|
163
175
|
|
164
176
|
|
165
177
|
(function() {
|
@@ -225,7 +237,7 @@ var define, requireModule;
|
|
225
237
|
|
226
238
|
@class Ember
|
227
239
|
@static
|
228
|
-
@version 1.0.0
|
240
|
+
@version 1.0.0
|
229
241
|
*/
|
230
242
|
|
231
243
|
if ('undefined' === typeof Ember) {
|
@@ -252,10 +264,10 @@ Ember.toString = function() { return "Ember"; };
|
|
252
264
|
/**
|
253
265
|
@property VERSION
|
254
266
|
@type String
|
255
|
-
@default '1.0.0
|
267
|
+
@default '1.0.0'
|
256
268
|
@final
|
257
269
|
*/
|
258
|
-
Ember.VERSION = '1.0.0
|
270
|
+
Ember.VERSION = '1.0.0';
|
259
271
|
|
260
272
|
/**
|
261
273
|
Standard environmental variables. You can define these in a global `ENV`
|
@@ -4601,8 +4613,8 @@ function registerComputedWithProperties(name, macro) {
|
|
4601
4613
|
property is null, an empty string, empty array, or empty function.
|
4602
4614
|
|
4603
4615
|
Note: When using `Ember.computed.empty` to watch an array make sure to
|
4604
|
-
use the `array.length`
|
4605
|
-
|
4616
|
+
use the `array.length` syntax so the computed can subscribe to transitions
|
4617
|
+
from empty to non-empty states.
|
4606
4618
|
|
4607
4619
|
Example
|
4608
4620
|
|
@@ -4610,9 +4622,9 @@ function registerComputedWithProperties(name, macro) {
|
|
4610
4622
|
var ToDoList = Ember.Object.extend({
|
4611
4623
|
done: Ember.computed.empty('todos.length')
|
4612
4624
|
});
|
4613
|
-
var todoList = ToDoList.create({
|
4625
|
+
var todoList = ToDoList.create({todos: ['Unit Test', 'Documentation', 'Release']});
|
4614
4626
|
todoList.get('done'); // false
|
4615
|
-
todoList.get('
|
4627
|
+
todoList.get('todos').clear(); // []
|
4616
4628
|
todoList.get('done'); // true
|
4617
4629
|
```
|
4618
4630
|
|
@@ -5714,7 +5726,7 @@ define("backburner",
|
|
5714
5726
|
clearTimeout(debouncee[2]);
|
5715
5727
|
}
|
5716
5728
|
|
5717
|
-
var timer =
|
5729
|
+
var timer = global.setTimeout(function() {
|
5718
5730
|
if (!immediate) {
|
5719
5731
|
self.run.apply(self, args);
|
5720
5732
|
}
|
@@ -5783,8 +5795,8 @@ define("backburner",
|
|
5783
5795
|
function createAutorun(backburner) {
|
5784
5796
|
backburner.begin();
|
5785
5797
|
autorun = global.setTimeout(function() {
|
5786
|
-
backburner.end();
|
5787
5798
|
autorun = null;
|
5799
|
+
backburner.end();
|
5788
5800
|
});
|
5789
5801
|
}
|
5790
5802
|
|
@@ -7225,19 +7237,19 @@ Ember.mixin = function(obj) {
|
|
7225
7237
|
`Ember.Mixin.extend`.
|
7226
7238
|
|
7227
7239
|
Note that mixins extend a constructor's prototype so arrays and object literals
|
7228
|
-
defined as properties will be shared amongst objects that implement the mixin.
|
7240
|
+
defined as properties will be shared amongst objects that implement the mixin.
|
7229
7241
|
If you want to define an property in a mixin that is not shared, you can define
|
7230
7242
|
it either as a computed property or have it be created on initialization of the object.
|
7231
|
-
|
7243
|
+
|
7232
7244
|
```javascript
|
7233
7245
|
//filters array will be shared amongst any object implementing mixin
|
7234
7246
|
App.Filterable = Ember.Mixin.create({
|
7235
|
-
filters: Ember.A()
|
7247
|
+
filters: Ember.A()
|
7236
7248
|
});
|
7237
7249
|
|
7238
7250
|
//filters will be a separate array for every object implementing the mixin
|
7239
7251
|
App.Filterable = Ember.Mixin.create({
|
7240
|
-
filters: Ember.computed(function(){return Ember.A();})
|
7252
|
+
filters: Ember.computed(function(){return Ember.A();})
|
7241
7253
|
});
|
7242
7254
|
|
7243
7255
|
//filters will be created as a separate array during the object's initialization
|
@@ -7484,6 +7496,22 @@ Ember.aliasMethod = function(methodName) {
|
|
7484
7496
|
//
|
7485
7497
|
|
7486
7498
|
/**
|
7499
|
+
Specify a method that observes property changes.
|
7500
|
+
|
7501
|
+
```javascript
|
7502
|
+
Ember.Object.extend({
|
7503
|
+
valueObserver: Ember.observer(function() {
|
7504
|
+
// Executes whenever the "value" property changes
|
7505
|
+
}, 'value')
|
7506
|
+
});
|
7507
|
+
```
|
7508
|
+
|
7509
|
+
In the future this method may become asynchronous. If you want to ensure
|
7510
|
+
synchronous behavior, use `immediateObserver`.
|
7511
|
+
|
7512
|
+
Also available as `Function.prototype.observes` if prototype extensions are
|
7513
|
+
enabled.
|
7514
|
+
|
7487
7515
|
@method observer
|
7488
7516
|
@for Ember
|
7489
7517
|
@param {Function} func
|
@@ -7496,9 +7524,23 @@ Ember.observer = function(func) {
|
|
7496
7524
|
return func;
|
7497
7525
|
};
|
7498
7526
|
|
7499
|
-
// If observers ever become asynchronous, Ember.immediateObserver
|
7500
|
-
// must remain synchronous.
|
7501
7527
|
/**
|
7528
|
+
Specify a method that observes property changes.
|
7529
|
+
|
7530
|
+
```javascript
|
7531
|
+
Ember.Object.extend({
|
7532
|
+
valueObserver: Ember.immediateObserver(function() {
|
7533
|
+
// Executes whenever the "value" property changes
|
7534
|
+
}, 'value')
|
7535
|
+
});
|
7536
|
+
```
|
7537
|
+
|
7538
|
+
In the future, `Ember.observer` may become asynchronous. In this event,
|
7539
|
+
`Ember.immediateObserver` will maintain the synchronous behavior.
|
7540
|
+
|
7541
|
+
Also available as `Function.prototype.observesImmediately` if prototype extensions are
|
7542
|
+
enabled.
|
7543
|
+
|
7502
7544
|
@method immediateObserver
|
7503
7545
|
@for Ember
|
7504
7546
|
@param {Function} func
|
@@ -7526,24 +7568,31 @@ Ember.immediateObserver = function() {
|
|
7526
7568
|
|
7527
7569
|
```javascript
|
7528
7570
|
App.PersonView = Ember.View.extend({
|
7571
|
+
|
7529
7572
|
friends: [{ name: 'Tom' }, { name: 'Stefan' }, { name: 'Kris' }],
|
7530
|
-
|
7573
|
+
|
7574
|
+
valueWillChange: Ember.beforeObserver(function(obj, keyName) {
|
7531
7575
|
this.changingFrom = obj.get(keyName);
|
7532
|
-
}
|
7533
|
-
|
7576
|
+
}, 'content.value'),
|
7577
|
+
|
7578
|
+
valueDidChange: Ember.observer(function(obj, keyName) {
|
7534
7579
|
// only run if updating a value already in the DOM
|
7535
7580
|
if (this.get('state') === 'inDOM') {
|
7536
|
-
|
7537
|
-
|
7581
|
+
var color = obj.get(keyName) > this.changingFrom ? 'green' : 'red';
|
7582
|
+
// logic
|
7538
7583
|
}
|
7539
|
-
}
|
7540
|
-
|
7584
|
+
}, 'content.value'),
|
7585
|
+
|
7586
|
+
friendsDidChange: Ember.observer(function(obj, keyName) {
|
7541
7587
|
// some logic
|
7542
7588
|
// obj.get(keyName) returns friends array
|
7543
|
-
}
|
7589
|
+
}, 'friends.@each.name')
|
7544
7590
|
});
|
7545
7591
|
```
|
7546
7592
|
|
7593
|
+
Also available as `Function.prototype.observesBefore` if prototype extensions are
|
7594
|
+
enabled.
|
7595
|
+
|
7547
7596
|
@method beforeObserver
|
7548
7597
|
@for Ember
|
7549
7598
|
@param {Function} func
|
@@ -7627,6 +7676,7 @@ define("rsvp/async",
|
|
7627
7676
|
var browserGlobal = (typeof window !== 'undefined') ? window : {};
|
7628
7677
|
var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
|
7629
7678
|
var async;
|
7679
|
+
var local = (typeof global !== 'undefined') ? global : this;
|
7630
7680
|
|
7631
7681
|
// old node
|
7632
7682
|
function useNextTick() {
|
@@ -7677,7 +7727,7 @@ define("rsvp/async",
|
|
7677
7727
|
|
7678
7728
|
function useSetTimeout() {
|
7679
7729
|
return function(callback, arg) {
|
7680
|
-
|
7730
|
+
local.setTimeout(function() {
|
7681
7731
|
callback(arg);
|
7682
7732
|
}, 1);
|
7683
7733
|
};
|
@@ -8216,6 +8266,13 @@ define("rsvp",
|
|
8216
8266
|
})();
|
8217
8267
|
|
8218
8268
|
(function() {
|
8269
|
+
/**
|
8270
|
+
Flag to enable/disable model factory injections (disabled by default)
|
8271
|
+
If model factory injections are enabled, models should not be
|
8272
|
+
accessed globally (only through `container.lookupFactory('model:modelName'))`);
|
8273
|
+
*/
|
8274
|
+
Ember.MODEL_FACTORY_INJECTIONS = false || !!Ember.ENV.MODEL_FACTORY_INJECTIONS;
|
8275
|
+
|
8219
8276
|
define("container",
|
8220
8277
|
[],
|
8221
8278
|
function() {
|
@@ -8494,6 +8551,7 @@ define("container",
|
|
8494
8551
|
|
8495
8552
|
container.unregister('model:user')
|
8496
8553
|
container.lookup('model:user') === undefined //=> true
|
8554
|
+
```
|
8497
8555
|
|
8498
8556
|
@method unregister
|
8499
8557
|
@param {String} fullName
|
@@ -8577,7 +8635,7 @@ define("container",
|
|
8577
8635
|
*/
|
8578
8636
|
makeToString: function(factory, fullName) {
|
8579
8637
|
return factory.toString();
|
8580
|
-
},
|
8638
|
+
},
|
8581
8639
|
|
8582
8640
|
/**
|
8583
8641
|
Given a fullName return a corresponding instance.
|
@@ -8985,6 +9043,7 @@ define("container",
|
|
8985
9043
|
var factory = container.resolve(name);
|
8986
9044
|
var injectedFactory;
|
8987
9045
|
var cache = container.factoryCache;
|
9046
|
+
var type = fullName.split(":")[0];
|
8988
9047
|
|
8989
9048
|
if (!factory) { return; }
|
8990
9049
|
|
@@ -8992,7 +9051,7 @@ define("container",
|
|
8992
9051
|
return cache.get(fullName);
|
8993
9052
|
}
|
8994
9053
|
|
8995
|
-
if (typeof factory.extend !== 'function') {
|
9054
|
+
if (typeof factory.extend !== 'function' || (!Ember.MODEL_FACTORY_INJECTIONS && type === 'model')) {
|
8996
9055
|
// TODO: think about a 'safe' merge style extension
|
8997
9056
|
// for now just fallback to create time injection
|
8998
9057
|
return factory;
|
@@ -10796,6 +10855,9 @@ Ember.Array = Ember.Mixin.create(Ember.Enumerable, /** @scope Ember.Array.protot
|
|
10796
10855
|
return an enumerable that maps automatically to the named key on the
|
10797
10856
|
member objects.
|
10798
10857
|
|
10858
|
+
If you merely want to watch for any items being added or removed to the array,
|
10859
|
+
use the `[]` property instead of `@each`.
|
10860
|
+
|
10799
10861
|
@property @each
|
10800
10862
|
*/
|
10801
10863
|
'@each': Ember.computed(function() {
|
@@ -10827,7 +10889,7 @@ var get = Ember.get,
|
|
10827
10889
|
eachPropertyPattern = /^(.*)\.@each\.(.*)/,
|
10828
10890
|
doubleEachPropertyPattern = /(.*\.@each){2,}/;
|
10829
10891
|
|
10830
|
-
|
10892
|
+
/*
|
10831
10893
|
Tracks changes to dependent arrays, as well as to properties of items in
|
10832
10894
|
dependent arrays.
|
10833
10895
|
|
@@ -11016,22 +11078,29 @@ DependentArraysObserver.prototype = {
|
|
11016
11078
|
guid = guidFor(dependentArray),
|
11017
11079
|
dependentKey = this.dependentKeysByGuid[guid],
|
11018
11080
|
itemPropertyKeys = this.cp._itemPropertyKeys[dependentKey] || [],
|
11081
|
+
item,
|
11019
11082
|
itemIndex,
|
11083
|
+
sliceIndex,
|
11020
11084
|
observerContexts;
|
11021
11085
|
|
11022
11086
|
observerContexts = this.removeTransformation(dependentKey, index, removedCount);
|
11023
|
-
|
11087
|
+
|
11088
|
+
|
11089
|
+
function removeObservers(propertyKey) {
|
11090
|
+
removeBeforeObserver(item, propertyKey, this, observerContexts[sliceIndex].beforeObserver);
|
11091
|
+
removeObserver(item, propertyKey, this, observerContexts[sliceIndex].observer);
|
11092
|
+
}
|
11093
|
+
|
11094
|
+
for (sliceIndex = removedCount - 1; sliceIndex >= 0; --sliceIndex) {
|
11024
11095
|
itemIndex = index + sliceIndex;
|
11096
|
+
item = dependentArray.objectAt(itemIndex);
|
11025
11097
|
|
11026
|
-
forEach(itemPropertyKeys,
|
11027
|
-
removeBeforeObserver(item, propertyKey, this, observerContexts[sliceIndex].beforeObserver);
|
11028
|
-
removeObserver(item, propertyKey, this, observerContexts[sliceIndex].observer);
|
11029
|
-
}, this);
|
11098
|
+
forEach(itemPropertyKeys, removeObservers, this);
|
11030
11099
|
|
11031
11100
|
changeMeta = createChangeMeta(dependentArray, item, itemIndex, this.instanceMeta.propertyName, this.cp);
|
11032
11101
|
this.setValue( removedItem.call(
|
11033
11102
|
this.instanceMeta.context, this.getValue(), item, changeMeta, this.instanceMeta.sugarMeta));
|
11034
|
-
}
|
11103
|
+
}
|
11035
11104
|
},
|
11036
11105
|
|
11037
11106
|
dependentArrayDidChange: function (dependentArray, index, removedCount, addedCount) {
|
@@ -11045,8 +11114,8 @@ DependentArraysObserver.prototype = {
|
|
11045
11114
|
|
11046
11115
|
forEach(dependentArray.slice(index, index + addedCount), function (item, sliceIndex) {
|
11047
11116
|
if (itemPropertyKeys) {
|
11048
|
-
observerContext =
|
11049
|
-
observerContexts[sliceIndex] =
|
11117
|
+
observerContext =
|
11118
|
+
observerContexts[sliceIndex] =
|
11050
11119
|
this.createPropertyObserverContext(dependentArray, index + sliceIndex, this.trackedArraysByGuid[dependentKey]);
|
11051
11120
|
forEach(itemPropertyKeys, function (propertyKey) {
|
11052
11121
|
addBeforeObserver(item, propertyKey, this, observerContext.beforeObserver);
|
@@ -11063,30 +11132,29 @@ DependentArraysObserver.prototype = {
|
|
11063
11132
|
},
|
11064
11133
|
|
11065
11134
|
itemPropertyWillChange: function (obj, keyName, array, index) {
|
11066
|
-
var
|
11135
|
+
var guid = guidFor(obj);
|
11067
11136
|
|
11068
|
-
if (!this.changedItems[
|
11069
|
-
this.changedItems[
|
11070
|
-
array: array,
|
11137
|
+
if (!this.changedItems[guid]) {
|
11138
|
+
this.changedItems[guid] = {
|
11139
|
+
array: array,
|
11071
11140
|
index: index,
|
11072
11141
|
obj: obj,
|
11073
|
-
|
11074
|
-
previousValue: get(obj, keyName)
|
11142
|
+
previousValues: {}
|
11075
11143
|
};
|
11076
11144
|
}
|
11145
|
+
|
11146
|
+
this.changedItems[guid].previousValues[keyName] = get(obj, keyName);
|
11077
11147
|
},
|
11078
11148
|
|
11079
11149
|
itemPropertyDidChange: function(obj, keyName, array, index) {
|
11080
11150
|
Ember.run.once(this, 'flushChanges');
|
11081
11151
|
},
|
11082
11152
|
|
11083
|
-
// TODO: it probably makes more sense to remove the item during `willChange`
|
11084
|
-
// and add it back (with the new value) during `didChange`
|
11085
11153
|
flushChanges: function() {
|
11086
11154
|
var changedItems = this.changedItems, key, c, changeMeta;
|
11087
11155
|
for (key in changedItems) {
|
11088
11156
|
c = changedItems[key];
|
11089
|
-
changeMeta = createChangeMeta(c.array, c.obj, c.index, this.instanceMeta.propertyName, this.cp, c.
|
11157
|
+
changeMeta = createChangeMeta(c.array, c.obj, c.index, this.instanceMeta.propertyName, this.cp, c.previousValues);
|
11090
11158
|
this.setValue(
|
11091
11159
|
this.callbacks.removedItem.call(this.instanceMeta.context, this.getValue(), c.obj, changeMeta, this.instanceMeta.sugarMeta));
|
11092
11160
|
this.setValue(
|
@@ -11096,18 +11164,19 @@ DependentArraysObserver.prototype = {
|
|
11096
11164
|
}
|
11097
11165
|
};
|
11098
11166
|
|
11099
|
-
function createChangeMeta(dependentArray, item, index, propertyName, property,
|
11167
|
+
function createChangeMeta(dependentArray, item, index, propertyName, property, previousValues) {
|
11100
11168
|
var meta = {
|
11101
11169
|
arrayChanged: dependentArray,
|
11102
11170
|
index: index,
|
11103
11171
|
item: item,
|
11104
11172
|
propertyName: propertyName,
|
11105
|
-
property: property
|
11106
|
-
// previous value is only available for item property changes!
|
11107
|
-
previousValue: previousValue
|
11173
|
+
property: property
|
11108
11174
|
};
|
11109
11175
|
|
11110
|
-
if (
|
11176
|
+
if (previousValues) {
|
11177
|
+
// previous values only available for item property changes
|
11178
|
+
meta.previousValues = previousValues;
|
11179
|
+
}
|
11111
11180
|
|
11112
11181
|
return meta;
|
11113
11182
|
}
|
@@ -11231,7 +11300,9 @@ function ReduceComputedProperty(options) {
|
|
11231
11300
|
|
11232
11301
|
forEach(cp._dependentKeys, function(dependentKey) {
|
11233
11302
|
var dependentArray = get(this, dependentKey);
|
11234
|
-
|
11303
|
+
if (dependentArray) {
|
11304
|
+
addItems.call(this, dependentArray, callbacks, cp, propertyName, meta);
|
11305
|
+
}
|
11235
11306
|
}, this);
|
11236
11307
|
};
|
11237
11308
|
|
@@ -11333,7 +11404,122 @@ ReduceComputedProperty.prototype.property = function () {
|
|
11333
11404
|
return ComputedProperty.prototype.property.apply(this, propertyArgs);
|
11334
11405
|
};
|
11335
11406
|
|
11407
|
+
/**
|
11408
|
+
Creates a computed property which operates on dependent arrays and
|
11409
|
+
is updated with "one at a time" semantics. When items are added or
|
11410
|
+
removed from the dependent array(s) a reduce computed only operates
|
11411
|
+
on the change instead of re-evaluating the entire array.
|
11412
|
+
|
11413
|
+
If there are more than one arguments the first arguments are
|
11414
|
+
considered to be dependent property keys. The last argument is
|
11415
|
+
required to be an options object. The options object can have the
|
11416
|
+
following four properties.
|
11417
|
+
|
11418
|
+
`initialValue` - A value or function that will be used as the initial
|
11419
|
+
value for the computed. If this property is a function the result of calling
|
11420
|
+
the function will be used as the initial value. This property is required.
|
11421
|
+
|
11422
|
+
`initialize` - An optional initialize function. Typically this will be used
|
11423
|
+
to set up state on the instanceMeta object.
|
11424
|
+
|
11425
|
+
`removedItem` - A function that is called each time an element is removed
|
11426
|
+
from the array.
|
11427
|
+
|
11428
|
+
`addedItem` - A function that is called each time an element is added to
|
11429
|
+
the array.
|
11430
|
+
|
11431
|
+
|
11432
|
+
The `initialize` function has the following signature:
|
11433
|
+
|
11434
|
+
```javascript
|
11435
|
+
function (initialValue, changeMeta, instanceMeta)
|
11436
|
+
```
|
11437
|
+
|
11438
|
+
`initialValue` - The value of the `initialValue` property from the
|
11439
|
+
options object.
|
11440
|
+
|
11441
|
+
`changeMeta` - An object which contains meta information about the
|
11442
|
+
computed. It contains the following properties:
|
11443
|
+
|
11444
|
+
- `property` the computed property
|
11445
|
+
- `propertyName` the name of the property on the object
|
11446
|
+
|
11447
|
+
`instanceMeta` - An object that can be used to store meta
|
11448
|
+
information needed for calculating your computed. For example a
|
11449
|
+
unique computed might use this to store the number of times a given
|
11450
|
+
element is found in the dependent array.
|
11451
|
+
|
11452
|
+
|
11453
|
+
The `removedItem` and `addedItem` functions both have the following signature:
|
11454
|
+
|
11455
|
+
```javascript
|
11456
|
+
function (accumulatedValue, item, changeMeta, instanceMeta)
|
11457
|
+
```
|
11458
|
+
|
11459
|
+
`accumulatedValue` - The value returned from the last time
|
11460
|
+
`removedItem` or `addedItem` was called or `initialValue`.
|
11461
|
+
|
11462
|
+
`item` - the element added or removed from the array
|
11463
|
+
|
11464
|
+
`changeMeta` - An object which contains meta information about the
|
11465
|
+
change. It contains the following properties:
|
11466
|
+
|
11467
|
+
- `property` the computed property
|
11468
|
+
- `propertyName` the name of the property on the object
|
11469
|
+
- `index` the index of the added or removed item
|
11470
|
+
- `item` the added or removed item: this is exactly the same as
|
11471
|
+
the second arg
|
11472
|
+
- `arrayChanged` the array that triggered the change. Can be
|
11473
|
+
useful when depending on multiple arrays.
|
11474
|
+
|
11475
|
+
For property changes triggered on an item property change (when
|
11476
|
+
depKey is something like `someArray.@each.someProperty`),
|
11477
|
+
`changeMeta` will also contain the following property:
|
11478
|
+
|
11479
|
+
- `previousValues` an object whose keys are the properties that changed on
|
11480
|
+
the item, and whose values are the item's previous values.
|
11481
|
+
|
11482
|
+
`previousValues` is important Ember coalesces item property changes via
|
11483
|
+
Ember.run.once. This means that by the time removedItem gets called, item has
|
11484
|
+
the new values, but you may need the previous value (eg for sorting &
|
11485
|
+
filtering).
|
11336
11486
|
|
11487
|
+
`instanceMeta` - An object that can be used to store meta
|
11488
|
+
information needed for calculating your computed. For example a
|
11489
|
+
unique computed might use this to store the number of times a given
|
11490
|
+
element is found in the dependent array.
|
11491
|
+
|
11492
|
+
The `removedItem` and `addedItem` functions should return the accumulated
|
11493
|
+
value. It is acceptable to not return anything (ie return undefined)
|
11494
|
+
to invalidate the computation. This is generally not a good idea for
|
11495
|
+
arrayComputed but it's used in eg max and min.
|
11496
|
+
|
11497
|
+
Example
|
11498
|
+
|
11499
|
+
```javascript
|
11500
|
+
Ember.computed.max = function (dependentKey) {
|
11501
|
+
return Ember.reduceComputed.call(null, dependentKey, {
|
11502
|
+
initialValue: -Infinity,
|
11503
|
+
|
11504
|
+
addedItem: function (accumulatedValue, item, changeMeta, instanceMeta) {
|
11505
|
+
return Math.max(accumulatedValue, item);
|
11506
|
+
},
|
11507
|
+
|
11508
|
+
removedItem: function (accumulatedValue, item, changeMeta, instanceMeta) {
|
11509
|
+
if (item < accumulatedValue) {
|
11510
|
+
return accumulatedValue;
|
11511
|
+
}
|
11512
|
+
}
|
11513
|
+
});
|
11514
|
+
};
|
11515
|
+
```
|
11516
|
+
|
11517
|
+
@method reduceComputed
|
11518
|
+
@for Ember
|
11519
|
+
@param {String} [dependentKeys*]
|
11520
|
+
@param {Object} options
|
11521
|
+
@returns {Ember.ComputedProperty}
|
11522
|
+
*/
|
11337
11523
|
Ember.reduceComputed = function (options) {
|
11338
11524
|
var args;
|
11339
11525
|
|
@@ -11359,7 +11545,6 @@ Ember.reduceComputed = function (options) {
|
|
11359
11545
|
return cp;
|
11360
11546
|
};
|
11361
11547
|
|
11362
|
-
|
11363
11548
|
})();
|
11364
11549
|
|
11365
11550
|
|
@@ -11404,7 +11589,120 @@ ArrayComputedProperty.prototype.resetValue = function (array) {
|
|
11404
11589
|
return array;
|
11405
11590
|
};
|
11406
11591
|
|
11592
|
+
/**
|
11593
|
+
Creates a computed property which operates on dependent arrays and
|
11594
|
+
is updated with "one at a time" semantics. When items are added or
|
11595
|
+
removed from the dependent array(s) an array computed only operates
|
11596
|
+
on the change instead of re-evaluating the entire array. This should
|
11597
|
+
return an array, if you'd like to use "one at a time" semantics and
|
11598
|
+
compute some value other then an array look at
|
11599
|
+
`Ember.reduceComputed`.
|
11600
|
+
|
11601
|
+
If there are more than one arguments the first arguments are
|
11602
|
+
considered to be dependent property keys. The last argument is
|
11603
|
+
required to be an options object. The options object can have the
|
11604
|
+
following three properties.
|
11605
|
+
|
11606
|
+
`initialize` - An optional initialize function. Typically this will be used
|
11607
|
+
to set up state on the instanceMeta object.
|
11608
|
+
|
11609
|
+
`removedItem` - A function that is called each time an element is
|
11610
|
+
removed from the array.
|
11611
|
+
|
11612
|
+
`addedItem` - A function that is called each time an element is
|
11613
|
+
added to the array.
|
11614
|
+
|
11615
|
+
|
11616
|
+
The `initialize` function has the following signature:
|
11617
|
+
|
11618
|
+
```javascript
|
11619
|
+
function (array, changeMeta, instanceMeta)
|
11620
|
+
```
|
11621
|
+
|
11622
|
+
`array` - The initial value of the arrayComputed, an empty array.
|
11623
|
+
|
11624
|
+
`changeMeta` - An object which contains meta information about the
|
11625
|
+
computed. It contains the following properties:
|
11626
|
+
|
11627
|
+
- `property` the computed property
|
11628
|
+
- `propertyName` the name of the property on the object
|
11629
|
+
|
11630
|
+
`instanceMeta` - An object that can be used to store meta
|
11631
|
+
information needed for calculating your computed. For example a
|
11632
|
+
unique computed might use this to store the number of times a given
|
11633
|
+
element is found in the dependent array.
|
11634
|
+
|
11635
|
+
|
11636
|
+
The `removedItem` and `addedItem` functions both have the following signature:
|
11637
|
+
|
11638
|
+
```javascript
|
11639
|
+
function (accumulatedValue, item, changeMeta, instanceMeta)
|
11640
|
+
```
|
11641
|
+
|
11642
|
+
`accumulatedValue` - The value returned from the last time
|
11643
|
+
`removedItem` or `addedItem` was called or an empty array.
|
11644
|
+
|
11645
|
+
`item` - the element added or removed from the array
|
11646
|
+
|
11647
|
+
`changeMeta` - An object which contains meta information about the
|
11648
|
+
change. It contains the following properties:
|
11649
|
+
|
11650
|
+
- `property` the computed property
|
11651
|
+
- `propertyName` the name of the property on the object
|
11652
|
+
- `index` the index of the added or removed item
|
11653
|
+
- `item` the added or removed item: this is exactly the same as
|
11654
|
+
the second arg
|
11655
|
+
- `arrayChanged` the array that triggered the change. Can be
|
11656
|
+
useful when depending on multiple arrays.
|
11657
|
+
|
11658
|
+
For property changes triggered on an item property change (when
|
11659
|
+
depKey is something like `someArray.@each.someProperty`),
|
11660
|
+
`changeMeta` will also contain the following property:
|
11661
|
+
|
11662
|
+
- `previousValues` an object whose keys are the properties that changed on
|
11663
|
+
the item, and whose values are the item's previous values.
|
11664
|
+
|
11665
|
+
`previousValues` is important Ember coalesces item property changes via
|
11666
|
+
Ember.run.once. This means that by the time removedItem gets called, item has
|
11667
|
+
the new values, but you may need the previous value (eg for sorting &
|
11668
|
+
filtering).
|
11669
|
+
|
11670
|
+
`instanceMeta` - An object that can be used to store meta
|
11671
|
+
information needed for calculating your computed. For example a
|
11672
|
+
unique computed might use this to store the number of times a given
|
11673
|
+
element is found in the dependent array.
|
11674
|
+
|
11675
|
+
The `removedItem` and `addedItem` functions should return the accumulated
|
11676
|
+
value. It is acceptable to not return anything (ie return undefined)
|
11677
|
+
to invalidate the computation. This is generally not a good idea for
|
11678
|
+
arrayComputed but it's used in eg max and min.
|
11679
|
+
|
11680
|
+
Example
|
11681
|
+
|
11682
|
+
```javascript
|
11683
|
+
Ember.computed.map = function(dependentKey, callback) {
|
11684
|
+
var options = {
|
11685
|
+
addedItem: function(array, item, changeMeta, instanceMeta) {
|
11686
|
+
var mapped = callback(item);
|
11687
|
+
array.insertAt(changeMeta.index, mapped);
|
11688
|
+
return array;
|
11689
|
+
},
|
11690
|
+
removedItem: function(array, item, changeMeta, instanceMeta) {
|
11691
|
+
array.removeAt(changeMeta.index, 1);
|
11692
|
+
return array;
|
11693
|
+
}
|
11694
|
+
};
|
11407
11695
|
|
11696
|
+
return Ember.arrayComputed(dependentKey, options);
|
11697
|
+
};
|
11698
|
+
```
|
11699
|
+
|
11700
|
+
@method arrayComputed
|
11701
|
+
@for Ember
|
11702
|
+
@param {String} [dependentKeys*]
|
11703
|
+
@param {Object} options
|
11704
|
+
@returns {Ember.ComputedProperty}
|
11705
|
+
*/
|
11408
11706
|
Ember.arrayComputed = function (options) {
|
11409
11707
|
var args;
|
11410
11708
|
|
@@ -11431,12 +11729,45 @@ Ember.arrayComputed = function (options) {
|
|
11431
11729
|
|
11432
11730
|
|
11433
11731
|
(function() {
|
11732
|
+
/**
|
11733
|
+
@module ember
|
11734
|
+
@submodule ember-runtime
|
11735
|
+
*/
|
11736
|
+
|
11434
11737
|
var get = Ember.get,
|
11435
11738
|
set = Ember.set,
|
11739
|
+
guidFor = Ember.guidFor,
|
11740
|
+
merge = Ember.merge,
|
11436
11741
|
a_slice = [].slice,
|
11437
11742
|
forEach = Ember.EnumerableUtils.forEach,
|
11438
11743
|
map = Ember.EnumerableUtils.map;
|
11439
11744
|
|
11745
|
+
/**
|
11746
|
+
A computed property that calculates the maximum value in the
|
11747
|
+
dependent array. This will return `-Infinity` when the dependent
|
11748
|
+
array is empty.
|
11749
|
+
|
11750
|
+
Example
|
11751
|
+
|
11752
|
+
```javascript
|
11753
|
+
App.Person = Ember.Object.extend({
|
11754
|
+
childAges: Ember.computed.mapBy('children', 'age'),
|
11755
|
+
maxChildAge: Ember.computed.max('childAges')
|
11756
|
+
});
|
11757
|
+
|
11758
|
+
var lordByron = App.Person.create({children: []});
|
11759
|
+
lordByron.get('maxChildAge'); // -Infinity
|
11760
|
+
lordByron.get('children').pushObject({name: 'Augusta Ada Byron', age: 7});
|
11761
|
+
lordByron.get('maxChildAge'); // 7
|
11762
|
+
lordByron.get('children').pushObjects([{name: 'Allegra Byron', age: 5}, {name: 'Elizabeth Medora Leigh', age: 8}]);
|
11763
|
+
lordByron.get('maxChildAge'); // 8
|
11764
|
+
```
|
11765
|
+
|
11766
|
+
@method computed.max
|
11767
|
+
@for Ember
|
11768
|
+
@param {String} dependentKey
|
11769
|
+
@return {Ember.ComputedProperty} computes the largest value in the dependentKey's array
|
11770
|
+
*/
|
11440
11771
|
Ember.computed.max = function (dependentKey) {
|
11441
11772
|
return Ember.reduceComputed.call(null, dependentKey, {
|
11442
11773
|
initialValue: -Infinity,
|
@@ -11453,6 +11784,32 @@ Ember.computed.max = function (dependentKey) {
|
|
11453
11784
|
});
|
11454
11785
|
};
|
11455
11786
|
|
11787
|
+
/**
|
11788
|
+
A computed property that calculates the minimum value in the
|
11789
|
+
dependent array. This will return `Infinity` when the dependent
|
11790
|
+
array is empty.
|
11791
|
+
|
11792
|
+
Example
|
11793
|
+
|
11794
|
+
```javascript
|
11795
|
+
App.Person = Ember.Object.extend({
|
11796
|
+
childAges: Ember.computed.mapBy('children', 'age'),
|
11797
|
+
minChildAge: Ember.computed.min('childAges')
|
11798
|
+
});
|
11799
|
+
|
11800
|
+
var lordByron = App.Person.create({children: []});
|
11801
|
+
lordByron.get('minChildAge'); // Infinity
|
11802
|
+
lordByron.get('children').pushObject({name: 'Augusta Ada Byron', age: 7});
|
11803
|
+
lordByron.get('minChildAge'); // 7
|
11804
|
+
lordByron.get('children').pushObjects([{name: 'Allegra Byron', age: 5}, {name: 'Elizabeth Medora Leigh', age: 8}]);
|
11805
|
+
lordByron.get('minChildAge'); // 5
|
11806
|
+
```
|
11807
|
+
|
11808
|
+
@method computed.min
|
11809
|
+
@for Ember
|
11810
|
+
@param {String} dependentKey
|
11811
|
+
@return {Ember.ComputedProperty} computes the smallest value in the dependentKey's array
|
11812
|
+
*/
|
11456
11813
|
Ember.computed.min = function (dependentKey) {
|
11457
11814
|
return Ember.reduceComputed.call(null, dependentKey, {
|
11458
11815
|
initialValue: Infinity,
|
@@ -11469,6 +11826,36 @@ Ember.computed.min = function (dependentKey) {
|
|
11469
11826
|
});
|
11470
11827
|
};
|
11471
11828
|
|
11829
|
+
/**
|
11830
|
+
Returns an array mapped via the callback
|
11831
|
+
|
11832
|
+
The callback method you provide should have the following signature:
|
11833
|
+
|
11834
|
+
```javascript
|
11835
|
+
function(item);
|
11836
|
+
```
|
11837
|
+
|
11838
|
+
- `item` is the current item in the iteration.
|
11839
|
+
|
11840
|
+
Example
|
11841
|
+
|
11842
|
+
```javascript
|
11843
|
+
App.Hampster = Ember.Object.extend({
|
11844
|
+
excitingChores: Ember.computed.map('chores', function(chore) {
|
11845
|
+
return chore.toUpperCase() + '!';
|
11846
|
+
})
|
11847
|
+
});
|
11848
|
+
|
11849
|
+
var hampster = App.Hampster.create({chores: ['cook', 'clean', 'write more unit tests']});
|
11850
|
+
hampster.get('excitingChores'); // ['COOK!', 'CLEAN!', 'WRITE MORE UNIT TESTS!']
|
11851
|
+
```
|
11852
|
+
|
11853
|
+
@method computed.map
|
11854
|
+
@for Ember
|
11855
|
+
@param {String} dependentKey
|
11856
|
+
@param {Function} callback
|
11857
|
+
@return {Ember.ComputedProperty} an array mapped via the callback
|
11858
|
+
*/
|
11472
11859
|
Ember.computed.map = function(dependentKey, callback) {
|
11473
11860
|
var options = {
|
11474
11861
|
addedItem: function(array, item, changeMeta, instanceMeta) {
|
@@ -11485,11 +11872,79 @@ Ember.computed.map = function(dependentKey, callback) {
|
|
11485
11872
|
return Ember.arrayComputed(dependentKey, options);
|
11486
11873
|
};
|
11487
11874
|
|
11488
|
-
|
11875
|
+
/**
|
11876
|
+
Returns an array mapped to the specified key.
|
11877
|
+
|
11878
|
+
Example
|
11879
|
+
|
11880
|
+
```javascript
|
11881
|
+
App.Person = Ember.Object.extend({
|
11882
|
+
childAges: Ember.computed.mapBy('children', 'age'),
|
11883
|
+
minChildAge: Ember.computed.min('childAges')
|
11884
|
+
});
|
11885
|
+
|
11886
|
+
var lordByron = App.Person.create({children: []});
|
11887
|
+
lordByron.get('childAge'); // []
|
11888
|
+
lordByron.get('children').pushObject({name: 'Augusta Ada Byron', age: 7});
|
11889
|
+
lordByron.get('childAge'); // [7]
|
11890
|
+
lordByron.get('children').pushObjects([{name: 'Allegra Byron', age: 5}, {name: 'Elizabeth Medora Leigh', age: 8}]);
|
11891
|
+
lordByron.get('childAge'); // [7, 5, 8]
|
11892
|
+
```
|
11893
|
+
|
11894
|
+
@method computed.mapBy
|
11895
|
+
@for Ember
|
11896
|
+
@param {String} dependentKey
|
11897
|
+
@param {String} propertyKey
|
11898
|
+
@return {Ember.ComputedProperty} an array mapped to the specified key
|
11899
|
+
*/
|
11900
|
+
Ember.computed.mapBy = function(dependentKey, propertyKey) {
|
11489
11901
|
var callback = function(item) { return get(item, propertyKey); };
|
11490
11902
|
return Ember.computed.map(dependentKey + '.@each.' + propertyKey, callback);
|
11491
11903
|
};
|
11492
11904
|
|
11905
|
+
/**
|
11906
|
+
@method computed.mapProperty
|
11907
|
+
@for Ember
|
11908
|
+
@deprecated Use `Ember.computed.mapBy` instead
|
11909
|
+
@param dependentKey
|
11910
|
+
@param propertyKey
|
11911
|
+
*/
|
11912
|
+
Ember.computed.mapProperty = Ember.computed.mapBy;
|
11913
|
+
|
11914
|
+
/**
|
11915
|
+
Filters the array by the callback.
|
11916
|
+
|
11917
|
+
The callback method you provide should have the following signature:
|
11918
|
+
|
11919
|
+
```javascript
|
11920
|
+
function(item);
|
11921
|
+
```
|
11922
|
+
|
11923
|
+
- `item` is the current item in the iteration.
|
11924
|
+
|
11925
|
+
Example
|
11926
|
+
|
11927
|
+
```javascript
|
11928
|
+
App.Hampster = Ember.Object.extend({
|
11929
|
+
remainingChores: Ember.computed.filter('chores', function(chore) {
|
11930
|
+
return !chore.done;
|
11931
|
+
})
|
11932
|
+
});
|
11933
|
+
|
11934
|
+
var hampster = App.Hampster.create({chores: [
|
11935
|
+
{name: 'cook', done: true},
|
11936
|
+
{name: 'clean', done: true},
|
11937
|
+
{name: 'write more unit tests', done: false}
|
11938
|
+
]});
|
11939
|
+
hampster.get('remainingChores'); // [{name: 'write more unit tests', done: false}]
|
11940
|
+
```
|
11941
|
+
|
11942
|
+
@method computed.filter
|
11943
|
+
@for Ember
|
11944
|
+
@param {String} dependentKey
|
11945
|
+
@param {Function} callback
|
11946
|
+
@return {Ember.ComputedProperty} the filtered array
|
11947
|
+
*/
|
11493
11948
|
Ember.computed.filter = function(dependentKey, callback) {
|
11494
11949
|
var options = {
|
11495
11950
|
initialize: function (array, changeMeta, instanceMeta) {
|
@@ -11503,6 +11958,8 @@ Ember.computed.filter = function(dependentKey, callback) {
|
|
11503
11958
|
if (match) {
|
11504
11959
|
array.insertAt(filterIndex, item);
|
11505
11960
|
}
|
11961
|
+
|
11962
|
+
return array;
|
11506
11963
|
},
|
11507
11964
|
|
11508
11965
|
removedItem: function(array, item, changeMeta, instanceMeta) {
|
@@ -11511,13 +11968,40 @@ Ember.computed.filter = function(dependentKey, callback) {
|
|
11511
11968
|
if (filterIndex > -1) {
|
11512
11969
|
array.removeAt(filterIndex);
|
11513
11970
|
}
|
11971
|
+
|
11972
|
+
return array;
|
11514
11973
|
}
|
11515
11974
|
};
|
11516
11975
|
|
11517
11976
|
return Ember.arrayComputed(dependentKey, options);
|
11518
11977
|
};
|
11519
11978
|
|
11520
|
-
|
11979
|
+
/**
|
11980
|
+
Filters the array by the property and value
|
11981
|
+
|
11982
|
+
Example
|
11983
|
+
|
11984
|
+
```javascript
|
11985
|
+
App.Hampster = Ember.Object.extend({
|
11986
|
+
remainingChores: Ember.computed.filterBy('chores', 'done', false)
|
11987
|
+
});
|
11988
|
+
|
11989
|
+
var hampster = App.Hampster.create({chores: [
|
11990
|
+
{name: 'cook', done: true},
|
11991
|
+
{name: 'clean', done: true},
|
11992
|
+
{name: 'write more unit tests', done: false}
|
11993
|
+
]});
|
11994
|
+
hampster.get('remainingChores'); // [{name: 'write more unit tests', done: false}]
|
11995
|
+
```
|
11996
|
+
|
11997
|
+
@method computed.filterBy
|
11998
|
+
@for Ember
|
11999
|
+
@param {String} dependentKey
|
12000
|
+
@param {String} propertyKey
|
12001
|
+
@param {String} value
|
12002
|
+
@return {Ember.ComputedProperty} the filtered array
|
12003
|
+
*/
|
12004
|
+
Ember.computed.filterBy = function(dependentKey, propertyKey, value) {
|
11521
12005
|
var callback;
|
11522
12006
|
|
11523
12007
|
if (arguments.length === 2) {
|
@@ -11533,6 +12017,42 @@ Ember.computed.filterProperty = function(dependentKey, propertyKey, value) {
|
|
11533
12017
|
return Ember.computed.filter(dependentKey + '.@each.' + propertyKey, callback);
|
11534
12018
|
};
|
11535
12019
|
|
12020
|
+
/**
|
12021
|
+
@method computed.filterProperty
|
12022
|
+
@for Ember
|
12023
|
+
@param dependentKey
|
12024
|
+
@param propertyKey
|
12025
|
+
@param value
|
12026
|
+
@deprecated Use `Ember.computed.filterBy` instead
|
12027
|
+
*/
|
12028
|
+
Ember.computed.filterProperty = Ember.computed.filterBy;
|
12029
|
+
|
12030
|
+
/**
|
12031
|
+
A computed property which returns a new array with all the unique
|
12032
|
+
elements from one or more dependent arrays.
|
12033
|
+
|
12034
|
+
Example
|
12035
|
+
|
12036
|
+
```javascript
|
12037
|
+
App.Hampster = Ember.Object.extend({
|
12038
|
+
uniqueFruits: Ember.computed.uniq('fruits')
|
12039
|
+
});
|
12040
|
+
|
12041
|
+
var hampster = App.Hampster.create({fruits: [
|
12042
|
+
'banana',
|
12043
|
+
'grape',
|
12044
|
+
'kale',
|
12045
|
+
'banana'
|
12046
|
+
]});
|
12047
|
+
hampster.get('uniqueFruits'); // ['banana', 'grape', 'kale']
|
12048
|
+
```
|
12049
|
+
|
12050
|
+
@method computed.uniq
|
12051
|
+
@for Ember
|
12052
|
+
@param {String} propertyKey*
|
12053
|
+
@return {Ember.ComputedProperty} computes a new array with all the
|
12054
|
+
unique elements from the dependent array
|
12055
|
+
*/
|
11536
12056
|
Ember.computed.uniq = function() {
|
11537
12057
|
var args = a_slice.call(arguments);
|
11538
12058
|
args.push({
|
@@ -11541,7 +12061,7 @@ Ember.computed.uniq = function() {
|
|
11541
12061
|
},
|
11542
12062
|
|
11543
12063
|
addedItem: function(array, item, changeMeta, instanceMeta) {
|
11544
|
-
var guid =
|
12064
|
+
var guid = guidFor(item);
|
11545
12065
|
|
11546
12066
|
if (!instanceMeta.itemCounts[guid]) {
|
11547
12067
|
instanceMeta.itemCounts[guid] = 1;
|
@@ -11552,7 +12072,7 @@ Ember.computed.uniq = function() {
|
|
11552
12072
|
return array;
|
11553
12073
|
},
|
11554
12074
|
removedItem: function(array, item, _, instanceMeta) {
|
11555
|
-
var guid =
|
12075
|
+
var guid = guidFor(item),
|
11556
12076
|
itemCounts = instanceMeta.itemCounts;
|
11557
12077
|
|
11558
12078
|
if (--itemCounts[guid] === 0) {
|
@@ -11563,12 +12083,44 @@ Ember.computed.uniq = function() {
|
|
11563
12083
|
});
|
11564
12084
|
return Ember.arrayComputed.apply(null, args);
|
11565
12085
|
};
|
12086
|
+
|
12087
|
+
/**
|
12088
|
+
Alias for [Ember.computed.uniq](/api/#method_computed_uniq).
|
12089
|
+
|
12090
|
+
@method computed.union
|
12091
|
+
@for Ember
|
12092
|
+
@param {String} propertyKey*
|
12093
|
+
@return {Ember.ComputedProperty} computes a new array with all the
|
12094
|
+
unique elements from the dependent array
|
12095
|
+
*/
|
11566
12096
|
Ember.computed.union = Ember.computed.uniq;
|
11567
12097
|
|
12098
|
+
/**
|
12099
|
+
A computed property which returns a new array with all the duplicated
|
12100
|
+
elements from two or more dependeny arrays.
|
12101
|
+
|
12102
|
+
Example
|
12103
|
+
|
12104
|
+
```javascript
|
12105
|
+
var obj = Ember.Object.createWithMixins({
|
12106
|
+
adaFriends: ['Charles Babbage', 'John Hobhouse', 'William King', 'Mary Somerville'],
|
12107
|
+
charlesFriends: ['William King', 'Mary Somerville', 'Ada Lovelace', 'George Peacock'],
|
12108
|
+
friendsInCommon: Ember.computed.intersect('adaFriends', 'charlesFriends')
|
12109
|
+
});
|
12110
|
+
|
12111
|
+
obj.get('friendsInCommon'); // ['William King', 'Mary Somerville']
|
12112
|
+
```
|
12113
|
+
|
12114
|
+
@method computed.intersect
|
12115
|
+
@for Ember
|
12116
|
+
@param {String} propertyKey*
|
12117
|
+
@return {Ember.ComputedProperty} computes a new array with all the
|
12118
|
+
duplicated elements from the dependent arrays
|
12119
|
+
*/
|
11568
12120
|
Ember.computed.intersect = function () {
|
11569
12121
|
var getDependentKeyGuids = function (changeMeta) {
|
11570
12122
|
return map(changeMeta.property._dependentKeys, function (dependentKey) {
|
11571
|
-
return
|
12123
|
+
return guidFor(dependentKey);
|
11572
12124
|
});
|
11573
12125
|
};
|
11574
12126
|
|
@@ -11579,9 +12131,9 @@ Ember.computed.intersect = function () {
|
|
11579
12131
|
},
|
11580
12132
|
|
11581
12133
|
addedItem: function(array, item, changeMeta, instanceMeta) {
|
11582
|
-
var itemGuid =
|
12134
|
+
var itemGuid = guidFor(item),
|
11583
12135
|
dependentGuids = getDependentKeyGuids(changeMeta),
|
11584
|
-
dependentGuid =
|
12136
|
+
dependentGuid = guidFor(changeMeta.arrayChanged),
|
11585
12137
|
numberOfDependentArrays = changeMeta.property._dependentKeys.length,
|
11586
12138
|
itemCounts = instanceMeta.itemCounts;
|
11587
12139
|
|
@@ -11590,15 +12142,15 @@ Ember.computed.intersect = function () {
|
|
11590
12142
|
|
11591
12143
|
if (++itemCounts[itemGuid][dependentGuid] === 1 &&
|
11592
12144
|
numberOfDependentArrays === Ember.keys(itemCounts[itemGuid]).length) {
|
11593
|
-
|
12145
|
+
|
11594
12146
|
array.addObject(item);
|
11595
12147
|
}
|
11596
12148
|
return array;
|
11597
12149
|
},
|
11598
12150
|
removedItem: function(array, item, changeMeta, instanceMeta) {
|
11599
|
-
var itemGuid =
|
12151
|
+
var itemGuid = guidFor(item),
|
11600
12152
|
dependentGuids = getDependentKeyGuids(changeMeta),
|
11601
|
-
dependentGuid =
|
12153
|
+
dependentGuid = guidFor(changeMeta.arrayChanged),
|
11602
12154
|
numberOfDependentArrays = changeMeta.property._dependentKeys.length,
|
11603
12155
|
numberOfArraysItemAppearsIn,
|
11604
12156
|
itemCounts = instanceMeta.itemCounts;
|
@@ -11619,6 +12171,34 @@ Ember.computed.intersect = function () {
|
|
11619
12171
|
return Ember.arrayComputed.apply(null, args);
|
11620
12172
|
};
|
11621
12173
|
|
12174
|
+
/**
|
12175
|
+
A computed property which returns a new array with all the
|
12176
|
+
properties from the first dependent array that are not in the second
|
12177
|
+
dependent array.
|
12178
|
+
|
12179
|
+
Example
|
12180
|
+
|
12181
|
+
```javascript
|
12182
|
+
App.Hampster = Ember.Object.extend({
|
12183
|
+
likes: ['banana', 'grape', 'kale'],
|
12184
|
+
wants: Ember.computed.setDiff('likes', 'fruits')
|
12185
|
+
});
|
12186
|
+
|
12187
|
+
var hampster = App.Hampster.create({fruits: [
|
12188
|
+
'grape',
|
12189
|
+
'kale',
|
12190
|
+
]});
|
12191
|
+
hampster.get('wants'); // ['banana']
|
12192
|
+
```
|
12193
|
+
|
12194
|
+
@method computed.setDiff
|
12195
|
+
@for Ember
|
12196
|
+
@param {String} setAProperty
|
12197
|
+
@param {String} setBProperty
|
12198
|
+
@return {Ember.ComputedProperty} computes a new array with all the
|
12199
|
+
items from the first dependent array that are not in the second
|
12200
|
+
dependent array
|
12201
|
+
*/
|
11622
12202
|
Ember.computed.setDiff = function (setAProperty, setBProperty) {
|
11623
12203
|
if (arguments.length !== 2) {
|
11624
12204
|
throw new Error("setDiff requires exactly two dependent arrays.");
|
@@ -11627,7 +12207,7 @@ Ember.computed.setDiff = function (setAProperty, setBProperty) {
|
|
11627
12207
|
addedItem: function (array, item, changeMeta, instanceMeta) {
|
11628
12208
|
var setA = get(this, setAProperty),
|
11629
12209
|
setB = get(this, setBProperty);
|
11630
|
-
|
12210
|
+
|
11631
12211
|
if (changeMeta.arrayChanged === setA) {
|
11632
12212
|
if (!setB.contains(item)) {
|
11633
12213
|
array.addObject(item);
|
@@ -11641,7 +12221,7 @@ Ember.computed.setDiff = function (setAProperty, setBProperty) {
|
|
11641
12221
|
removedItem: function (array, item, changeMeta, instanceMeta) {
|
11642
12222
|
var setA = get(this, setAProperty),
|
11643
12223
|
setB = get(this, setBProperty);
|
11644
|
-
|
12224
|
+
|
11645
12225
|
if (changeMeta.arrayChanged === setB) {
|
11646
12226
|
if (setA.contains(item)) {
|
11647
12227
|
array.addObject(item);
|
@@ -11655,7 +12235,7 @@ Ember.computed.setDiff = function (setAProperty, setBProperty) {
|
|
11655
12235
|
};
|
11656
12236
|
|
11657
12237
|
function binarySearch(array, item, low, high) {
|
11658
|
-
var mid, midItem, res;
|
12238
|
+
var mid, midItem, res, guidMid, guidItem;
|
11659
12239
|
|
11660
12240
|
if (arguments.length < 4) { high = get(array, 'length'); }
|
11661
12241
|
if (arguments.length < 3) { low = 0; }
|
@@ -11667,7 +12247,18 @@ function binarySearch(array, item, low, high) {
|
|
11667
12247
|
mid = low + Math.floor((high - low) / 2);
|
11668
12248
|
midItem = array.objectAt(mid);
|
11669
12249
|
|
12250
|
+
guidMid = _guidFor(midItem);
|
12251
|
+
guidItem = _guidFor(item);
|
12252
|
+
|
12253
|
+
if (guidMid === guidItem) {
|
12254
|
+
return mid;
|
12255
|
+
}
|
12256
|
+
|
11670
12257
|
res = this.order(midItem, item);
|
12258
|
+
if (res === 0) {
|
12259
|
+
res = guidMid < guidItem ? -1 : 1;
|
12260
|
+
}
|
12261
|
+
|
11671
12262
|
|
11672
12263
|
if (res < 0) {
|
11673
12264
|
return this.binarySearch(array, item, mid+1, high);
|
@@ -11676,8 +12267,66 @@ function binarySearch(array, item, low, high) {
|
|
11676
12267
|
}
|
11677
12268
|
|
11678
12269
|
return mid;
|
12270
|
+
|
12271
|
+
function _guidFor(item) {
|
12272
|
+
if (Ember.ObjectProxy.detectInstance(item)) {
|
12273
|
+
return guidFor(get(item, 'content'));
|
12274
|
+
}
|
12275
|
+
return guidFor(item);
|
12276
|
+
}
|
11679
12277
|
}
|
11680
12278
|
|
12279
|
+
/**
|
12280
|
+
A computed property which returns a new array with all the
|
12281
|
+
properties from the first dependent array sorted based on a property
|
12282
|
+
or sort function.
|
12283
|
+
|
12284
|
+
The callback method you provide should have the following signature:
|
12285
|
+
|
12286
|
+
```javascript
|
12287
|
+
function(itemA, itemB);
|
12288
|
+
```
|
12289
|
+
|
12290
|
+
- `itemA` the first item to compare.
|
12291
|
+
- `itemB` the second item to compare.
|
12292
|
+
|
12293
|
+
This function should return `-1` when `itemA` should come before
|
12294
|
+
`itemB`. It should return `1` when `itemA` should come after
|
12295
|
+
`itemB`. If the `itemA` and `itemB` are equal this function should return `0`.
|
12296
|
+
|
12297
|
+
Example
|
12298
|
+
|
12299
|
+
```javascript
|
12300
|
+
var ToDoList = Ember.Object.extend({
|
12301
|
+
todosSorting: ['name'],
|
12302
|
+
sortedTodos: Ember.computed.sort('todos', 'todosSorting'),
|
12303
|
+
priorityTodos: Ember.computed.sort('todos', function(a, b){
|
12304
|
+
if (a.priority > b.priority) {
|
12305
|
+
return 1;
|
12306
|
+
} else if (a.priority < b.priority) {
|
12307
|
+
return -1;
|
12308
|
+
}
|
12309
|
+
return 0;
|
12310
|
+
}),
|
12311
|
+
});
|
12312
|
+
var todoList = ToDoList.create({todos: [
|
12313
|
+
{name: 'Unit Test', priority: 2},
|
12314
|
+
{name: 'Documentation', priority: 3},
|
12315
|
+
{name: 'Release', priority: 1}
|
12316
|
+
]});
|
12317
|
+
|
12318
|
+
todoList.get('sortedTodos'); // [{name:'Documentation', priority:3}, {name:'Release', priority:1}, {name:'Unit Test', priority:2}]
|
12319
|
+
todoList.get('priroityTodos'); // [{name:'Release', priority:1}, {name:'Unit Test', priority:2}, {name:'Documentation', priority:3}]
|
12320
|
+
```
|
12321
|
+
|
12322
|
+
@method computed.sort
|
12323
|
+
@for Ember
|
12324
|
+
@param {String} dependentKey
|
12325
|
+
@param {String or Function} sortDefinition a dependent key to an
|
12326
|
+
array of sort properties or a function to use when sorting
|
12327
|
+
@return {Ember.ComputedProperty} computes a new sorted array based
|
12328
|
+
on the sort property array or callback function
|
12329
|
+
*/
|
11681
12330
|
Ember.computed.sort = function (itemsKey, sortDefinition) {
|
11682
12331
|
Ember.assert("Ember.computed.sort requires two arguments: an array key to sort and either a sort properties key or sort function", arguments.length === 2);
|
11683
12332
|
|
@@ -11765,9 +12414,8 @@ Ember.computed.sort = function (itemsKey, sortDefinition) {
|
|
11765
12414
|
removedItem: function (array, item, changeMeta, instanceMeta) {
|
11766
12415
|
var proxyProperties, index, searchItem;
|
11767
12416
|
|
11768
|
-
if (changeMeta.
|
11769
|
-
proxyProperties = { content: item };
|
11770
|
-
proxyProperties[changeMeta.keyChanged] = changeMeta.previousValue;
|
12417
|
+
if (changeMeta.previousValues) {
|
12418
|
+
proxyProperties = merge({ content: item }, changeMeta.previousValues);
|
11771
12419
|
|
11772
12420
|
searchItem = Ember.ObjectProxy.create(proxyProperties);
|
11773
12421
|
} else {
|
@@ -12191,9 +12839,9 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Function) {
|
|
12191
12839
|
Computed properties allow you to treat a function like a property:
|
12192
12840
|
|
12193
12841
|
```javascript
|
12194
|
-
MyApp.
|
12195
|
-
firstName:
|
12196
|
-
lastName:
|
12842
|
+
MyApp.President = Ember.Object.extend({
|
12843
|
+
firstName: '',
|
12844
|
+
lastName: '',
|
12197
12845
|
|
12198
12846
|
fullName: function() {
|
12199
12847
|
return this.get('firstName') + ' ' + this.get('lastName');
|
@@ -12202,7 +12850,12 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Function) {
|
|
12202
12850
|
}.property()
|
12203
12851
|
});
|
12204
12852
|
|
12205
|
-
MyApp.
|
12853
|
+
var president = MyApp.President.create({
|
12854
|
+
firstName: "Barack",
|
12855
|
+
lastName: "Obama"
|
12856
|
+
});
|
12857
|
+
|
12858
|
+
president.get('fullName'); // "Barack Obama"
|
12206
12859
|
```
|
12207
12860
|
|
12208
12861
|
Treating a function like a property is useful because they can work with
|
@@ -12214,9 +12867,9 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Function) {
|
|
12214
12867
|
about these dependencies like this:
|
12215
12868
|
|
12216
12869
|
```javascript
|
12217
|
-
MyApp.
|
12218
|
-
firstName:
|
12219
|
-
lastName:
|
12870
|
+
MyApp.President = Ember.Object.extend({
|
12871
|
+
firstName: '',
|
12872
|
+
lastName: '',
|
12220
12873
|
|
12221
12874
|
fullName: function() {
|
12222
12875
|
return this.get('firstName') + ' ' + this.get('lastName');
|
@@ -12253,15 +12906,18 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Function) {
|
|
12253
12906
|
For example:
|
12254
12907
|
|
12255
12908
|
```javascript
|
12256
|
-
Ember.Object.
|
12909
|
+
Ember.Object.extend({
|
12257
12910
|
valueObserver: function() {
|
12258
12911
|
// Executes whenever the "value" property changes
|
12259
12912
|
}.observes('value')
|
12260
12913
|
});
|
12261
12914
|
```
|
12262
12915
|
|
12263
|
-
|
12264
|
-
|
12916
|
+
In the future this method may become asynchronous. If you want to ensure
|
12917
|
+
synchronous behavior, use `observesImmediately`.
|
12918
|
+
|
12919
|
+
See `Ember.observer`.
|
12920
|
+
|
12265
12921
|
@method observes
|
12266
12922
|
@for Function
|
12267
12923
|
*/
|
@@ -12270,24 +12926,58 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Function) {
|
|
12270
12926
|
return this;
|
12271
12927
|
};
|
12272
12928
|
|
12929
|
+
/**
|
12930
|
+
The `observesImmediately` extension of Javascript's Function prototype is
|
12931
|
+
available when `Ember.EXTEND_PROTOTYPES` or
|
12932
|
+
`Ember.EXTEND_PROTOTYPES.Function` is true, which is the default.
|
12933
|
+
|
12934
|
+
You can observe property changes simply by adding the `observesImmediately`
|
12935
|
+
call to the end of your method declarations in classes that you write.
|
12936
|
+
For example:
|
12937
|
+
|
12938
|
+
```javascript
|
12939
|
+
Ember.Object.extend({
|
12940
|
+
valueObserver: function() {
|
12941
|
+
// Executes immediately after the "value" property changes
|
12942
|
+
}.observesImmediately('value')
|
12943
|
+
});
|
12944
|
+
```
|
12945
|
+
|
12946
|
+
In the future, `observes` may become asynchronous. In this event,
|
12947
|
+
`observesImmediately` will maintain the synchronous behavior.
|
12948
|
+
|
12949
|
+
See `Ember.immediateObserver`.
|
12950
|
+
|
12951
|
+
@method observesImmediately
|
12952
|
+
@for Function
|
12953
|
+
*/
|
12954
|
+
Function.prototype.observesImmediately = function() {
|
12955
|
+
for (var i=0, l=arguments.length; i<l; i++) {
|
12956
|
+
var arg = arguments[i];
|
12957
|
+
Ember.assert("Immediate observers must observe internal properties only, not properties on other objects.", arg.indexOf('.') === -1);
|
12958
|
+
}
|
12959
|
+
|
12960
|
+
return this.observes.apply(this, arguments);
|
12961
|
+
};
|
12962
|
+
|
12273
12963
|
/**
|
12274
12964
|
The `observesBefore` extension of Javascript's Function prototype is
|
12275
12965
|
available when `Ember.EXTEND_PROTOTYPES` or
|
12276
12966
|
`Ember.EXTEND_PROTOTYPES.Function` is true, which is the default.
|
12277
12967
|
|
12278
|
-
You can get notified when a property
|
12968
|
+
You can get notified when a property change is about to happen by
|
12279
12969
|
by adding the `observesBefore` call to the end of your method
|
12280
12970
|
declarations in classes that you write. For example:
|
12281
12971
|
|
12282
12972
|
```javascript
|
12283
|
-
Ember.Object.
|
12973
|
+
Ember.Object.extend({
|
12284
12974
|
valueObserver: function() {
|
12285
12975
|
// Executes whenever the "value" property is about to change
|
12286
12976
|
}.observesBefore('value')
|
12287
12977
|
});
|
12288
12978
|
```
|
12289
12979
|
|
12290
|
-
See `Ember.
|
12980
|
+
See `Ember.beforeObserver`.
|
12291
12981
|
|
12292
12982
|
@method observesBefore
|
12293
12983
|
@for Function
|
@@ -13730,11 +14420,6 @@ Ember.Evented = Ember.Mixin.create({
|
|
13730
14420
|
Ember.sendEvent(this, name, args);
|
13731
14421
|
},
|
13732
14422
|
|
13733
|
-
fire: function(name) {
|
13734
|
-
Ember.deprecate("Ember.Evented#fire() has been deprecated in favor of trigger() for compatibility with jQuery. It will be removed in 1.0. Please update your code to call trigger() instead.");
|
13735
|
-
this.trigger.apply(this, arguments);
|
13736
|
-
},
|
13737
|
-
|
13738
14423
|
/**
|
13739
14424
|
Cancels subscription for given name, target, and method.
|
13740
14425
|
|
@@ -13913,6 +14598,121 @@ Ember.ActionHandler = Ember.Mixin.create({
|
|
13913
14598
|
|
13914
14599
|
|
13915
14600
|
|
14601
|
+
(function() {
|
14602
|
+
var set = Ember.set, get = Ember.get,
|
14603
|
+
resolve = Ember.RSVP.resolve,
|
14604
|
+
rethrow = Ember.RSVP.rethrow,
|
14605
|
+
not = Ember.computed.not,
|
14606
|
+
or = Ember.computed.or;
|
14607
|
+
|
14608
|
+
/**
|
14609
|
+
@module ember
|
14610
|
+
@submodule ember-runtime
|
14611
|
+
*/
|
14612
|
+
|
14613
|
+
function installPromise(proxy, promise) {
|
14614
|
+
promise.then(function(value) {
|
14615
|
+
set(proxy, 'isFulfilled', true);
|
14616
|
+
set(proxy, 'content', value);
|
14617
|
+
|
14618
|
+
return value;
|
14619
|
+
}, function(reason) {
|
14620
|
+
set(proxy, 'isRejected', true);
|
14621
|
+
set(proxy, 'reason', reason);
|
14622
|
+
}).fail(rethrow);
|
14623
|
+
}
|
14624
|
+
|
14625
|
+
/**
|
14626
|
+
A low level mixin making ObjectProxy, ObjectController or ArrayController's promise aware.
|
14627
|
+
|
14628
|
+
```javascript
|
14629
|
+
var ObjectPromiseController = Ember.ObjectController.extend(Ember.PromiseProxyMixin);
|
14630
|
+
|
14631
|
+
var controller = ObjectPromiseController.create({
|
14632
|
+
promise: $.getJSON('/some/remote/data.json')
|
14633
|
+
});
|
14634
|
+
|
14635
|
+
controller.then(function(json){
|
14636
|
+
// the json
|
14637
|
+
}, function(reason) {
|
14638
|
+
// the reason why you have no json
|
14639
|
+
});
|
14640
|
+
```
|
14641
|
+
|
14642
|
+
the controller has bindable attributes which
|
14643
|
+
track the promises life cycle
|
14644
|
+
|
14645
|
+
```javascript
|
14646
|
+
controller.get('isPending') //=> true
|
14647
|
+
controller.get('isSettled') //=> false
|
14648
|
+
controller.get('isRejected') //=> false
|
14649
|
+
controller.get('isFulfilled') //=> false
|
14650
|
+
```
|
14651
|
+
|
14652
|
+
When the the $.getJSON completes, and the promise is fulfilled
|
14653
|
+
with json, the life cycle attributes will update accordingly.
|
14654
|
+
|
14655
|
+
```javascript
|
14656
|
+
controller.get('isPending') //=> false
|
14657
|
+
controller.get('isSettled') //=> true
|
14658
|
+
controller.get('isRejected') //=> false
|
14659
|
+
controller.get('isFulfilled') //=> true
|
14660
|
+
```
|
14661
|
+
|
14662
|
+
As the controller is an ObjectController, and the json now its content,
|
14663
|
+
all the json properties will be available directly from the controller.
|
14664
|
+
|
14665
|
+
```javascript
|
14666
|
+
// Assuming the following json:
|
14667
|
+
{
|
14668
|
+
firstName: 'Stefan',
|
14669
|
+
lastName: 'Penner'
|
14670
|
+
}
|
14671
|
+
|
14672
|
+
// both properties will accessible on the controller
|
14673
|
+
controller.get('firstName') //=> 'Stefan'
|
14674
|
+
controller.get('lastName') //=> 'Penner'
|
14675
|
+
```
|
14676
|
+
|
14677
|
+
If the controller is backing a template, the attributes are
|
14678
|
+
bindable from within that template
|
14679
|
+
```handlebars
|
14680
|
+
{{#if isPending}}
|
14681
|
+
loading...
|
14682
|
+
{{else}}
|
14683
|
+
firstName: {{firstName}}
|
14684
|
+
lastName: {{lastName}}
|
14685
|
+
{{/if}}
|
14686
|
+
```
|
14687
|
+
@class Ember.PromiseProxyMixin
|
14688
|
+
*/
|
14689
|
+
Ember.PromiseProxyMixin = Ember.Mixin.create({
|
14690
|
+
reason: null,
|
14691
|
+
isPending: not('isSettled').readOnly(),
|
14692
|
+
isSettled: or('isRejected', 'isFulfilled').readOnly(),
|
14693
|
+
isRejected: false,
|
14694
|
+
isFulfilled: false,
|
14695
|
+
|
14696
|
+
promise: Ember.computed(function(key, promise) {
|
14697
|
+
if (arguments.length === 2) {
|
14698
|
+
promise = resolve(promise);
|
14699
|
+
installPromise(this, promise);
|
14700
|
+
return promise;
|
14701
|
+
} else {
|
14702
|
+
throw new Error("PromiseProxy's promise must be set");
|
14703
|
+
}
|
14704
|
+
}),
|
14705
|
+
|
14706
|
+
then: function(fulfill, reject) {
|
14707
|
+
return get(this, 'promise').then(fulfill, reject);
|
14708
|
+
}
|
14709
|
+
});
|
14710
|
+
|
14711
|
+
|
14712
|
+
})();
|
14713
|
+
|
14714
|
+
|
14715
|
+
|
13916
14716
|
(function() {
|
13917
14717
|
|
13918
14718
|
})();
|
@@ -15613,7 +16413,9 @@ var get = Ember.get,
|
|
15613
16413
|
removeBeforeObserver = Ember.removeBeforeObserver,
|
15614
16414
|
removeObserver = Ember.removeObserver,
|
15615
16415
|
propertyWillChange = Ember.propertyWillChange,
|
15616
|
-
propertyDidChange = Ember.propertyDidChange
|
16416
|
+
propertyDidChange = Ember.propertyDidChange,
|
16417
|
+
meta = Ember.meta,
|
16418
|
+
defineProperty = Ember.defineProperty;
|
15617
16419
|
|
15618
16420
|
function contentPropertyWillChange(content, contentKey) {
|
15619
16421
|
var key = contentKey.slice(8); // remove "content."
|
@@ -15731,6 +16533,14 @@ Ember.ObjectProxy = Ember.Object.extend(/** @scope Ember.ObjectProxy.prototype *
|
|
15731
16533
|
},
|
15732
16534
|
|
15733
16535
|
setUnknownProperty: function (key, value) {
|
16536
|
+
var m = meta(this);
|
16537
|
+
if (m.proto === this) {
|
16538
|
+
// if marked as prototype then just defineProperty
|
16539
|
+
// rather than delegate
|
16540
|
+
defineProperty(this, key, null, value);
|
16541
|
+
return value;
|
16542
|
+
}
|
16543
|
+
|
15734
16544
|
var content = get(this, 'content');
|
15735
16545
|
Ember.assert(fmt("Cannot delegate set('%@', %@) to the 'content' property of object proxy %@: its 'content' is undefined.", [key, value, this]), content);
|
15736
16546
|
return set(content, key, value);
|
@@ -15738,25 +16548,6 @@ Ember.ObjectProxy = Ember.Object.extend(/** @scope Ember.ObjectProxy.prototype *
|
|
15738
16548
|
|
15739
16549
|
});
|
15740
16550
|
|
15741
|
-
Ember.ObjectProxy.reopenClass({
|
15742
|
-
create: function () {
|
15743
|
-
var mixin, prototype, i, l, properties, keyName;
|
15744
|
-
if (arguments.length) {
|
15745
|
-
prototype = this.proto();
|
15746
|
-
for (i = 0, l = arguments.length; i < l; i++) {
|
15747
|
-
properties = arguments[i];
|
15748
|
-
for (keyName in properties) {
|
15749
|
-
if (!properties.hasOwnProperty(keyName) || keyName in prototype) { continue; }
|
15750
|
-
if (!mixin) mixin = {};
|
15751
|
-
mixin[keyName] = null;
|
15752
|
-
}
|
15753
|
-
}
|
15754
|
-
if (mixin) this._initMixins([mixin]);
|
15755
|
-
}
|
15756
|
-
return this._super.apply(this, arguments);
|
15757
|
-
}
|
15758
|
-
});
|
15759
|
-
|
15760
16551
|
})();
|
15761
16552
|
|
15762
16553
|
|
@@ -15769,7 +16560,8 @@ Ember.ObjectProxy.reopenClass({
|
|
15769
16560
|
|
15770
16561
|
|
15771
16562
|
var set = Ember.set, get = Ember.get, guidFor = Ember.guidFor;
|
15772
|
-
var forEach = Ember.EnumerableUtils.forEach
|
16563
|
+
var forEach = Ember.EnumerableUtils.forEach,
|
16564
|
+
indexOf = Ember.ArrayPolyfills.indexOf;
|
15773
16565
|
|
15774
16566
|
var EachArray = Ember.Object.extend(Ember.Array, {
|
15775
16567
|
|
@@ -15827,7 +16619,7 @@ function removeObserverForContentKey(content, keyName, proxy, idx, loc) {
|
|
15827
16619
|
|
15828
16620
|
guid = guidFor(item);
|
15829
16621
|
indicies = objects[guid];
|
15830
|
-
indicies[
|
16622
|
+
indicies[indexOf.call(indicies, loc)] = null;
|
15831
16623
|
}
|
15832
16624
|
}
|
15833
16625
|
}
|
@@ -16752,7 +17544,7 @@ Ember.ControllerMixin = Ember.Mixin.create(Ember.ActionHandler, {
|
|
16752
17544
|
deprecatedSend: function(actionName) {
|
16753
17545
|
var args = [].slice.call(arguments, 1);
|
16754
17546
|
Ember.assert('' + this + " has the action " + actionName + " but it is not a function", typeof this[actionName] === 'function');
|
16755
|
-
Ember.deprecate('Action handlers implemented directly on controllers are deprecated in favor of action handlers on an `actions` object', false);
|
17547
|
+
Ember.deprecate('Action handlers implemented directly on controllers are deprecated in favor of action handlers on an `actions` object (' + actionName + ' on ' + this + ')', false);
|
16756
17548
|
this[actionName].apply(this, args);
|
16757
17549
|
return;
|
16758
17550
|
}
|
@@ -17232,11 +18024,15 @@ Ember.ArrayController = Ember.ArrayProxy.extend(Ember.ControllerMixin,
|
|
17232
18024
|
},
|
17233
18025
|
|
17234
18026
|
init: function() {
|
17235
|
-
if (!this.get('content')) { Ember.defineProperty(this, 'content', undefined, Ember.A()); }
|
17236
18027
|
this._super();
|
18028
|
+
|
17237
18029
|
this.set('_subControllers', Ember.A());
|
17238
18030
|
},
|
17239
18031
|
|
18032
|
+
content: Ember.computed(function () {
|
18033
|
+
return Ember.A();
|
18034
|
+
}),
|
18035
|
+
|
17240
18036
|
controllerAt: function(idx, object, controllerClass) {
|
17241
18037
|
var container = get(this, 'container'),
|
17242
18038
|
subControllers = get(this, '_subControllers'),
|
@@ -17322,1489 +18118,5 @@ Ember Runtime
|
|
17322
18118
|
|
17323
18119
|
})();
|
17324
18120
|
|
17325
|
-
(function() {
|
17326
|
-
var get = Ember.get, set = Ember.set;
|
17327
|
-
|
17328
|
-
/**
|
17329
|
-
@module ember
|
17330
|
-
@submodule ember-states
|
17331
|
-
*/
|
17332
|
-
|
17333
|
-
/**
|
17334
|
-
The State class allows you to define individual states within a finite state machine
|
17335
|
-
inside your Ember application.
|
17336
|
-
|
17337
|
-
### How States Work
|
17338
|
-
|
17339
|
-
When you setup a finite state machine this means you are setting up a mechanism to precisely
|
17340
|
-
manage the change within a system. You can control the various states or modes that your
|
17341
|
-
application can be in at any given time. Additionally, you can manage what specific states
|
17342
|
-
are allowed to transition to other states.
|
17343
|
-
|
17344
|
-
The state machine is in only one state at a time. This state is known as the current state.
|
17345
|
-
It is possible to change from one state to another by a triggering event or condition.
|
17346
|
-
This is called a transition.
|
17347
|
-
|
17348
|
-
Finite state machines are important because they allow the application developer to be
|
17349
|
-
deterministic about the the sequence of events that can happen within a system. Some states
|
17350
|
-
cannot be entered when the application is a given state.
|
17351
|
-
|
17352
|
-
For example:
|
17353
|
-
|
17354
|
-
A door that is in the `locked` state cannot be `opened` (you must transition to the `unlocked`
|
17355
|
-
state first).
|
17356
|
-
|
17357
|
-
A door that is in the `open` state cannot be `locked` (you must transition to the `closed`
|
17358
|
-
state first).
|
17359
|
-
|
17360
|
-
|
17361
|
-
Each state instance has the following characteristics:
|
17362
|
-
|
17363
|
-
- Zero or more parent states
|
17364
|
-
- A start state
|
17365
|
-
- A name
|
17366
|
-
- A path (a computed value that prefixes parent states and the complete hierarchy to itself )
|
17367
|
-
|
17368
|
-
A state is known as a "leafState" when it is the last item on the path and has no children
|
17369
|
-
beneath it.
|
17370
|
-
|
17371
|
-
The isLeaf property returns a boolean.
|
17372
|
-
|
17373
|
-
Each state can emit the following transition events
|
17374
|
-
|
17375
|
-
- setup
|
17376
|
-
- enter
|
17377
|
-
- exit
|
17378
|
-
|
17379
|
-
A state object is ususally created in the context of a state manager.
|
17380
|
-
|
17381
|
-
```javascript
|
17382
|
-
doorStateManager = Ember.StateManager.create({
|
17383
|
-
locked: Ember.State.create(),
|
17384
|
-
closed: Ember.State.create(),
|
17385
|
-
unlocked: Ember.State.create(),
|
17386
|
-
open: Ember.State.create()
|
17387
|
-
});
|
17388
|
-
```
|
17389
|
-
|
17390
|
-
@class State
|
17391
|
-
@namespace Ember
|
17392
|
-
@extends Ember.Object
|
17393
|
-
@uses Ember.Evented
|
17394
|
-
*/
|
17395
|
-
Ember.State = Ember.Object.extend(Ember.Evented,
|
17396
|
-
/** @scope Ember.State.prototype */{
|
17397
|
-
/**
|
17398
|
-
A reference to the parent state.
|
17399
|
-
|
17400
|
-
@property parentState
|
17401
|
-
@type Ember.State
|
17402
|
-
*/
|
17403
|
-
parentState: null,
|
17404
|
-
start: null,
|
17405
|
-
|
17406
|
-
/**
|
17407
|
-
The name of this state.
|
17408
|
-
|
17409
|
-
@property name
|
17410
|
-
@type String
|
17411
|
-
*/
|
17412
|
-
name: null,
|
17413
|
-
|
17414
|
-
/**
|
17415
|
-
The full path to this state.
|
17416
|
-
|
17417
|
-
@property path
|
17418
|
-
@type String
|
17419
|
-
*/
|
17420
|
-
path: Ember.computed(function() {
|
17421
|
-
var parentPath = get(this, 'parentState.path'),
|
17422
|
-
path = get(this, 'name');
|
17423
|
-
|
17424
|
-
if (parentPath) {
|
17425
|
-
path = parentPath + '.' + path;
|
17426
|
-
}
|
17427
|
-
|
17428
|
-
return path;
|
17429
|
-
}),
|
17430
|
-
|
17431
|
-
/**
|
17432
|
-
@private
|
17433
|
-
|
17434
|
-
Override the default event firing from `Ember.Evented` to
|
17435
|
-
also call methods with the given name.
|
17436
|
-
|
17437
|
-
@method trigger
|
17438
|
-
@param name
|
17439
|
-
*/
|
17440
|
-
trigger: function(name) {
|
17441
|
-
if (this[name]) {
|
17442
|
-
this[name].apply(this, [].slice.call(arguments, 1));
|
17443
|
-
}
|
17444
|
-
this._super.apply(this, arguments);
|
17445
|
-
},
|
17446
|
-
|
17447
|
-
/**
|
17448
|
-
Initialize Ember.State object
|
17449
|
-
Sets childStates to Ember.NativeArray
|
17450
|
-
Sets eventTransitions to empty object unless already defined.
|
17451
|
-
Loops over properties of this state and ensures that any property that
|
17452
|
-
is an instance of Ember.State is moved to `states` hash.
|
17453
|
-
|
17454
|
-
|
17455
|
-
@method init
|
17456
|
-
*/
|
17457
|
-
init: function() {
|
17458
|
-
var states = get(this, 'states');
|
17459
|
-
set(this, 'childStates', Ember.A());
|
17460
|
-
set(this, 'eventTransitions', get(this, 'eventTransitions') || {});
|
17461
|
-
|
17462
|
-
var name, value, transitionTarget;
|
17463
|
-
|
17464
|
-
// As a convenience, loop over the properties
|
17465
|
-
// of this state and look for any that are other
|
17466
|
-
// Ember.State instances or classes, and move them
|
17467
|
-
// to the `states` hash. This avoids having to
|
17468
|
-
// create an explicit separate hash.
|
17469
|
-
|
17470
|
-
if (!states) {
|
17471
|
-
states = {};
|
17472
|
-
|
17473
|
-
for (name in this) {
|
17474
|
-
if (name === "constructor") { continue; }
|
17475
|
-
|
17476
|
-
if (value = this[name]) {
|
17477
|
-
if (transitionTarget = value.transitionTarget) {
|
17478
|
-
this.eventTransitions[name] = transitionTarget;
|
17479
|
-
}
|
17480
|
-
|
17481
|
-
this.setupChild(states, name, value);
|
17482
|
-
}
|
17483
|
-
}
|
17484
|
-
|
17485
|
-
set(this, 'states', states);
|
17486
|
-
} else {
|
17487
|
-
for (name in states) {
|
17488
|
-
this.setupChild(states, name, states[name]);
|
17489
|
-
}
|
17490
|
-
}
|
17491
|
-
|
17492
|
-
// pathsCaches is a nested hash of the form:
|
17493
|
-
// pathsCaches[stateManagerTypeGuid][path] == transitions_hash
|
17494
|
-
set(this, 'pathsCaches', {});
|
17495
|
-
},
|
17496
|
-
|
17497
|
-
/**
|
17498
|
-
Sets a cached instance of the state. Ember.guidFor is used
|
17499
|
-
to find the guid of the associated state manager. If a cache can be found
|
17500
|
-
the state path is added to that cache, otherwise an empty JavaScript object
|
17501
|
-
is created. And the state path is appended to that instead.
|
17502
|
-
|
17503
|
-
@method setPathsCache
|
17504
|
-
@param stateManager
|
17505
|
-
@param path
|
17506
|
-
@param transitions
|
17507
|
-
*/
|
17508
|
-
setPathsCache: function(stateManager, path, transitions) {
|
17509
|
-
var stateManagerTypeGuid = Ember.guidFor(stateManager.constructor),
|
17510
|
-
pathsCaches = get(this, 'pathsCaches'),
|
17511
|
-
pathsCacheForManager = pathsCaches[stateManagerTypeGuid] || {};
|
17512
|
-
|
17513
|
-
pathsCacheForManager[path] = transitions;
|
17514
|
-
pathsCaches[stateManagerTypeGuid] = pathsCacheForManager;
|
17515
|
-
},
|
17516
|
-
|
17517
|
-
/**
|
17518
|
-
Returns a cached path for the state instance. Each state manager
|
17519
|
-
has a GUID and this is used to look up a cached path if it has already
|
17520
|
-
been created. If a cached path is not found an empty JavaScript object
|
17521
|
-
is returned instead.
|
17522
|
-
|
17523
|
-
@method getPathsCache
|
17524
|
-
@param stateManager
|
17525
|
-
@param path
|
17526
|
-
*/
|
17527
|
-
getPathsCache: function(stateManager, path) {
|
17528
|
-
var stateManagerTypeGuid = Ember.guidFor(stateManager.constructor),
|
17529
|
-
pathsCaches = get(this, 'pathsCaches'),
|
17530
|
-
pathsCacheForManager = pathsCaches[stateManagerTypeGuid] || {};
|
17531
|
-
|
17532
|
-
return pathsCacheForManager[path];
|
17533
|
-
},
|
17534
|
-
|
17535
|
-
/**
|
17536
|
-
@private
|
17537
|
-
|
17538
|
-
Create the child instance and ensure that it is an instance of Ember.State
|
17539
|
-
|
17540
|
-
@method setupChild
|
17541
|
-
@param states
|
17542
|
-
@param name
|
17543
|
-
@param value
|
17544
|
-
*/
|
17545
|
-
setupChild: function(states, name, value) {
|
17546
|
-
if (!value) { return false; }
|
17547
|
-
var instance;
|
17548
|
-
|
17549
|
-
if (value instanceof Ember.State) {
|
17550
|
-
set(value, 'name', name);
|
17551
|
-
instance = value;
|
17552
|
-
instance.container = this.container;
|
17553
|
-
} else if (Ember.State.detect(value)) {
|
17554
|
-
instance = value.create({
|
17555
|
-
name: name,
|
17556
|
-
container: this.container
|
17557
|
-
});
|
17558
|
-
}
|
17559
|
-
|
17560
|
-
if (instance instanceof Ember.State) {
|
17561
|
-
set(instance, 'parentState', this);
|
17562
|
-
get(this, 'childStates').pushObject(instance);
|
17563
|
-
states[name] = instance;
|
17564
|
-
return instance;
|
17565
|
-
}
|
17566
|
-
},
|
17567
|
-
|
17568
|
-
/**
|
17569
|
-
@private
|
17570
|
-
|
17571
|
-
@method lookupEventTransition
|
17572
|
-
@param name
|
17573
|
-
*/
|
17574
|
-
lookupEventTransition: function(name) {
|
17575
|
-
var path, state = this;
|
17576
|
-
|
17577
|
-
while(state && !path) {
|
17578
|
-
path = state.eventTransitions[name];
|
17579
|
-
state = state.get('parentState');
|
17580
|
-
}
|
17581
|
-
|
17582
|
-
return path;
|
17583
|
-
},
|
17584
|
-
|
17585
|
-
/**
|
17586
|
-
A Boolean value indicating whether the state is a leaf state
|
17587
|
-
in the state hierarchy. This is `false` if the state has child
|
17588
|
-
states; otherwise it is true.
|
17589
|
-
|
17590
|
-
@property isLeaf
|
17591
|
-
@type Boolean
|
17592
|
-
*/
|
17593
|
-
isLeaf: Ember.computed(function() {
|
17594
|
-
return !get(this, 'childStates').length;
|
17595
|
-
}),
|
17596
|
-
|
17597
|
-
/**
|
17598
|
-
A boolean value indicating whether the state takes a context.
|
17599
|
-
By default we assume all states take contexts.
|
17600
|
-
|
17601
|
-
@property hasContext
|
17602
|
-
@default true
|
17603
|
-
*/
|
17604
|
-
hasContext: true,
|
17605
|
-
|
17606
|
-
/**
|
17607
|
-
This is the default transition event.
|
17608
|
-
|
17609
|
-
@event setup
|
17610
|
-
@param {Ember.StateManager} manager
|
17611
|
-
@param context
|
17612
|
-
@see Ember.StateManager#transitionEvent
|
17613
|
-
*/
|
17614
|
-
setup: Ember.K,
|
17615
|
-
|
17616
|
-
/**
|
17617
|
-
This event fires when the state is entered.
|
17618
|
-
|
17619
|
-
@event enter
|
17620
|
-
@param {Ember.StateManager} manager
|
17621
|
-
*/
|
17622
|
-
enter: Ember.K,
|
17623
|
-
|
17624
|
-
/**
|
17625
|
-
This event fires when the state is exited.
|
17626
|
-
|
17627
|
-
@event exit
|
17628
|
-
@param {Ember.StateManager} manager
|
17629
|
-
*/
|
17630
|
-
exit: Ember.K
|
17631
|
-
});
|
17632
|
-
|
17633
|
-
Ember.State.reopenClass({
|
17634
|
-
|
17635
|
-
/**
|
17636
|
-
Creates an action function for transitioning to the named state while
|
17637
|
-
preserving context.
|
17638
|
-
|
17639
|
-
The following example StateManagers are equivalent:
|
17640
|
-
|
17641
|
-
```javascript
|
17642
|
-
aManager = Ember.StateManager.create({
|
17643
|
-
stateOne: Ember.State.create({
|
17644
|
-
changeToStateTwo: Ember.State.transitionTo('stateTwo')
|
17645
|
-
}),
|
17646
|
-
stateTwo: Ember.State.create({})
|
17647
|
-
})
|
17648
|
-
|
17649
|
-
bManager = Ember.StateManager.create({
|
17650
|
-
stateOne: Ember.State.create({
|
17651
|
-
changeToStateTwo: function(manager, context) {
|
17652
|
-
manager.transitionTo('stateTwo', context)
|
17653
|
-
}
|
17654
|
-
}),
|
17655
|
-
stateTwo: Ember.State.create({})
|
17656
|
-
})
|
17657
|
-
```
|
17658
|
-
|
17659
|
-
@method transitionTo
|
17660
|
-
@static
|
17661
|
-
@param {String} target
|
17662
|
-
*/
|
17663
|
-
|
17664
|
-
transitionTo: function(target) {
|
17665
|
-
|
17666
|
-
var transitionFunction = function(stateManager, contextOrEvent) {
|
17667
|
-
var contexts = [],
|
17668
|
-
Event = Ember.$ && Ember.$.Event;
|
17669
|
-
|
17670
|
-
if (contextOrEvent && (Event && contextOrEvent instanceof Event)) {
|
17671
|
-
if (contextOrEvent.hasOwnProperty('contexts')) {
|
17672
|
-
contexts = contextOrEvent.contexts.slice();
|
17673
|
-
}
|
17674
|
-
}
|
17675
|
-
else {
|
17676
|
-
contexts = [].slice.call(arguments, 1);
|
17677
|
-
}
|
17678
|
-
|
17679
|
-
contexts.unshift(target);
|
17680
|
-
stateManager.transitionTo.apply(stateManager, contexts);
|
17681
|
-
};
|
17682
|
-
|
17683
|
-
transitionFunction.transitionTarget = target;
|
17684
|
-
|
17685
|
-
return transitionFunction;
|
17686
|
-
}
|
17687
|
-
|
17688
|
-
});
|
17689
|
-
|
17690
|
-
})();
|
17691
|
-
|
17692
|
-
|
17693
|
-
|
17694
|
-
(function() {
|
17695
|
-
/**
|
17696
|
-
@module ember
|
17697
|
-
@submodule ember-states
|
17698
|
-
*/
|
17699
|
-
|
17700
|
-
var get = Ember.get, set = Ember.set, fmt = Ember.String.fmt;
|
17701
|
-
var arrayForEach = Ember.ArrayPolyfills.forEach;
|
17702
|
-
/**
|
17703
|
-
A Transition takes the enter, exit and resolve states and normalizes
|
17704
|
-
them:
|
17705
|
-
|
17706
|
-
* takes any passed in contexts into consideration
|
17707
|
-
* adds in `initialState`s
|
17708
|
-
|
17709
|
-
@class Transition
|
17710
|
-
@private
|
17711
|
-
*/
|
17712
|
-
var Transition = function(raw) {
|
17713
|
-
this.enterStates = raw.enterStates.slice();
|
17714
|
-
this.exitStates = raw.exitStates.slice();
|
17715
|
-
this.resolveState = raw.resolveState;
|
17716
|
-
|
17717
|
-
this.finalState = raw.enterStates[raw.enterStates.length - 1] || raw.resolveState;
|
17718
|
-
};
|
17719
|
-
|
17720
|
-
Transition.prototype = {
|
17721
|
-
/**
|
17722
|
-
Normalize the passed in enter, exit and resolve states.
|
17723
|
-
|
17724
|
-
This process also adds `finalState` and `contexts` to the Transition object.
|
17725
|
-
|
17726
|
-
@method normalize
|
17727
|
-
@param {Ember.StateManager} manager the state manager running the transition
|
17728
|
-
@param {Array} contexts a list of contexts passed into `transitionTo`
|
17729
|
-
*/
|
17730
|
-
normalize: function(manager, contexts) {
|
17731
|
-
this.matchContextsToStates(contexts);
|
17732
|
-
this.addInitialStates();
|
17733
|
-
this.removeUnchangedContexts(manager);
|
17734
|
-
return this;
|
17735
|
-
},
|
17736
|
-
|
17737
|
-
/**
|
17738
|
-
Match each of the contexts passed to `transitionTo` to a state.
|
17739
|
-
This process may also require adding additional enter and exit
|
17740
|
-
states if there are more contexts than enter states.
|
17741
|
-
|
17742
|
-
@method matchContextsToStates
|
17743
|
-
@param {Array} contexts a list of contexts passed into `transitionTo`
|
17744
|
-
*/
|
17745
|
-
matchContextsToStates: function(contexts) {
|
17746
|
-
var stateIdx = this.enterStates.length - 1,
|
17747
|
-
matchedContexts = [],
|
17748
|
-
state,
|
17749
|
-
context;
|
17750
|
-
|
17751
|
-
// Next, we will match the passed in contexts to the states they
|
17752
|
-
// represent.
|
17753
|
-
//
|
17754
|
-
// First, assign a context to each enter state in reverse order. If
|
17755
|
-
// any contexts are left, add a parent state to the list of states
|
17756
|
-
// to enter and exit, and assign a context to the parent state.
|
17757
|
-
//
|
17758
|
-
// If there are still contexts left when the state manager is
|
17759
|
-
// reached, raise an exception.
|
17760
|
-
//
|
17761
|
-
// This allows the following:
|
17762
|
-
//
|
17763
|
-
// |- root
|
17764
|
-
// | |- post
|
17765
|
-
// | | |- comments
|
17766
|
-
// | |- about (* current state)
|
17767
|
-
//
|
17768
|
-
// For `transitionTo('post.comments', post, post.get('comments')`,
|
17769
|
-
// the first context (`post`) will be assigned to `root.post`, and
|
17770
|
-
// the second context (`post.get('comments')`) will be assigned
|
17771
|
-
// to `root.post.comments`.
|
17772
|
-
//
|
17773
|
-
// For the following:
|
17774
|
-
//
|
17775
|
-
// |- root
|
17776
|
-
// | |- post
|
17777
|
-
// | | |- index (* current state)
|
17778
|
-
// | | |- comments
|
17779
|
-
//
|
17780
|
-
// For `transitionTo('post.comments', otherPost, otherPost.get('comments')`,
|
17781
|
-
// the `<root.post>` state will be added to the list of enter and exit
|
17782
|
-
// states because its context has changed.
|
17783
|
-
|
17784
|
-
while (contexts.length > 0) {
|
17785
|
-
if (stateIdx >= 0) {
|
17786
|
-
state = this.enterStates[stateIdx--];
|
17787
|
-
} else {
|
17788
|
-
if (this.enterStates.length) {
|
17789
|
-
state = get(this.enterStates[0], 'parentState');
|
17790
|
-
if (!state) { throw "Cannot match all contexts to states"; }
|
17791
|
-
} else {
|
17792
|
-
// If re-entering the current state with a context, the resolve
|
17793
|
-
// state will be the current state.
|
17794
|
-
state = this.resolveState;
|
17795
|
-
}
|
17796
|
-
|
17797
|
-
this.enterStates.unshift(state);
|
17798
|
-
this.exitStates.unshift(state);
|
17799
|
-
}
|
17800
|
-
|
17801
|
-
// in routers, only states with dynamic segments have a context
|
17802
|
-
if (get(state, 'hasContext')) {
|
17803
|
-
context = contexts.pop();
|
17804
|
-
} else {
|
17805
|
-
context = null;
|
17806
|
-
}
|
17807
|
-
|
17808
|
-
matchedContexts.unshift(context);
|
17809
|
-
}
|
17810
|
-
|
17811
|
-
this.contexts = matchedContexts;
|
17812
|
-
},
|
17813
|
-
|
17814
|
-
/**
|
17815
|
-
Add any `initialState`s to the list of enter states.
|
17816
|
-
|
17817
|
-
@method addInitialStates
|
17818
|
-
*/
|
17819
|
-
addInitialStates: function() {
|
17820
|
-
var finalState = this.finalState, initialState;
|
17821
|
-
|
17822
|
-
while(true) {
|
17823
|
-
initialState = get(finalState, 'initialState') || 'start';
|
17824
|
-
finalState = get(finalState, 'states.' + initialState);
|
17825
|
-
|
17826
|
-
if (!finalState) { break; }
|
17827
|
-
|
17828
|
-
this.finalState = finalState;
|
17829
|
-
this.enterStates.push(finalState);
|
17830
|
-
this.contexts.push(undefined);
|
17831
|
-
}
|
17832
|
-
},
|
17833
|
-
|
17834
|
-
/**
|
17835
|
-
Remove any states that were added because the number of contexts
|
17836
|
-
exceeded the number of explicit enter states, but the context has
|
17837
|
-
not changed since the last time the state was entered.
|
17838
|
-
|
17839
|
-
@method removeUnchangedContexts
|
17840
|
-
@param {Ember.StateManager} manager passed in to look up the last
|
17841
|
-
context for a state
|
17842
|
-
*/
|
17843
|
-
removeUnchangedContexts: function(manager) {
|
17844
|
-
// Start from the beginning of the enter states. If the state was added
|
17845
|
-
// to the list during the context matching phase, make sure the context
|
17846
|
-
// has actually changed since the last time the state was entered.
|
17847
|
-
while (this.enterStates.length > 0) {
|
17848
|
-
if (this.enterStates[0] !== this.exitStates[0]) { break; }
|
17849
|
-
|
17850
|
-
if (this.enterStates.length === this.contexts.length) {
|
17851
|
-
if (manager.getStateMeta(this.enterStates[0], 'context') !== this.contexts[0]) { break; }
|
17852
|
-
this.contexts.shift();
|
17853
|
-
}
|
17854
|
-
|
17855
|
-
this.resolveState = this.enterStates.shift();
|
17856
|
-
this.exitStates.shift();
|
17857
|
-
}
|
17858
|
-
}
|
17859
|
-
};
|
17860
|
-
|
17861
|
-
|
17862
|
-
/**
|
17863
|
-
Sends the event to the currentState, if the event is not handled this method
|
17864
|
-
will proceed to call the parentState recursively until it encounters an
|
17865
|
-
event handler or reaches the top or root of the state path hierarchy.
|
17866
|
-
|
17867
|
-
@method sendRecursively
|
17868
|
-
@param event
|
17869
|
-
@param currentState
|
17870
|
-
@param isUnhandledPass
|
17871
|
-
*/
|
17872
|
-
var sendRecursively = function(event, currentState, isUnhandledPass) {
|
17873
|
-
var log = this.enableLogging,
|
17874
|
-
eventName = isUnhandledPass ? 'unhandledEvent' : event,
|
17875
|
-
action = currentState[eventName],
|
17876
|
-
contexts, sendRecursiveArguments, actionArguments;
|
17877
|
-
|
17878
|
-
contexts = [].slice.call(arguments, 3);
|
17879
|
-
|
17880
|
-
// Test to see if the action is a method that
|
17881
|
-
// can be invoked. Don't blindly check just for
|
17882
|
-
// existence, because it is possible the state
|
17883
|
-
// manager has a child state of the given name,
|
17884
|
-
// and we should still raise an exception in that
|
17885
|
-
// case.
|
17886
|
-
if (typeof action === 'function') {
|
17887
|
-
if (log) {
|
17888
|
-
if (isUnhandledPass) {
|
17889
|
-
Ember.Logger.log(fmt("STATEMANAGER: Unhandled event '%@' being sent to state %@.", [event, get(currentState, 'path')]));
|
17890
|
-
} else {
|
17891
|
-
Ember.Logger.log(fmt("STATEMANAGER: Sending event '%@' to state %@.", [event, get(currentState, 'path')]));
|
17892
|
-
}
|
17893
|
-
}
|
17894
|
-
|
17895
|
-
actionArguments = contexts;
|
17896
|
-
if (isUnhandledPass) {
|
17897
|
-
actionArguments.unshift(event);
|
17898
|
-
}
|
17899
|
-
actionArguments.unshift(this);
|
17900
|
-
|
17901
|
-
return action.apply(currentState, actionArguments);
|
17902
|
-
} else {
|
17903
|
-
var parentState = get(currentState, 'parentState');
|
17904
|
-
if (parentState) {
|
17905
|
-
|
17906
|
-
sendRecursiveArguments = contexts;
|
17907
|
-
sendRecursiveArguments.unshift(event, parentState, isUnhandledPass);
|
17908
|
-
|
17909
|
-
return sendRecursively.apply(this, sendRecursiveArguments);
|
17910
|
-
} else if (!isUnhandledPass) {
|
17911
|
-
return sendEvent.call(this, event, contexts, true);
|
17912
|
-
}
|
17913
|
-
}
|
17914
|
-
};
|
17915
|
-
|
17916
|
-
/**
|
17917
|
-
Send an event to the currentState.
|
17918
|
-
|
17919
|
-
@method sendEvent
|
17920
|
-
@param eventName
|
17921
|
-
@param sendRecursiveArguments
|
17922
|
-
@param isUnhandledPass
|
17923
|
-
*/
|
17924
|
-
var sendEvent = function(eventName, sendRecursiveArguments, isUnhandledPass) {
|
17925
|
-
sendRecursiveArguments.unshift(eventName, get(this, 'currentState'), isUnhandledPass);
|
17926
|
-
return sendRecursively.apply(this, sendRecursiveArguments);
|
17927
|
-
};
|
17928
|
-
|
17929
|
-
/**
|
17930
|
-
StateManager is part of Ember's implementation of a finite state machine. A
|
17931
|
-
StateManager instance manages a number of properties that are instances of
|
17932
|
-
`Ember.State`,
|
17933
|
-
tracks the current active state, and triggers callbacks when states have changed.
|
17934
|
-
|
17935
|
-
## Defining States
|
17936
|
-
|
17937
|
-
The states of StateManager can be declared in one of two ways. First, you can
|
17938
|
-
define a `states` property that contains all the states:
|
17939
|
-
|
17940
|
-
```javascript
|
17941
|
-
var managerA = Ember.StateManager.create({
|
17942
|
-
states: {
|
17943
|
-
stateOne: Ember.State.create(),
|
17944
|
-
stateTwo: Ember.State.create()
|
17945
|
-
}
|
17946
|
-
});
|
17947
|
-
|
17948
|
-
managerA.get('states');
|
17949
|
-
// {
|
17950
|
-
// stateOne: Ember.State.create(),
|
17951
|
-
// stateTwo: Ember.State.create()
|
17952
|
-
// }
|
17953
|
-
```
|
17954
|
-
|
17955
|
-
You can also add instances of `Ember.State` (or an `Ember.State` subclass)
|
17956
|
-
directly as properties of a StateManager. These states will be collected into
|
17957
|
-
the `states` property for you.
|
17958
|
-
|
17959
|
-
```javascript
|
17960
|
-
var managerA = Ember.StateManager.create({
|
17961
|
-
stateOne: Ember.State.create(),
|
17962
|
-
stateTwo: Ember.State.create()
|
17963
|
-
});
|
17964
|
-
|
17965
|
-
managerA.get('states');
|
17966
|
-
// {
|
17967
|
-
// stateOne: Ember.State.create(),
|
17968
|
-
// stateTwo: Ember.State.create()
|
17969
|
-
// }
|
17970
|
-
```
|
17971
|
-
|
17972
|
-
## The Initial State
|
17973
|
-
|
17974
|
-
When created, a StateManager instance will immediately enter into the state
|
17975
|
-
defined as its `start` property or the state referenced by name in its
|
17976
|
-
`initialState` property:
|
17977
|
-
|
17978
|
-
```javascript
|
17979
|
-
var managerA = Ember.StateManager.create({
|
17980
|
-
start: Ember.State.create({})
|
17981
|
-
});
|
17982
|
-
|
17983
|
-
managerA.get('currentState.name'); // 'start'
|
17984
|
-
|
17985
|
-
var managerB = Ember.StateManager.create({
|
17986
|
-
initialState: 'beginHere',
|
17987
|
-
beginHere: Ember.State.create({})
|
17988
|
-
});
|
17989
|
-
|
17990
|
-
managerB.get('currentState.name'); // 'beginHere'
|
17991
|
-
```
|
17992
|
-
|
17993
|
-
Because it is a property you may also provide a computed function if you wish
|
17994
|
-
to derive an `initialState` programmatically:
|
17995
|
-
|
17996
|
-
```javascript
|
17997
|
-
var managerC = Ember.StateManager.create({
|
17998
|
-
initialState: function() {
|
17999
|
-
if (someLogic) {
|
18000
|
-
return 'active';
|
18001
|
-
} else {
|
18002
|
-
return 'passive';
|
18003
|
-
}
|
18004
|
-
}.property(),
|
18005
|
-
active: Ember.State.create({}),
|
18006
|
-
passive: Ember.State.create({})
|
18007
|
-
});
|
18008
|
-
```
|
18009
|
-
|
18010
|
-
## Moving Between States
|
18011
|
-
|
18012
|
-
A StateManager can have any number of `Ember.State` objects as properties
|
18013
|
-
and can have a single one of these states as its current state.
|
18014
|
-
|
18015
|
-
Calling `transitionTo` transitions between states:
|
18016
|
-
|
18017
|
-
```javascript
|
18018
|
-
var robotManager = Ember.StateManager.create({
|
18019
|
-
initialState: 'poweredDown',
|
18020
|
-
poweredDown: Ember.State.create({}),
|
18021
|
-
poweredUp: Ember.State.create({})
|
18022
|
-
});
|
18023
|
-
|
18024
|
-
robotManager.get('currentState.name'); // 'poweredDown'
|
18025
|
-
robotManager.transitionTo('poweredUp');
|
18026
|
-
robotManager.get('currentState.name'); // 'poweredUp'
|
18027
|
-
```
|
18028
|
-
|
18029
|
-
Before transitioning into a new state the existing `currentState` will have
|
18030
|
-
its `exit` method called with the StateManager instance as its first argument
|
18031
|
-
and an object representing the transition as its second argument.
|
18032
|
-
|
18033
|
-
After transitioning into a new state the new `currentState` will have its
|
18034
|
-
`enter` method called with the StateManager instance as its first argument
|
18035
|
-
and an object representing the transition as its second argument.
|
18036
|
-
|
18037
|
-
```javascript
|
18038
|
-
var robotManager = Ember.StateManager.create({
|
18039
|
-
initialState: 'poweredDown',
|
18040
|
-
poweredDown: Ember.State.create({
|
18041
|
-
exit: function(stateManager) {
|
18042
|
-
console.log("exiting the poweredDown state")
|
18043
|
-
}
|
18044
|
-
}),
|
18045
|
-
poweredUp: Ember.State.create({
|
18046
|
-
enter: function(stateManager) {
|
18047
|
-
console.log("entering the poweredUp state. Destroy all humans.")
|
18048
|
-
}
|
18049
|
-
})
|
18050
|
-
});
|
18051
|
-
|
18052
|
-
robotManager.get('currentState.name'); // 'poweredDown'
|
18053
|
-
robotManager.transitionTo('poweredUp');
|
18054
|
-
|
18055
|
-
// will log
|
18056
|
-
// 'exiting the poweredDown state'
|
18057
|
-
// 'entering the poweredUp state. Destroy all humans.'
|
18058
|
-
```
|
18059
|
-
|
18060
|
-
Once a StateManager is already in a state, subsequent attempts to enter that
|
18061
|
-
state will not trigger enter or exit method calls. Attempts to transition
|
18062
|
-
into a state that the manager does not have will result in no changes in the
|
18063
|
-
StateManager's current state:
|
18064
|
-
|
18065
|
-
```javascript
|
18066
|
-
var robotManager = Ember.StateManager.create({
|
18067
|
-
initialState: 'poweredDown',
|
18068
|
-
poweredDown: Ember.State.create({
|
18069
|
-
exit: function(stateManager) {
|
18070
|
-
console.log("exiting the poweredDown state")
|
18071
|
-
}
|
18072
|
-
}),
|
18073
|
-
poweredUp: Ember.State.create({
|
18074
|
-
enter: function(stateManager) {
|
18075
|
-
console.log("entering the poweredUp state. Destroy all humans.")
|
18076
|
-
}
|
18077
|
-
})
|
18078
|
-
});
|
18079
|
-
|
18080
|
-
robotManager.get('currentState.name'); // 'poweredDown'
|
18081
|
-
robotManager.transitionTo('poweredUp');
|
18082
|
-
// will log
|
18083
|
-
// 'exiting the poweredDown state'
|
18084
|
-
// 'entering the poweredUp state. Destroy all humans.'
|
18085
|
-
robotManager.transitionTo('poweredUp'); // no logging, no state change
|
18086
|
-
|
18087
|
-
robotManager.transitionTo('someUnknownState'); // silently fails
|
18088
|
-
robotManager.get('currentState.name'); // 'poweredUp'
|
18089
|
-
```
|
18090
|
-
|
18091
|
-
Each state property may itself contain properties that are instances of
|
18092
|
-
`Ember.State`. The StateManager can transition to specific sub-states in a
|
18093
|
-
series of transitionTo method calls or via a single transitionTo with the
|
18094
|
-
full path to the specific state. The StateManager will also keep track of the
|
18095
|
-
full path to its currentState
|
18096
|
-
|
18097
|
-
```javascript
|
18098
|
-
var robotManager = Ember.StateManager.create({
|
18099
|
-
initialState: 'poweredDown',
|
18100
|
-
poweredDown: Ember.State.create({
|
18101
|
-
charging: Ember.State.create(),
|
18102
|
-
charged: Ember.State.create()
|
18103
|
-
}),
|
18104
|
-
poweredUp: Ember.State.create({
|
18105
|
-
mobile: Ember.State.create(),
|
18106
|
-
stationary: Ember.State.create()
|
18107
|
-
})
|
18108
|
-
});
|
18109
|
-
|
18110
|
-
robotManager.get('currentState.name'); // 'poweredDown'
|
18111
|
-
|
18112
|
-
robotManager.transitionTo('poweredUp');
|
18113
|
-
robotManager.get('currentState.name'); // 'poweredUp'
|
18114
|
-
|
18115
|
-
robotManager.transitionTo('mobile');
|
18116
|
-
robotManager.get('currentState.name'); // 'mobile'
|
18117
|
-
|
18118
|
-
// transition via a state path
|
18119
|
-
robotManager.transitionTo('poweredDown.charging');
|
18120
|
-
robotManager.get('currentState.name'); // 'charging'
|
18121
|
-
|
18122
|
-
robotManager.get('currentState.path'); // 'poweredDown.charging'
|
18123
|
-
```
|
18124
|
-
|
18125
|
-
Enter transition methods will be called for each state and nested child state
|
18126
|
-
in their hierarchical order. Exit methods will be called for each state and
|
18127
|
-
its nested states in reverse hierarchical order.
|
18128
|
-
|
18129
|
-
Exit transitions for a parent state are not called when entering into one of
|
18130
|
-
its child states, only when transitioning to a new section of possible states
|
18131
|
-
in the hierarchy.
|
18132
|
-
|
18133
|
-
```javascript
|
18134
|
-
var robotManager = Ember.StateManager.create({
|
18135
|
-
initialState: 'poweredDown',
|
18136
|
-
poweredDown: Ember.State.create({
|
18137
|
-
enter: function() {},
|
18138
|
-
exit: function() {
|
18139
|
-
console.log("exited poweredDown state")
|
18140
|
-
},
|
18141
|
-
charging: Ember.State.create({
|
18142
|
-
enter: function() {},
|
18143
|
-
exit: function() {}
|
18144
|
-
}),
|
18145
|
-
charged: Ember.State.create({
|
18146
|
-
enter: function() {
|
18147
|
-
console.log("entered charged state")
|
18148
|
-
},
|
18149
|
-
exit: function() {
|
18150
|
-
console.log("exited charged state")
|
18151
|
-
}
|
18152
|
-
})
|
18153
|
-
}),
|
18154
|
-
poweredUp: Ember.State.create({
|
18155
|
-
enter: function() {
|
18156
|
-
console.log("entered poweredUp state")
|
18157
|
-
},
|
18158
|
-
exit: function() {},
|
18159
|
-
mobile: Ember.State.create({
|
18160
|
-
enter: function() {
|
18161
|
-
console.log("entered mobile state")
|
18162
|
-
},
|
18163
|
-
exit: function() {}
|
18164
|
-
}),
|
18165
|
-
stationary: Ember.State.create({
|
18166
|
-
enter: function() {},
|
18167
|
-
exit: function() {}
|
18168
|
-
})
|
18169
|
-
})
|
18170
|
-
});
|
18171
|
-
|
18172
|
-
|
18173
|
-
robotManager.get('currentState.path'); // 'poweredDown'
|
18174
|
-
robotManager.transitionTo('charged');
|
18175
|
-
// logs 'entered charged state'
|
18176
|
-
// but does *not* log 'exited poweredDown state'
|
18177
|
-
robotManager.get('currentState.name'); // 'charged
|
18178
|
-
|
18179
|
-
robotManager.transitionTo('poweredUp.mobile');
|
18180
|
-
// logs
|
18181
|
-
// 'exited charged state'
|
18182
|
-
// 'exited poweredDown state'
|
18183
|
-
// 'entered poweredUp state'
|
18184
|
-
// 'entered mobile state'
|
18185
|
-
```
|
18186
|
-
|
18187
|
-
During development you can set a StateManager's `enableLogging` property to
|
18188
|
-
`true` to receive console messages of state transitions.
|
18189
|
-
|
18190
|
-
```javascript
|
18191
|
-
var robotManager = Ember.StateManager.create({
|
18192
|
-
enableLogging: true
|
18193
|
-
});
|
18194
|
-
```
|
18195
|
-
|
18196
|
-
## Managing currentState with Actions
|
18197
|
-
|
18198
|
-
To control which transitions are possible for a given state, and
|
18199
|
-
appropriately handle external events, the StateManager can receive and
|
18200
|
-
route action messages to its states via the `send` method. Calling to
|
18201
|
-
`send` with an action name will begin searching for a method with the same
|
18202
|
-
name starting at the current state and moving up through the parent states
|
18203
|
-
in a state hierarchy until an appropriate method is found or the StateManager
|
18204
|
-
instance itself is reached.
|
18205
|
-
|
18206
|
-
If an appropriately named method is found it will be called with the state
|
18207
|
-
manager as the first argument and an optional `context` object as the second
|
18208
|
-
argument.
|
18209
|
-
|
18210
|
-
```javascript
|
18211
|
-
var managerA = Ember.StateManager.create({
|
18212
|
-
initialState: 'stateOne.substateOne.subsubstateOne',
|
18213
|
-
stateOne: Ember.State.create({
|
18214
|
-
substateOne: Ember.State.create({
|
18215
|
-
anAction: function(manager, context) {
|
18216
|
-
console.log("an action was called")
|
18217
|
-
},
|
18218
|
-
subsubstateOne: Ember.State.create({})
|
18219
|
-
})
|
18220
|
-
})
|
18221
|
-
});
|
18222
|
-
|
18223
|
-
managerA.get('currentState.name'); // 'subsubstateOne'
|
18224
|
-
managerA.send('anAction');
|
18225
|
-
// 'stateOne.substateOne.subsubstateOne' has no anAction method
|
18226
|
-
// so the 'anAction' method of 'stateOne.substateOne' is called
|
18227
|
-
// and logs "an action was called"
|
18228
|
-
// with managerA as the first argument
|
18229
|
-
// and no second argument
|
18230
|
-
|
18231
|
-
var someObject = {};
|
18232
|
-
managerA.send('anAction', someObject);
|
18233
|
-
// the 'anAction' method of 'stateOne.substateOne' is called again
|
18234
|
-
// with managerA as the first argument and
|
18235
|
-
// someObject as the second argument.
|
18236
|
-
```
|
18237
|
-
|
18238
|
-
If the StateManager attempts to send an action but does not find an appropriately named
|
18239
|
-
method in the current state or while moving upwards through the state hierarchy, it will
|
18240
|
-
repeat the process looking for a `unhandledEvent` method. If an `unhandledEvent` method is
|
18241
|
-
found, it will be called with the original event name as the second argument. If an
|
18242
|
-
`unhandledEvent` method is not found, the StateManager will throw a new Ember.Error.
|
18243
|
-
|
18244
|
-
```javascript
|
18245
|
-
var managerB = Ember.StateManager.create({
|
18246
|
-
initialState: 'stateOne.substateOne.subsubstateOne',
|
18247
|
-
stateOne: Ember.State.create({
|
18248
|
-
substateOne: Ember.State.create({
|
18249
|
-
subsubstateOne: Ember.State.create({}),
|
18250
|
-
unhandledEvent: function(manager, eventName, context) {
|
18251
|
-
console.log("got an unhandledEvent with name " + eventName);
|
18252
|
-
}
|
18253
|
-
})
|
18254
|
-
})
|
18255
|
-
});
|
18256
|
-
|
18257
|
-
managerB.get('currentState.name'); // 'subsubstateOne'
|
18258
|
-
managerB.send('anAction');
|
18259
|
-
// neither `stateOne.substateOne.subsubstateOne` nor any of it's
|
18260
|
-
// parent states have a handler for `anAction`. `subsubstateOne`
|
18261
|
-
// also does not have a `unhandledEvent` method, but its parent
|
18262
|
-
// state, `substateOne`, does, and it gets fired. It will log
|
18263
|
-
// "got an unhandledEvent with name anAction"
|
18264
|
-
```
|
18265
|
-
|
18266
|
-
Action detection only moves upwards through the state hierarchy from the current state.
|
18267
|
-
It does not search in other portions of the hierarchy.
|
18268
|
-
|
18269
|
-
```javascript
|
18270
|
-
var managerC = Ember.StateManager.create({
|
18271
|
-
initialState: 'stateOne.substateOne.subsubstateOne',
|
18272
|
-
stateOne: Ember.State.create({
|
18273
|
-
substateOne: Ember.State.create({
|
18274
|
-
subsubstateOne: Ember.State.create({})
|
18275
|
-
})
|
18276
|
-
}),
|
18277
|
-
stateTwo: Ember.State.create({
|
18278
|
-
anAction: function(manager, context) {
|
18279
|
-
// will not be called below because it is
|
18280
|
-
// not a parent of the current state
|
18281
|
-
}
|
18282
|
-
})
|
18283
|
-
});
|
18284
|
-
|
18285
|
-
managerC.get('currentState.name'); // 'subsubstateOne'
|
18286
|
-
managerC.send('anAction');
|
18287
|
-
// Error: <Ember.StateManager:ember132> could not
|
18288
|
-
// respond to event anAction in state stateOne.substateOne.subsubstateOne.
|
18289
|
-
```
|
18290
|
-
|
18291
|
-
Inside of an action method the given state should delegate `transitionTo` calls on its
|
18292
|
-
StateManager.
|
18293
|
-
|
18294
|
-
```javascript
|
18295
|
-
var robotManager = Ember.StateManager.create({
|
18296
|
-
initialState: 'poweredDown.charging',
|
18297
|
-
poweredDown: Ember.State.create({
|
18298
|
-
charging: Ember.State.create({
|
18299
|
-
chargeComplete: function(manager, context) {
|
18300
|
-
manager.transitionTo('charged')
|
18301
|
-
}
|
18302
|
-
}),
|
18303
|
-
charged: Ember.State.create({
|
18304
|
-
boot: function(manager, context) {
|
18305
|
-
manager.transitionTo('poweredUp')
|
18306
|
-
}
|
18307
|
-
})
|
18308
|
-
}),
|
18309
|
-
poweredUp: Ember.State.create({
|
18310
|
-
beginExtermination: function(manager, context) {
|
18311
|
-
manager.transitionTo('rampaging')
|
18312
|
-
},
|
18313
|
-
rampaging: Ember.State.create()
|
18314
|
-
})
|
18315
|
-
});
|
18316
|
-
|
18317
|
-
robotManager.get('currentState.name'); // 'charging'
|
18318
|
-
robotManager.send('boot'); // throws error, no boot action
|
18319
|
-
// in current hierarchy
|
18320
|
-
robotManager.get('currentState.name'); // remains 'charging'
|
18321
|
-
|
18322
|
-
robotManager.send('beginExtermination'); // throws error, no beginExtermination
|
18323
|
-
// action in current hierarchy
|
18324
|
-
robotManager.get('currentState.name'); // remains 'charging'
|
18325
|
-
|
18326
|
-
robotManager.send('chargeComplete');
|
18327
|
-
robotManager.get('currentState.name'); // 'charged'
|
18328
|
-
|
18329
|
-
robotManager.send('boot');
|
18330
|
-
robotManager.get('currentState.name'); // 'poweredUp'
|
18331
|
-
|
18332
|
-
robotManager.send('beginExtermination', allHumans);
|
18333
|
-
robotManager.get('currentState.name'); // 'rampaging'
|
18334
|
-
```
|
18335
|
-
|
18336
|
-
Transition actions can also be created using the `transitionTo` method of the `Ember.State` class. The
|
18337
|
-
following example StateManagers are equivalent:
|
18338
|
-
|
18339
|
-
```javascript
|
18340
|
-
var aManager = Ember.StateManager.create({
|
18341
|
-
stateOne: Ember.State.create({
|
18342
|
-
changeToStateTwo: Ember.State.transitionTo('stateTwo')
|
18343
|
-
}),
|
18344
|
-
stateTwo: Ember.State.create({})
|
18345
|
-
});
|
18346
|
-
|
18347
|
-
var bManager = Ember.StateManager.create({
|
18348
|
-
stateOne: Ember.State.create({
|
18349
|
-
changeToStateTwo: function(manager, context) {
|
18350
|
-
manager.transitionTo('stateTwo', context)
|
18351
|
-
}
|
18352
|
-
}),
|
18353
|
-
stateTwo: Ember.State.create({})
|
18354
|
-
});
|
18355
|
-
```
|
18356
|
-
|
18357
|
-
@class StateManager
|
18358
|
-
@namespace Ember
|
18359
|
-
@extends Ember.State
|
18360
|
-
**/
|
18361
|
-
Ember.StateManager = Ember.State.extend({
|
18362
|
-
/**
|
18363
|
-
@private
|
18364
|
-
|
18365
|
-
When creating a new statemanager, look for a default state to transition
|
18366
|
-
into. This state can either be named `start`, or can be specified using the
|
18367
|
-
`initialState` property.
|
18368
|
-
|
18369
|
-
@method init
|
18370
|
-
*/
|
18371
|
-
init: function() {
|
18372
|
-
this._super();
|
18373
|
-
|
18374
|
-
set(this, 'stateMeta', Ember.Map.create());
|
18375
|
-
|
18376
|
-
var initialState = get(this, 'initialState');
|
18377
|
-
|
18378
|
-
if (!initialState && get(this, 'states.start')) {
|
18379
|
-
initialState = 'start';
|
18380
|
-
}
|
18381
|
-
|
18382
|
-
if (initialState) {
|
18383
|
-
this.transitionTo(initialState);
|
18384
|
-
Ember.assert('Failed to transition to initial state "' + initialState + '"', !!get(this, 'currentState'));
|
18385
|
-
}
|
18386
|
-
},
|
18387
|
-
|
18388
|
-
/**
|
18389
|
-
Return the stateMeta, a hash of possible states. If no items exist in the stateMeta hash
|
18390
|
-
this method sets the stateMeta to an empty JavaScript object and returns that instead.
|
18391
|
-
|
18392
|
-
@method stateMetaFor
|
18393
|
-
@param state
|
18394
|
-
*/
|
18395
|
-
stateMetaFor: function(state) {
|
18396
|
-
var meta = get(this, 'stateMeta'),
|
18397
|
-
stateMeta = meta.get(state);
|
18398
|
-
|
18399
|
-
if (!stateMeta) {
|
18400
|
-
stateMeta = {};
|
18401
|
-
meta.set(state, stateMeta);
|
18402
|
-
}
|
18403
|
-
|
18404
|
-
return stateMeta;
|
18405
|
-
},
|
18406
|
-
|
18407
|
-
/**
|
18408
|
-
Sets a key value pair on the stateMeta hash.
|
18409
|
-
|
18410
|
-
@method setStateMeta
|
18411
|
-
@param state
|
18412
|
-
@param key
|
18413
|
-
@param value
|
18414
|
-
*/
|
18415
|
-
setStateMeta: function(state, key, value) {
|
18416
|
-
return set(this.stateMetaFor(state), key, value);
|
18417
|
-
},
|
18418
|
-
|
18419
|
-
/**
|
18420
|
-
Returns the value of an item in the stateMeta hash at the given key.
|
18421
|
-
|
18422
|
-
@method getStateMeta
|
18423
|
-
@param state
|
18424
|
-
@param key
|
18425
|
-
*/
|
18426
|
-
getStateMeta: function(state, key) {
|
18427
|
-
return get(this.stateMetaFor(state), key);
|
18428
|
-
},
|
18429
|
-
|
18430
|
-
/**
|
18431
|
-
The current state from among the manager's possible states. This property should
|
18432
|
-
not be set directly. Use `transitionTo` to move between states by name.
|
18433
|
-
|
18434
|
-
@property currentState
|
18435
|
-
@type Ember.State
|
18436
|
-
*/
|
18437
|
-
currentState: null,
|
18438
|
-
|
18439
|
-
/**
|
18440
|
-
The path of the current state. Returns a string representation of the current
|
18441
|
-
state.
|
18442
|
-
|
18443
|
-
@property currentPath
|
18444
|
-
@type String
|
18445
|
-
*/
|
18446
|
-
currentPath: Ember.computed.alias('currentState.path'),
|
18447
|
-
|
18448
|
-
/**
|
18449
|
-
The name of transitionEvent that this stateManager will dispatch
|
18450
|
-
|
18451
|
-
@property transitionEvent
|
18452
|
-
@type String
|
18453
|
-
@default 'setup'
|
18454
|
-
*/
|
18455
|
-
transitionEvent: 'setup',
|
18456
|
-
|
18457
|
-
/**
|
18458
|
-
If set to true, `errorOnUnhandledEvents` will cause an exception to be
|
18459
|
-
raised if you attempt to send an event to a state manager that is not
|
18460
|
-
handled by the current state or any of its parent states.
|
18461
|
-
|
18462
|
-
@property errorOnUnhandledEvents
|
18463
|
-
@type Boolean
|
18464
|
-
@default true
|
18465
|
-
*/
|
18466
|
-
errorOnUnhandledEvent: true,
|
18467
|
-
|
18468
|
-
/**
|
18469
|
-
An alias to sendEvent method
|
18470
|
-
|
18471
|
-
@method send
|
18472
|
-
@param event
|
18473
|
-
*/
|
18474
|
-
send: function(event) {
|
18475
|
-
var contexts = [].slice.call(arguments, 1);
|
18476
|
-
Ember.assert('Cannot send event "' + event + '" while currentState is ' + get(this, 'currentState'), get(this, 'currentState'));
|
18477
|
-
return sendEvent.call(this, event, contexts, false);
|
18478
|
-
},
|
18479
|
-
|
18480
|
-
/**
|
18481
|
-
If errorOnUnhandledEvent is true this event with throw an Ember.Error
|
18482
|
-
indicating that the no state could respond to the event passed through the
|
18483
|
-
state machine.
|
18484
|
-
|
18485
|
-
@method unhandledEvent
|
18486
|
-
@param manager
|
18487
|
-
@param event
|
18488
|
-
*/
|
18489
|
-
unhandledEvent: function(manager, event) {
|
18490
|
-
if (get(this, 'errorOnUnhandledEvent')) {
|
18491
|
-
throw new Ember.Error(this.toString() + " could not respond to event " + event + " in state " + get(this, 'currentState.path') + ".");
|
18492
|
-
}
|
18493
|
-
},
|
18494
|
-
|
18495
|
-
/**
|
18496
|
-
Finds a state by its state path.
|
18497
|
-
|
18498
|
-
Example:
|
18499
|
-
|
18500
|
-
```javascript
|
18501
|
-
var manager = Ember.StateManager.create({
|
18502
|
-
root: Ember.State.create({
|
18503
|
-
dashboard: Ember.State.create()
|
18504
|
-
})
|
18505
|
-
});
|
18506
|
-
|
18507
|
-
manager.getStateByPath(manager, "root.dashboard");
|
18508
|
-
// returns the dashboard state
|
18509
|
-
|
18510
|
-
var aState = manager.getStateByPath(manager, "root.dashboard");
|
18511
|
-
|
18512
|
-
var path = aState.get('path');
|
18513
|
-
// path is 'root.dashboard'
|
18514
|
-
|
18515
|
-
var name = aState.get('name');
|
18516
|
-
// name is 'dashboard'
|
18517
|
-
```
|
18518
|
-
|
18519
|
-
@method getStateByPath
|
18520
|
-
@param {Ember.State} root the state to start searching from
|
18521
|
-
@param {String} path the state path to follow
|
18522
|
-
@return {Ember.State} the state at the end of the path
|
18523
|
-
*/
|
18524
|
-
getStateByPath: function(root, path) {
|
18525
|
-
var parts = path.split('.'),
|
18526
|
-
state = root;
|
18527
|
-
|
18528
|
-
for (var i=0, len=parts.length; i<len; i++) {
|
18529
|
-
state = get(get(state, 'states'), parts[i]);
|
18530
|
-
if (!state) { break; }
|
18531
|
-
}
|
18532
|
-
|
18533
|
-
return state;
|
18534
|
-
},
|
18535
|
-
|
18536
|
-
findStateByPath: function(state, path) {
|
18537
|
-
var possible;
|
18538
|
-
|
18539
|
-
while (!possible && state) {
|
18540
|
-
possible = this.getStateByPath(state, path);
|
18541
|
-
state = get(state, 'parentState');
|
18542
|
-
}
|
18543
|
-
|
18544
|
-
return possible;
|
18545
|
-
},
|
18546
|
-
|
18547
|
-
/**
|
18548
|
-
A state stores its child states in its `states` hash.
|
18549
|
-
This code takes a path like `posts.show` and looks
|
18550
|
-
up `root.states.posts.states.show`.
|
18551
|
-
|
18552
|
-
It returns a list of all of the states from the
|
18553
|
-
root, which is the list of states to call `enter`
|
18554
|
-
on.
|
18555
|
-
|
18556
|
-
@method getStatesInPath
|
18557
|
-
@param root
|
18558
|
-
@param path
|
18559
|
-
*/
|
18560
|
-
getStatesInPath: function(root, path) {
|
18561
|
-
if (!path || path === "") { return undefined; }
|
18562
|
-
var parts = path.split('.'),
|
18563
|
-
result = [],
|
18564
|
-
states,
|
18565
|
-
state;
|
18566
|
-
|
18567
|
-
for (var i=0, len=parts.length; i<len; i++) {
|
18568
|
-
states = get(root, 'states');
|
18569
|
-
if (!states) { return undefined; }
|
18570
|
-
state = get(states, parts[i]);
|
18571
|
-
if (state) { root = state; result.push(state); }
|
18572
|
-
else { return undefined; }
|
18573
|
-
}
|
18574
|
-
|
18575
|
-
return result;
|
18576
|
-
},
|
18577
|
-
|
18578
|
-
/**
|
18579
|
-
Alias for transitionTo.
|
18580
|
-
This method applies a transitionTo to the arguments passed into this method.
|
18581
|
-
|
18582
|
-
@method goToState
|
18583
|
-
*/
|
18584
|
-
goToState: function() {
|
18585
|
-
// not deprecating this yet so people don't constantly need to
|
18586
|
-
// make trivial changes for little reason.
|
18587
|
-
return this.transitionTo.apply(this, arguments);
|
18588
|
-
},
|
18589
|
-
|
18590
|
-
/**
|
18591
|
-
Transition to another state within the state machine. If the path is empty returns
|
18592
|
-
immediately. This method attempts to get a hash of the enter, exit and resolve states
|
18593
|
-
from the existing state cache. Processes the raw state information based on the
|
18594
|
-
passed in context. Creates a new transition object and triggers a new setupContext.
|
18595
|
-
|
18596
|
-
@method transitionTo
|
18597
|
-
@param path
|
18598
|
-
@param context
|
18599
|
-
*/
|
18600
|
-
transitionTo: function(path, context) {
|
18601
|
-
// XXX When is transitionTo called with no path
|
18602
|
-
if (Ember.isEmpty(path)) { return; }
|
18603
|
-
|
18604
|
-
// The ES6 signature of this function is `path, ...contexts`
|
18605
|
-
var contexts = context ? Array.prototype.slice.call(arguments, 1) : [],
|
18606
|
-
currentState = get(this, 'currentState') || this;
|
18607
|
-
|
18608
|
-
// First, get the enter, exit and resolve states for the current state
|
18609
|
-
// and specified path. If possible, use an existing cache.
|
18610
|
-
var hash = this.contextFreeTransition(currentState, path);
|
18611
|
-
|
18612
|
-
// Next, process the raw state information for the contexts passed in.
|
18613
|
-
var transition = new Transition(hash).normalize(this, contexts);
|
18614
|
-
|
18615
|
-
this.enterState(transition);
|
18616
|
-
this.triggerSetupContext(transition);
|
18617
|
-
},
|
18618
|
-
|
18619
|
-
/**
|
18620
|
-
Allows you to transition to any other state in the state manager without
|
18621
|
-
being constrained by the state hierarchy of the current state path.
|
18622
|
-
This method will traverse the state path upwards through its parents until
|
18623
|
-
it finds the specified state path. All the transitions are captured during the
|
18624
|
-
traversal.
|
18625
|
-
|
18626
|
-
Caches and returns hash of transitions, which contain the exitSates, enterStates and
|
18627
|
-
resolvedState
|
18628
|
-
|
18629
|
-
@method contextFreeTransition
|
18630
|
-
@param currentState
|
18631
|
-
@param path
|
18632
|
-
*/
|
18633
|
-
contextFreeTransition: function(currentState, path) {
|
18634
|
-
var cache = currentState.getPathsCache(this, path);
|
18635
|
-
if (cache) { return cache; }
|
18636
|
-
|
18637
|
-
var enterStates = this.getStatesInPath(currentState, path),
|
18638
|
-
exitStates = [],
|
18639
|
-
resolveState = currentState;
|
18640
|
-
|
18641
|
-
// Walk up the states. For each state, check whether a state matching
|
18642
|
-
// the `path` is nested underneath. This will find the closest
|
18643
|
-
// parent state containing `path`.
|
18644
|
-
//
|
18645
|
-
// This allows the user to pass in a relative path. For example, for
|
18646
|
-
// the following state hierarchy:
|
18647
|
-
//
|
18648
|
-
// | |root
|
18649
|
-
// | |- posts
|
18650
|
-
// | | |- show (* current)
|
18651
|
-
// | |- comments
|
18652
|
-
// | | |- show
|
18653
|
-
//
|
18654
|
-
// If the current state is `<root.posts.show>`, an attempt to
|
18655
|
-
// transition to `comments.show` will match `<root.comments.show>`.
|
18656
|
-
//
|
18657
|
-
// First, this code will look for root.posts.show.comments.show.
|
18658
|
-
// Next, it will look for root.posts.comments.show. Finally,
|
18659
|
-
// it will look for `root.comments.show`, and find the state.
|
18660
|
-
//
|
18661
|
-
// After this process, the following variables will exist:
|
18662
|
-
//
|
18663
|
-
// * resolveState: a common parent state between the current
|
18664
|
-
// and target state. In the above example, `<root>` is the
|
18665
|
-
// `resolveState`.
|
18666
|
-
// * enterStates: a list of all of the states represented
|
18667
|
-
// by the path from the `resolveState`. For example, for
|
18668
|
-
// the path `root.comments.show`, `enterStates` would have
|
18669
|
-
// `[<root.comments>, <root.comments.show>]`
|
18670
|
-
// * exitStates: a list of all of the states from the
|
18671
|
-
// `resolveState` to the `currentState`. In the above
|
18672
|
-
// example, `exitStates` would have
|
18673
|
-
// `[<root.posts>`, `<root.posts.show>]`.
|
18674
|
-
while (resolveState && !enterStates) {
|
18675
|
-
exitStates.unshift(resolveState);
|
18676
|
-
|
18677
|
-
resolveState = get(resolveState, 'parentState');
|
18678
|
-
if (!resolveState) {
|
18679
|
-
enterStates = this.getStatesInPath(this, path);
|
18680
|
-
if (!enterStates) {
|
18681
|
-
Ember.assert('Could not find state for path: "'+path+'"');
|
18682
|
-
return;
|
18683
|
-
}
|
18684
|
-
}
|
18685
|
-
enterStates = this.getStatesInPath(resolveState, path);
|
18686
|
-
}
|
18687
|
-
|
18688
|
-
// If the path contains some states that are parents of both the
|
18689
|
-
// current state and the target state, remove them.
|
18690
|
-
//
|
18691
|
-
// For example, in the following hierarchy:
|
18692
|
-
//
|
18693
|
-
// |- root
|
18694
|
-
// | |- post
|
18695
|
-
// | | |- index (* current)
|
18696
|
-
// | | |- show
|
18697
|
-
//
|
18698
|
-
// If the `path` is `root.post.show`, the three variables will
|
18699
|
-
// be:
|
18700
|
-
//
|
18701
|
-
// * resolveState: `<state manager>`
|
18702
|
-
// * enterStates: `[<root>, <root.post>, <root.post.show>]`
|
18703
|
-
// * exitStates: `[<root>, <root.post>, <root.post.index>]`
|
18704
|
-
//
|
18705
|
-
// The goal of this code is to remove the common states, so we
|
18706
|
-
// have:
|
18707
|
-
//
|
18708
|
-
// * resolveState: `<root.post>`
|
18709
|
-
// * enterStates: `[<root.post.show>]`
|
18710
|
-
// * exitStates: `[<root.post.index>]`
|
18711
|
-
//
|
18712
|
-
// This avoid unnecessary calls to the enter and exit transitions.
|
18713
|
-
while (enterStates.length > 0 && enterStates[0] === exitStates[0]) {
|
18714
|
-
resolveState = enterStates.shift();
|
18715
|
-
exitStates.shift();
|
18716
|
-
}
|
18717
|
-
|
18718
|
-
// Cache the enterStates, exitStates, and resolveState for the
|
18719
|
-
// current state and the `path`.
|
18720
|
-
var transitions = {
|
18721
|
-
exitStates: exitStates,
|
18722
|
-
enterStates: enterStates,
|
18723
|
-
resolveState: resolveState
|
18724
|
-
};
|
18725
|
-
|
18726
|
-
currentState.setPathsCache(this, path, transitions);
|
18727
|
-
|
18728
|
-
return transitions;
|
18729
|
-
},
|
18730
|
-
|
18731
|
-
/**
|
18732
|
-
A trigger to setup the state contexts. Each state is setup with
|
18733
|
-
an enterState.
|
18734
|
-
|
18735
|
-
@method triggerSetupContext
|
18736
|
-
@param transitions
|
18737
|
-
*/
|
18738
|
-
triggerSetupContext: function(transitions) {
|
18739
|
-
var contexts = transitions.contexts,
|
18740
|
-
offset = transitions.enterStates.length - contexts.length,
|
18741
|
-
enterStates = transitions.enterStates,
|
18742
|
-
transitionEvent = get(this, 'transitionEvent');
|
18743
|
-
|
18744
|
-
Ember.assert("More contexts provided than states", offset >= 0);
|
18745
|
-
|
18746
|
-
arrayForEach.call(enterStates, function(state, idx) {
|
18747
|
-
state.trigger(transitionEvent, this, contexts[idx-offset]);
|
18748
|
-
}, this);
|
18749
|
-
},
|
18750
|
-
|
18751
|
-
/**
|
18752
|
-
Returns the state instance by name. If state is not found the parentState
|
18753
|
-
is returned instead.
|
18754
|
-
|
18755
|
-
@method getState
|
18756
|
-
@param name
|
18757
|
-
*/
|
18758
|
-
getState: function(name) {
|
18759
|
-
var state = get(this, name),
|
18760
|
-
parentState = get(this, 'parentState');
|
18761
|
-
|
18762
|
-
if (state) {
|
18763
|
-
return state;
|
18764
|
-
} else if (parentState) {
|
18765
|
-
return parentState.getState(name);
|
18766
|
-
}
|
18767
|
-
},
|
18768
|
-
|
18769
|
-
/**
|
18770
|
-
Causes a transition from the exitState of one state to the enterState of another
|
18771
|
-
state in the state machine. At the end of the transition the currentState is set
|
18772
|
-
to the finalState of the transition passed into this method.
|
18773
|
-
|
18774
|
-
@method enterState
|
18775
|
-
@param transition
|
18776
|
-
*/
|
18777
|
-
enterState: function(transition) {
|
18778
|
-
var log = this.enableLogging;
|
18779
|
-
|
18780
|
-
var exitStates = transition.exitStates.slice(0).reverse();
|
18781
|
-
arrayForEach.call(exitStates, function(state) {
|
18782
|
-
state.trigger('exit', this);
|
18783
|
-
}, this);
|
18784
|
-
|
18785
|
-
arrayForEach.call(transition.enterStates, function(state) {
|
18786
|
-
if (log) { Ember.Logger.log("STATEMANAGER: Entering " + get(state, 'path')); }
|
18787
|
-
state.trigger('enter', this);
|
18788
|
-
}, this);
|
18789
|
-
|
18790
|
-
set(this, 'currentState', transition.finalState);
|
18791
|
-
}
|
18792
|
-
});
|
18793
|
-
|
18794
|
-
})();
|
18795
|
-
|
18796
|
-
|
18797
|
-
|
18798
|
-
(function() {
|
18799
|
-
/**
|
18800
|
-
Ember States
|
18801
|
-
|
18802
|
-
@module ember
|
18803
|
-
@submodule ember-states
|
18804
|
-
@requires ember-runtime
|
18805
|
-
*/
|
18806
|
-
|
18807
|
-
})();
|
18808
|
-
|
18809
18121
|
|
18810
18122
|
})();
|