ember-source 1.0.0.rc8 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
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
|
})();
|