pyro 0.9.0 → 1.0.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -61,7 +61,7 @@ var define, requireModule;
61
61
 
62
62
  @class Ember
63
63
  @static
64
- @version 1.0.0-rc.8
64
+ @version 1.0.0
65
65
  */
66
66
 
67
67
  if ('undefined' === typeof Ember) {
@@ -88,10 +88,10 @@ Ember.toString = function() { return "Ember"; };
88
88
  /**
89
89
  @property VERSION
90
90
  @type String
91
- @default '1.0.0-rc.8'
91
+ @default '1.0.0'
92
92
  @final
93
93
  */
94
- Ember.VERSION = '1.0.0-rc.8';
94
+ Ember.VERSION = '1.0.0';
95
95
 
96
96
  /**
97
97
  Standard environmental variables. You can define these in a global `ENV`
@@ -4433,8 +4433,8 @@ function registerComputedWithProperties(name, macro) {
4433
4433
  property is null, an empty string, empty array, or empty function.
4434
4434
 
4435
4435
  Note: When using `Ember.computed.empty` to watch an array make sure to
4436
- use the `array.length` or `array.@each` syntax so the computed can
4437
- subscribe to transitions from empty to non-empty states.
4436
+ use the `array.length` syntax so the computed can subscribe to transitions
4437
+ from empty to non-empty states.
4438
4438
 
4439
4439
  Example
4440
4440
 
@@ -4442,9 +4442,9 @@ function registerComputedWithProperties(name, macro) {
4442
4442
  var ToDoList = Ember.Object.extend({
4443
4443
  done: Ember.computed.empty('todos.length')
4444
4444
  });
4445
- var todoList = ToDoList.create({todoList: ['Unit Test', 'Documentation', 'Release']});
4445
+ var todoList = ToDoList.create({todos: ['Unit Test', 'Documentation', 'Release']});
4446
4446
  todoList.get('done'); // false
4447
- todoList.get('todoList').clear(); // []
4447
+ todoList.get('todos').clear(); // []
4448
4448
  todoList.get('done'); // true
4449
4449
  ```
4450
4450
 
@@ -5546,7 +5546,7 @@ define("backburner",
5546
5546
  clearTimeout(debouncee[2]);
5547
5547
  }
5548
5548
 
5549
- var timer = window.setTimeout(function() {
5549
+ var timer = global.setTimeout(function() {
5550
5550
  if (!immediate) {
5551
5551
  self.run.apply(self, args);
5552
5552
  }
@@ -5615,8 +5615,8 @@ define("backburner",
5615
5615
  function createAutorun(backburner) {
5616
5616
  backburner.begin();
5617
5617
  autorun = global.setTimeout(function() {
5618
- backburner.end();
5619
5618
  autorun = null;
5619
+ backburner.end();
5620
5620
  });
5621
5621
  }
5622
5622
 
@@ -7057,19 +7057,19 @@ Ember.mixin = function(obj) {
7057
7057
  `Ember.Mixin.extend`.
7058
7058
 
7059
7059
  Note that mixins extend a constructor's prototype so arrays and object literals
7060
- defined as properties will be shared amongst objects that implement the mixin.
7060
+ defined as properties will be shared amongst objects that implement the mixin.
7061
7061
  If you want to define an property in a mixin that is not shared, you can define
7062
7062
  it either as a computed property or have it be created on initialization of the object.
7063
-
7063
+
7064
7064
  ```javascript
7065
7065
  //filters array will be shared amongst any object implementing mixin
7066
7066
  App.Filterable = Ember.Mixin.create({
7067
- filters: Ember.A()
7067
+ filters: Ember.A()
7068
7068
  });
7069
7069
 
7070
7070
  //filters will be a separate array for every object implementing the mixin
7071
7071
  App.Filterable = Ember.Mixin.create({
7072
- filters: Ember.computed(function(){return Ember.A();})
7072
+ filters: Ember.computed(function(){return Ember.A();})
7073
7073
  });
7074
7074
 
7075
7075
  //filters will be created as a separate array during the object's initialization
@@ -7316,6 +7316,22 @@ Ember.aliasMethod = function(methodName) {
7316
7316
  //
7317
7317
 
7318
7318
  /**
7319
+ Specify a method that observes property changes.
7320
+
7321
+ ```javascript
7322
+ Ember.Object.extend({
7323
+ valueObserver: Ember.observer(function() {
7324
+ // Executes whenever the "value" property changes
7325
+ }, 'value')
7326
+ });
7327
+ ```
7328
+
7329
+ In the future this method may become asynchronous. If you want to ensure
7330
+ synchronous behavior, use `immediateObserver`.
7331
+
7332
+ Also available as `Function.prototype.observes` if prototype extensions are
7333
+ enabled.
7334
+
7319
7335
  @method observer
7320
7336
  @for Ember
7321
7337
  @param {Function} func
@@ -7328,9 +7344,23 @@ Ember.observer = function(func) {
7328
7344
  return func;
7329
7345
  };
7330
7346
 
7331
- // If observers ever become asynchronous, Ember.immediateObserver
7332
- // must remain synchronous.
7333
7347
  /**
7348
+ Specify a method that observes property changes.
7349
+
7350
+ ```javascript
7351
+ Ember.Object.extend({
7352
+ valueObserver: Ember.immediateObserver(function() {
7353
+ // Executes whenever the "value" property changes
7354
+ }, 'value')
7355
+ });
7356
+ ```
7357
+
7358
+ In the future, `Ember.observer` may become asynchronous. In this event,
7359
+ `Ember.immediateObserver` will maintain the synchronous behavior.
7360
+
7361
+ Also available as `Function.prototype.observesImmediately` if prototype extensions are
7362
+ enabled.
7363
+
7334
7364
  @method immediateObserver
7335
7365
  @for Ember
7336
7366
  @param {Function} func
@@ -7358,24 +7388,31 @@ Ember.immediateObserver = function() {
7358
7388
 
7359
7389
  ```javascript
7360
7390
  App.PersonView = Ember.View.extend({
7391
+
7361
7392
  friends: [{ name: 'Tom' }, { name: 'Stefan' }, { name: 'Kris' }],
7362
- valueWillChange: function (obj, keyName) {
7393
+
7394
+ valueWillChange: Ember.beforeObserver(function(obj, keyName) {
7363
7395
  this.changingFrom = obj.get(keyName);
7364
- }.observesBefore('content.value'),
7365
- valueDidChange: function(obj, keyName) {
7396
+ }, 'content.value'),
7397
+
7398
+ valueDidChange: Ember.observer(function(obj, keyName) {
7366
7399
  // only run if updating a value already in the DOM
7367
7400
  if (this.get('state') === 'inDOM') {
7368
- var color = obj.get(keyName) > this.changingFrom ? 'green' : 'red';
7369
- // logic
7401
+ var color = obj.get(keyName) > this.changingFrom ? 'green' : 'red';
7402
+ // logic
7370
7403
  }
7371
- }.observes('content.value'),
7372
- friendsDidChange: function(obj, keyName) {
7404
+ }, 'content.value'),
7405
+
7406
+ friendsDidChange: Ember.observer(function(obj, keyName) {
7373
7407
  // some logic
7374
7408
  // obj.get(keyName) returns friends array
7375
- }.observes('friends.@each.name')
7409
+ }, 'friends.@each.name')
7376
7410
  });
7377
7411
  ```
7378
7412
 
7413
+ Also available as `Function.prototype.observesBefore` if prototype extensions are
7414
+ enabled.
7415
+
7379
7416
  @method beforeObserver
7380
7417
  @for Ember
7381
7418
  @param {Function} func
@@ -7459,6 +7496,7 @@ define("rsvp/async",
7459
7496
  var browserGlobal = (typeof window !== 'undefined') ? window : {};
7460
7497
  var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
7461
7498
  var async;
7499
+ var local = (typeof global !== 'undefined') ? global : this;
7462
7500
 
7463
7501
  // old node
7464
7502
  function useNextTick() {
@@ -7509,7 +7547,7 @@ define("rsvp/async",
7509
7547
 
7510
7548
  function useSetTimeout() {
7511
7549
  return function(callback, arg) {
7512
- global.setTimeout(function() {
7550
+ local.setTimeout(function() {
7513
7551
  callback(arg);
7514
7552
  }, 1);
7515
7553
  };
@@ -8048,6 +8086,13 @@ define("rsvp",
8048
8086
  })();
8049
8087
 
8050
8088
  (function() {
8089
+ /**
8090
+ Flag to enable/disable model factory injections (disabled by default)
8091
+ If model factory injections are enabled, models should not be
8092
+ accessed globally (only through `container.lookupFactory('model:modelName'))`);
8093
+ */
8094
+ Ember.MODEL_FACTORY_INJECTIONS = false || !!Ember.ENV.MODEL_FACTORY_INJECTIONS;
8095
+
8051
8096
  define("container",
8052
8097
  [],
8053
8098
  function() {
@@ -8326,6 +8371,7 @@ define("container",
8326
8371
 
8327
8372
  container.unregister('model:user')
8328
8373
  container.lookup('model:user') === undefined //=> true
8374
+ ```
8329
8375
 
8330
8376
  @method unregister
8331
8377
  @param {String} fullName
@@ -8409,7 +8455,7 @@ define("container",
8409
8455
  */
8410
8456
  makeToString: function(factory, fullName) {
8411
8457
  return factory.toString();
8412
- },
8458
+ },
8413
8459
 
8414
8460
  /**
8415
8461
  Given a fullName return a corresponding instance.
@@ -8817,6 +8863,7 @@ define("container",
8817
8863
  var factory = container.resolve(name);
8818
8864
  var injectedFactory;
8819
8865
  var cache = container.factoryCache;
8866
+ var type = fullName.split(":")[0];
8820
8867
 
8821
8868
  if (!factory) { return; }
8822
8869
 
@@ -8824,7 +8871,7 @@ define("container",
8824
8871
  return cache.get(fullName);
8825
8872
  }
8826
8873
 
8827
- if (typeof factory.extend !== 'function') {
8874
+ if (typeof factory.extend !== 'function' || (!Ember.MODEL_FACTORY_INJECTIONS && type === 'model')) {
8828
8875
  // TODO: think about a 'safe' merge style extension
8829
8876
  // for now just fallback to create time injection
8830
8877
  return factory;
@@ -10627,6 +10674,9 @@ Ember.Array = Ember.Mixin.create(Ember.Enumerable, /** @scope Ember.Array.protot
10627
10674
  return an enumerable that maps automatically to the named key on the
10628
10675
  member objects.
10629
10676
 
10677
+ If you merely want to watch for any items being added or removed to the array,
10678
+ use the `[]` property instead of `@each`.
10679
+
10630
10680
  @property @each
10631
10681
  */
10632
10682
  '@each': Ember.computed(function() {
@@ -10658,7 +10708,7 @@ var get = Ember.get,
10658
10708
  eachPropertyPattern = /^(.*)\.@each\.(.*)/,
10659
10709
  doubleEachPropertyPattern = /(.*\.@each){2,}/;
10660
10710
 
10661
- /**
10711
+ /*
10662
10712
  Tracks changes to dependent arrays, as well as to properties of items in
10663
10713
  dependent arrays.
10664
10714
 
@@ -10847,22 +10897,29 @@ DependentArraysObserver.prototype = {
10847
10897
  guid = guidFor(dependentArray),
10848
10898
  dependentKey = this.dependentKeysByGuid[guid],
10849
10899
  itemPropertyKeys = this.cp._itemPropertyKeys[dependentKey] || [],
10900
+ item,
10850
10901
  itemIndex,
10902
+ sliceIndex,
10851
10903
  observerContexts;
10852
10904
 
10853
10905
  observerContexts = this.removeTransformation(dependentKey, index, removedCount);
10854
- forEach(dependentArray.slice(index, index + removedCount), function (item, sliceIndex) {
10906
+
10907
+
10908
+ function removeObservers(propertyKey) {
10909
+ removeBeforeObserver(item, propertyKey, this, observerContexts[sliceIndex].beforeObserver);
10910
+ removeObserver(item, propertyKey, this, observerContexts[sliceIndex].observer);
10911
+ }
10912
+
10913
+ for (sliceIndex = removedCount - 1; sliceIndex >= 0; --sliceIndex) {
10855
10914
  itemIndex = index + sliceIndex;
10915
+ item = dependentArray.objectAt(itemIndex);
10856
10916
 
10857
- forEach(itemPropertyKeys, function (propertyKey) {
10858
- removeBeforeObserver(item, propertyKey, this, observerContexts[sliceIndex].beforeObserver);
10859
- removeObserver(item, propertyKey, this, observerContexts[sliceIndex].observer);
10860
- }, this);
10917
+ forEach(itemPropertyKeys, removeObservers, this);
10861
10918
 
10862
10919
  changeMeta = createChangeMeta(dependentArray, item, itemIndex, this.instanceMeta.propertyName, this.cp);
10863
10920
  this.setValue( removedItem.call(
10864
10921
  this.instanceMeta.context, this.getValue(), item, changeMeta, this.instanceMeta.sugarMeta));
10865
- }, this);
10922
+ }
10866
10923
  },
10867
10924
 
10868
10925
  dependentArrayDidChange: function (dependentArray, index, removedCount, addedCount) {
@@ -10876,8 +10933,8 @@ DependentArraysObserver.prototype = {
10876
10933
 
10877
10934
  forEach(dependentArray.slice(index, index + addedCount), function (item, sliceIndex) {
10878
10935
  if (itemPropertyKeys) {
10879
- observerContext =
10880
- observerContexts[sliceIndex] =
10936
+ observerContext =
10937
+ observerContexts[sliceIndex] =
10881
10938
  this.createPropertyObserverContext(dependentArray, index + sliceIndex, this.trackedArraysByGuid[dependentKey]);
10882
10939
  forEach(itemPropertyKeys, function (propertyKey) {
10883
10940
  addBeforeObserver(item, propertyKey, this, observerContext.beforeObserver);
@@ -10894,30 +10951,29 @@ DependentArraysObserver.prototype = {
10894
10951
  },
10895
10952
 
10896
10953
  itemPropertyWillChange: function (obj, keyName, array, index) {
10897
- var changeId = guidFor(obj)+":"+keyName;
10954
+ var guid = guidFor(obj);
10898
10955
 
10899
- if (!this.changedItems[changeId]) {
10900
- this.changedItems[changeId] = {
10901
- array: array,
10956
+ if (!this.changedItems[guid]) {
10957
+ this.changedItems[guid] = {
10958
+ array: array,
10902
10959
  index: index,
10903
10960
  obj: obj,
10904
- keyChanged: keyName,
10905
- previousValue: get(obj, keyName)
10961
+ previousValues: {}
10906
10962
  };
10907
10963
  }
10964
+
10965
+ this.changedItems[guid].previousValues[keyName] = get(obj, keyName);
10908
10966
  },
10909
10967
 
10910
10968
  itemPropertyDidChange: function(obj, keyName, array, index) {
10911
10969
  Ember.run.once(this, 'flushChanges');
10912
10970
  },
10913
10971
 
10914
- // TODO: it probably makes more sense to remove the item during `willChange`
10915
- // and add it back (with the new value) during `didChange`
10916
10972
  flushChanges: function() {
10917
10973
  var changedItems = this.changedItems, key, c, changeMeta;
10918
10974
  for (key in changedItems) {
10919
10975
  c = changedItems[key];
10920
- changeMeta = createChangeMeta(c.array, c.obj, c.index, this.instanceMeta.propertyName, this.cp, c.keyChanged, c.previousValue);
10976
+ changeMeta = createChangeMeta(c.array, c.obj, c.index, this.instanceMeta.propertyName, this.cp, c.previousValues);
10921
10977
  this.setValue(
10922
10978
  this.callbacks.removedItem.call(this.instanceMeta.context, this.getValue(), c.obj, changeMeta, this.instanceMeta.sugarMeta));
10923
10979
  this.setValue(
@@ -10927,18 +10983,19 @@ DependentArraysObserver.prototype = {
10927
10983
  }
10928
10984
  };
10929
10985
 
10930
- function createChangeMeta(dependentArray, item, index, propertyName, property, key, previousValue) {
10986
+ function createChangeMeta(dependentArray, item, index, propertyName, property, previousValues) {
10931
10987
  var meta = {
10932
10988
  arrayChanged: dependentArray,
10933
10989
  index: index,
10934
10990
  item: item,
10935
10991
  propertyName: propertyName,
10936
- property: property,
10937
- // previous value is only available for item property changes!
10938
- previousValue: previousValue
10992
+ property: property
10939
10993
  };
10940
10994
 
10941
- if (key) { meta.keyChanged = key; }
10995
+ if (previousValues) {
10996
+ // previous values only available for item property changes
10997
+ meta.previousValues = previousValues;
10998
+ }
10942
10999
 
10943
11000
  return meta;
10944
11001
  }
@@ -11062,7 +11119,9 @@ function ReduceComputedProperty(options) {
11062
11119
 
11063
11120
  forEach(cp._dependentKeys, function(dependentKey) {
11064
11121
  var dependentArray = get(this, dependentKey);
11065
- addItems.call(this, dependentArray, callbacks, cp, propertyName, meta);
11122
+ if (dependentArray) {
11123
+ addItems.call(this, dependentArray, callbacks, cp, propertyName, meta);
11124
+ }
11066
11125
  }, this);
11067
11126
  };
11068
11127
 
@@ -11164,7 +11223,122 @@ ReduceComputedProperty.prototype.property = function () {
11164
11223
  return ComputedProperty.prototype.property.apply(this, propertyArgs);
11165
11224
  };
11166
11225
 
11226
+ /**
11227
+ Creates a computed property which operates on dependent arrays and
11228
+ is updated with "one at a time" semantics. When items are added or
11229
+ removed from the dependent array(s) a reduce computed only operates
11230
+ on the change instead of re-evaluating the entire array.
11231
+
11232
+ If there are more than one arguments the first arguments are
11233
+ considered to be dependent property keys. The last argument is
11234
+ required to be an options object. The options object can have the
11235
+ following four properties.
11236
+
11237
+ `initialValue` - A value or function that will be used as the initial
11238
+ value for the computed. If this property is a function the result of calling
11239
+ the function will be used as the initial value. This property is required.
11240
+
11241
+ `initialize` - An optional initialize function. Typically this will be used
11242
+ to set up state on the instanceMeta object.
11243
+
11244
+ `removedItem` - A function that is called each time an element is removed
11245
+ from the array.
11246
+
11247
+ `addedItem` - A function that is called each time an element is added to
11248
+ the array.
11249
+
11250
+
11251
+ The `initialize` function has the following signature:
11252
+
11253
+ ```javascript
11254
+ function (initialValue, changeMeta, instanceMeta)
11255
+ ```
11256
+
11257
+ `initialValue` - The value of the `initialValue` property from the
11258
+ options object.
11259
+
11260
+ `changeMeta` - An object which contains meta information about the
11261
+ computed. It contains the following properties:
11262
+
11263
+ - `property` the computed property
11264
+ - `propertyName` the name of the property on the object
11265
+
11266
+ `instanceMeta` - An object that can be used to store meta
11267
+ information needed for calculating your computed. For example a
11268
+ unique computed might use this to store the number of times a given
11269
+ element is found in the dependent array.
11270
+
11271
+
11272
+ The `removedItem` and `addedItem` functions both have the following signature:
11273
+
11274
+ ```javascript
11275
+ function (accumulatedValue, item, changeMeta, instanceMeta)
11276
+ ```
11277
+
11278
+ `accumulatedValue` - The value returned from the last time
11279
+ `removedItem` or `addedItem` was called or `initialValue`.
11280
+
11281
+ `item` - the element added or removed from the array
11282
+
11283
+ `changeMeta` - An object which contains meta information about the
11284
+ change. It contains the following properties:
11285
+
11286
+ - `property` the computed property
11287
+ - `propertyName` the name of the property on the object
11288
+ - `index` the index of the added or removed item
11289
+ - `item` the added or removed item: this is exactly the same as
11290
+ the second arg
11291
+ - `arrayChanged` the array that triggered the change. Can be
11292
+ useful when depending on multiple arrays.
11293
+
11294
+ For property changes triggered on an item property change (when
11295
+ depKey is something like `someArray.@each.someProperty`),
11296
+ `changeMeta` will also contain the following property:
11297
+
11298
+ - `previousValues` an object whose keys are the properties that changed on
11299
+ the item, and whose values are the item's previous values.
11300
+
11301
+ `previousValues` is important Ember coalesces item property changes via
11302
+ Ember.run.once. This means that by the time removedItem gets called, item has
11303
+ the new values, but you may need the previous value (eg for sorting &
11304
+ filtering).
11305
+
11306
+ `instanceMeta` - An object that can be used to store meta
11307
+ information needed for calculating your computed. For example a
11308
+ unique computed might use this to store the number of times a given
11309
+ element is found in the dependent array.
11310
+
11311
+ The `removedItem` and `addedItem` functions should return the accumulated
11312
+ value. It is acceptable to not return anything (ie return undefined)
11313
+ to invalidate the computation. This is generally not a good idea for
11314
+ arrayComputed but it's used in eg max and min.
11315
+
11316
+ Example
11317
+
11318
+ ```javascript
11319
+ Ember.computed.max = function (dependentKey) {
11320
+ return Ember.reduceComputed.call(null, dependentKey, {
11321
+ initialValue: -Infinity,
11322
+
11323
+ addedItem: function (accumulatedValue, item, changeMeta, instanceMeta) {
11324
+ return Math.max(accumulatedValue, item);
11325
+ },
11326
+
11327
+ removedItem: function (accumulatedValue, item, changeMeta, instanceMeta) {
11328
+ if (item < accumulatedValue) {
11329
+ return accumulatedValue;
11330
+ }
11331
+ }
11332
+ });
11333
+ };
11334
+ ```
11167
11335
 
11336
+ @method reduceComputed
11337
+ @for Ember
11338
+ @param {String} [dependentKeys*]
11339
+ @param {Object} options
11340
+ @returns {Ember.ComputedProperty}
11341
+ */
11168
11342
  Ember.reduceComputed = function (options) {
11169
11343
  var args;
11170
11344
 
@@ -11190,7 +11364,6 @@ Ember.reduceComputed = function (options) {
11190
11364
  return cp;
11191
11365
  };
11192
11366
 
11193
-
11194
11367
  })();
11195
11368
 
11196
11369
 
@@ -11235,7 +11408,120 @@ ArrayComputedProperty.prototype.resetValue = function (array) {
11235
11408
  return array;
11236
11409
  };
11237
11410
 
11411
+ /**
11412
+ Creates a computed property which operates on dependent arrays and
11413
+ is updated with "one at a time" semantics. When items are added or
11414
+ removed from the dependent array(s) an array computed only operates
11415
+ on the change instead of re-evaluating the entire array. This should
11416
+ return an array, if you'd like to use "one at a time" semantics and
11417
+ compute some value other then an array look at
11418
+ `Ember.reduceComputed`.
11238
11419
 
11420
+ If there are more than one arguments the first arguments are
11421
+ considered to be dependent property keys. The last argument is
11422
+ required to be an options object. The options object can have the
11423
+ following three properties.
11424
+
11425
+ `initialize` - An optional initialize function. Typically this will be used
11426
+ to set up state on the instanceMeta object.
11427
+
11428
+ `removedItem` - A function that is called each time an element is
11429
+ removed from the array.
11430
+
11431
+ `addedItem` - A function that is called each time an element is
11432
+ added to the array.
11433
+
11434
+
11435
+ The `initialize` function has the following signature:
11436
+
11437
+ ```javascript
11438
+ function (array, changeMeta, instanceMeta)
11439
+ ```
11440
+
11441
+ `array` - The initial value of the arrayComputed, an empty array.
11442
+
11443
+ `changeMeta` - An object which contains meta information about the
11444
+ computed. It contains the following properties:
11445
+
11446
+ - `property` the computed property
11447
+ - `propertyName` the name of the property on the object
11448
+
11449
+ `instanceMeta` - An object that can be used to store meta
11450
+ information needed for calculating your computed. For example a
11451
+ unique computed might use this to store the number of times a given
11452
+ element is found in the dependent array.
11453
+
11454
+
11455
+ The `removedItem` and `addedItem` functions both have the following signature:
11456
+
11457
+ ```javascript
11458
+ function (accumulatedValue, item, changeMeta, instanceMeta)
11459
+ ```
11460
+
11461
+ `accumulatedValue` - The value returned from the last time
11462
+ `removedItem` or `addedItem` was called or an empty array.
11463
+
11464
+ `item` - the element added or removed from the array
11465
+
11466
+ `changeMeta` - An object which contains meta information about the
11467
+ change. It contains the following properties:
11468
+
11469
+ - `property` the computed property
11470
+ - `propertyName` the name of the property on the object
11471
+ - `index` the index of the added or removed item
11472
+ - `item` the added or removed item: this is exactly the same as
11473
+ the second arg
11474
+ - `arrayChanged` the array that triggered the change. Can be
11475
+ useful when depending on multiple arrays.
11476
+
11477
+ For property changes triggered on an item property change (when
11478
+ depKey is something like `someArray.@each.someProperty`),
11479
+ `changeMeta` will also contain the following property:
11480
+
11481
+ - `previousValues` an object whose keys are the properties that changed on
11482
+ the item, and whose values are the item's previous values.
11483
+
11484
+ `previousValues` is important Ember coalesces item property changes via
11485
+ Ember.run.once. This means that by the time removedItem gets called, item has
11486
+ the new values, but you may need the previous value (eg for sorting &
11487
+ filtering).
11488
+
11489
+ `instanceMeta` - An object that can be used to store meta
11490
+ information needed for calculating your computed. For example a
11491
+ unique computed might use this to store the number of times a given
11492
+ element is found in the dependent array.
11493
+
11494
+ The `removedItem` and `addedItem` functions should return the accumulated
11495
+ value. It is acceptable to not return anything (ie return undefined)
11496
+ to invalidate the computation. This is generally not a good idea for
11497
+ arrayComputed but it's used in eg max and min.
11498
+
11499
+ Example
11500
+
11501
+ ```javascript
11502
+ Ember.computed.map = function(dependentKey, callback) {
11503
+ var options = {
11504
+ addedItem: function(array, item, changeMeta, instanceMeta) {
11505
+ var mapped = callback(item);
11506
+ array.insertAt(changeMeta.index, mapped);
11507
+ return array;
11508
+ },
11509
+ removedItem: function(array, item, changeMeta, instanceMeta) {
11510
+ array.removeAt(changeMeta.index, 1);
11511
+ return array;
11512
+ }
11513
+ };
11514
+
11515
+ return Ember.arrayComputed(dependentKey, options);
11516
+ };
11517
+ ```
11518
+
11519
+ @method arrayComputed
11520
+ @for Ember
11521
+ @param {String} [dependentKeys*]
11522
+ @param {Object} options
11523
+ @returns {Ember.ComputedProperty}
11524
+ */
11239
11525
  Ember.arrayComputed = function (options) {
11240
11526
  var args;
11241
11527
 
@@ -11262,12 +11548,45 @@ Ember.arrayComputed = function (options) {
11262
11548
 
11263
11549
 
11264
11550
  (function() {
11551
+ /**
11552
+ @module ember
11553
+ @submodule ember-runtime
11554
+ */
11555
+
11265
11556
  var get = Ember.get,
11266
11557
  set = Ember.set,
11558
+ guidFor = Ember.guidFor,
11559
+ merge = Ember.merge,
11267
11560
  a_slice = [].slice,
11268
11561
  forEach = Ember.EnumerableUtils.forEach,
11269
11562
  map = Ember.EnumerableUtils.map;
11270
11563
 
11564
+ /**
11565
+ A computed property that calculates the maximum value in the
11566
+ dependent array. This will return `-Infinity` when the dependent
11567
+ array is empty.
11568
+
11569
+ Example
11570
+
11571
+ ```javascript
11572
+ App.Person = Ember.Object.extend({
11573
+ childAges: Ember.computed.mapBy('children', 'age'),
11574
+ maxChildAge: Ember.computed.max('childAges')
11575
+ });
11576
+
11577
+ var lordByron = App.Person.create({children: []});
11578
+ lordByron.get('maxChildAge'); // -Infinity
11579
+ lordByron.get('children').pushObject({name: 'Augusta Ada Byron', age: 7});
11580
+ lordByron.get('maxChildAge'); // 7
11581
+ lordByron.get('children').pushObjects([{name: 'Allegra Byron', age: 5}, {name: 'Elizabeth Medora Leigh', age: 8}]);
11582
+ lordByron.get('maxChildAge'); // 8
11583
+ ```
11584
+
11585
+ @method computed.max
11586
+ @for Ember
11587
+ @param {String} dependentKey
11588
+ @return {Ember.ComputedProperty} computes the largest value in the dependentKey's array
11589
+ */
11271
11590
  Ember.computed.max = function (dependentKey) {
11272
11591
  return Ember.reduceComputed.call(null, dependentKey, {
11273
11592
  initialValue: -Infinity,
@@ -11284,6 +11603,32 @@ Ember.computed.max = function (dependentKey) {
11284
11603
  });
11285
11604
  };
11286
11605
 
11606
+ /**
11607
+ A computed property that calculates the minimum value in the
11608
+ dependent array. This will return `Infinity` when the dependent
11609
+ array is empty.
11610
+
11611
+ Example
11612
+
11613
+ ```javascript
11614
+ App.Person = Ember.Object.extend({
11615
+ childAges: Ember.computed.mapBy('children', 'age'),
11616
+ minChildAge: Ember.computed.min('childAges')
11617
+ });
11618
+
11619
+ var lordByron = App.Person.create({children: []});
11620
+ lordByron.get('minChildAge'); // Infinity
11621
+ lordByron.get('children').pushObject({name: 'Augusta Ada Byron', age: 7});
11622
+ lordByron.get('minChildAge'); // 7
11623
+ lordByron.get('children').pushObjects([{name: 'Allegra Byron', age: 5}, {name: 'Elizabeth Medora Leigh', age: 8}]);
11624
+ lordByron.get('minChildAge'); // 5
11625
+ ```
11626
+
11627
+ @method computed.min
11628
+ @for Ember
11629
+ @param {String} dependentKey
11630
+ @return {Ember.ComputedProperty} computes the smallest value in the dependentKey's array
11631
+ */
11287
11632
  Ember.computed.min = function (dependentKey) {
11288
11633
  return Ember.reduceComputed.call(null, dependentKey, {
11289
11634
  initialValue: Infinity,
@@ -11300,6 +11645,36 @@ Ember.computed.min = function (dependentKey) {
11300
11645
  });
11301
11646
  };
11302
11647
 
11648
+ /**
11649
+ Returns an array mapped via the callback
11650
+
11651
+ The callback method you provide should have the following signature:
11652
+
11653
+ ```javascript
11654
+ function(item);
11655
+ ```
11656
+
11657
+ - `item` is the current item in the iteration.
11658
+
11659
+ Example
11660
+
11661
+ ```javascript
11662
+ App.Hampster = Ember.Object.extend({
11663
+ excitingChores: Ember.computed.map('chores', function(chore) {
11664
+ return chore.toUpperCase() + '!';
11665
+ })
11666
+ });
11667
+
11668
+ var hampster = App.Hampster.create({chores: ['cook', 'clean', 'write more unit tests']});
11669
+ hampster.get('excitingChores'); // ['COOK!', 'CLEAN!', 'WRITE MORE UNIT TESTS!']
11670
+ ```
11671
+
11672
+ @method computed.map
11673
+ @for Ember
11674
+ @param {String} dependentKey
11675
+ @param {Function} callback
11676
+ @return {Ember.ComputedProperty} an array mapped via the callback
11677
+ */
11303
11678
  Ember.computed.map = function(dependentKey, callback) {
11304
11679
  var options = {
11305
11680
  addedItem: function(array, item, changeMeta, instanceMeta) {
@@ -11316,11 +11691,79 @@ Ember.computed.map = function(dependentKey, callback) {
11316
11691
  return Ember.arrayComputed(dependentKey, options);
11317
11692
  };
11318
11693
 
11319
- Ember.computed.mapProperty = function(dependentKey, propertyKey) {
11694
+ /**
11695
+ Returns an array mapped to the specified key.
11696
+
11697
+ Example
11698
+
11699
+ ```javascript
11700
+ App.Person = Ember.Object.extend({
11701
+ childAges: Ember.computed.mapBy('children', 'age'),
11702
+ minChildAge: Ember.computed.min('childAges')
11703
+ });
11704
+
11705
+ var lordByron = App.Person.create({children: []});
11706
+ lordByron.get('childAge'); // []
11707
+ lordByron.get('children').pushObject({name: 'Augusta Ada Byron', age: 7});
11708
+ lordByron.get('childAge'); // [7]
11709
+ lordByron.get('children').pushObjects([{name: 'Allegra Byron', age: 5}, {name: 'Elizabeth Medora Leigh', age: 8}]);
11710
+ lordByron.get('childAge'); // [7, 5, 8]
11711
+ ```
11712
+
11713
+ @method computed.mapBy
11714
+ @for Ember
11715
+ @param {String} dependentKey
11716
+ @param {String} propertyKey
11717
+ @return {Ember.ComputedProperty} an array mapped to the specified key
11718
+ */
11719
+ Ember.computed.mapBy = function(dependentKey, propertyKey) {
11320
11720
  var callback = function(item) { return get(item, propertyKey); };
11321
11721
  return Ember.computed.map(dependentKey + '.@each.' + propertyKey, callback);
11322
11722
  };
11323
11723
 
11724
+ /**
11725
+ @method computed.mapProperty
11726
+ @for Ember
11727
+ @deprecated Use `Ember.computed.mapBy` instead
11728
+ @param dependentKey
11729
+ @param propertyKey
11730
+ */
11731
+ Ember.computed.mapProperty = Ember.computed.mapBy;
11732
+
11733
+ /**
11734
+ Filters the array by the callback.
11735
+
11736
+ The callback method you provide should have the following signature:
11737
+
11738
+ ```javascript
11739
+ function(item);
11740
+ ```
11741
+
11742
+ - `item` is the current item in the iteration.
11743
+
11744
+ Example
11745
+
11746
+ ```javascript
11747
+ App.Hampster = Ember.Object.extend({
11748
+ remainingChores: Ember.computed.filter('chores', function(chore) {
11749
+ return !chore.done;
11750
+ })
11751
+ });
11752
+
11753
+ var hampster = App.Hampster.create({chores: [
11754
+ {name: 'cook', done: true},
11755
+ {name: 'clean', done: true},
11756
+ {name: 'write more unit tests', done: false}
11757
+ ]});
11758
+ hampster.get('remainingChores'); // [{name: 'write more unit tests', done: false}]
11759
+ ```
11760
+
11761
+ @method computed.filter
11762
+ @for Ember
11763
+ @param {String} dependentKey
11764
+ @param {Function} callback
11765
+ @return {Ember.ComputedProperty} the filtered array
11766
+ */
11324
11767
  Ember.computed.filter = function(dependentKey, callback) {
11325
11768
  var options = {
11326
11769
  initialize: function (array, changeMeta, instanceMeta) {
@@ -11334,6 +11777,8 @@ Ember.computed.filter = function(dependentKey, callback) {
11334
11777
  if (match) {
11335
11778
  array.insertAt(filterIndex, item);
11336
11779
  }
11780
+
11781
+ return array;
11337
11782
  },
11338
11783
 
11339
11784
  removedItem: function(array, item, changeMeta, instanceMeta) {
@@ -11342,13 +11787,40 @@ Ember.computed.filter = function(dependentKey, callback) {
11342
11787
  if (filterIndex > -1) {
11343
11788
  array.removeAt(filterIndex);
11344
11789
  }
11790
+
11791
+ return array;
11345
11792
  }
11346
11793
  };
11347
11794
 
11348
11795
  return Ember.arrayComputed(dependentKey, options);
11349
11796
  };
11350
11797
 
11351
- Ember.computed.filterProperty = function(dependentKey, propertyKey, value) {
11798
+ /**
11799
+ Filters the array by the property and value
11800
+
11801
+ Example
11802
+
11803
+ ```javascript
11804
+ App.Hampster = Ember.Object.extend({
11805
+ remainingChores: Ember.computed.filterBy('chores', 'done', false)
11806
+ });
11807
+
11808
+ var hampster = App.Hampster.create({chores: [
11809
+ {name: 'cook', done: true},
11810
+ {name: 'clean', done: true},
11811
+ {name: 'write more unit tests', done: false}
11812
+ ]});
11813
+ hampster.get('remainingChores'); // [{name: 'write more unit tests', done: false}]
11814
+ ```
11815
+
11816
+ @method computed.filterBy
11817
+ @for Ember
11818
+ @param {String} dependentKey
11819
+ @param {String} propertyKey
11820
+ @param {String} value
11821
+ @return {Ember.ComputedProperty} the filtered array
11822
+ */
11823
+ Ember.computed.filterBy = function(dependentKey, propertyKey, value) {
11352
11824
  var callback;
11353
11825
 
11354
11826
  if (arguments.length === 2) {
@@ -11364,6 +11836,42 @@ Ember.computed.filterProperty = function(dependentKey, propertyKey, value) {
11364
11836
  return Ember.computed.filter(dependentKey + '.@each.' + propertyKey, callback);
11365
11837
  };
11366
11838
 
11839
+ /**
11840
+ @method computed.filterProperty
11841
+ @for Ember
11842
+ @param dependentKey
11843
+ @param propertyKey
11844
+ @param value
11845
+ @deprecated Use `Ember.computed.filterBy` instead
11846
+ */
11847
+ Ember.computed.filterProperty = Ember.computed.filterBy;
11848
+
11849
+ /**
11850
+ A computed property which returns a new array with all the unique
11851
+ elements from one or more dependent arrays.
11852
+
11853
+ Example
11854
+
11855
+ ```javascript
11856
+ App.Hampster = Ember.Object.extend({
11857
+ uniqueFruits: Ember.computed.uniq('fruits')
11858
+ });
11859
+
11860
+ var hampster = App.Hampster.create({fruits: [
11861
+ 'banana',
11862
+ 'grape',
11863
+ 'kale',
11864
+ 'banana'
11865
+ ]});
11866
+ hampster.get('uniqueFruits'); // ['banana', 'grape', 'kale']
11867
+ ```
11868
+
11869
+ @method computed.uniq
11870
+ @for Ember
11871
+ @param {String} propertyKey*
11872
+ @return {Ember.ComputedProperty} computes a new array with all the
11873
+ unique elements from the dependent array
11874
+ */
11367
11875
  Ember.computed.uniq = function() {
11368
11876
  var args = a_slice.call(arguments);
11369
11877
  args.push({
@@ -11372,7 +11880,7 @@ Ember.computed.uniq = function() {
11372
11880
  },
11373
11881
 
11374
11882
  addedItem: function(array, item, changeMeta, instanceMeta) {
11375
- var guid = Ember.guidFor(item);
11883
+ var guid = guidFor(item);
11376
11884
 
11377
11885
  if (!instanceMeta.itemCounts[guid]) {
11378
11886
  instanceMeta.itemCounts[guid] = 1;
@@ -11383,7 +11891,7 @@ Ember.computed.uniq = function() {
11383
11891
  return array;
11384
11892
  },
11385
11893
  removedItem: function(array, item, _, instanceMeta) {
11386
- var guid = Ember.guidFor(item),
11894
+ var guid = guidFor(item),
11387
11895
  itemCounts = instanceMeta.itemCounts;
11388
11896
 
11389
11897
  if (--itemCounts[guid] === 0) {
@@ -11394,12 +11902,44 @@ Ember.computed.uniq = function() {
11394
11902
  });
11395
11903
  return Ember.arrayComputed.apply(null, args);
11396
11904
  };
11905
+
11906
+ /**
11907
+ Alias for [Ember.computed.uniq](/api/#method_computed_uniq).
11908
+
11909
+ @method computed.union
11910
+ @for Ember
11911
+ @param {String} propertyKey*
11912
+ @return {Ember.ComputedProperty} computes a new array with all the
11913
+ unique elements from the dependent array
11914
+ */
11397
11915
  Ember.computed.union = Ember.computed.uniq;
11398
11916
 
11917
+ /**
11918
+ A computed property which returns a new array with all the duplicated
11919
+ elements from two or more dependeny arrays.
11920
+
11921
+ Example
11922
+
11923
+ ```javascript
11924
+ var obj = Ember.Object.createWithMixins({
11925
+ adaFriends: ['Charles Babbage', 'John Hobhouse', 'William King', 'Mary Somerville'],
11926
+ charlesFriends: ['William King', 'Mary Somerville', 'Ada Lovelace', 'George Peacock'],
11927
+ friendsInCommon: Ember.computed.intersect('adaFriends', 'charlesFriends')
11928
+ });
11929
+
11930
+ obj.get('friendsInCommon'); // ['William King', 'Mary Somerville']
11931
+ ```
11932
+
11933
+ @method computed.intersect
11934
+ @for Ember
11935
+ @param {String} propertyKey*
11936
+ @return {Ember.ComputedProperty} computes a new array with all the
11937
+ duplicated elements from the dependent arrays
11938
+ */
11399
11939
  Ember.computed.intersect = function () {
11400
11940
  var getDependentKeyGuids = function (changeMeta) {
11401
11941
  return map(changeMeta.property._dependentKeys, function (dependentKey) {
11402
- return Ember.guidFor(dependentKey);
11942
+ return guidFor(dependentKey);
11403
11943
  });
11404
11944
  };
11405
11945
 
@@ -11410,9 +11950,9 @@ Ember.computed.intersect = function () {
11410
11950
  },
11411
11951
 
11412
11952
  addedItem: function(array, item, changeMeta, instanceMeta) {
11413
- var itemGuid = Ember.guidFor(item),
11953
+ var itemGuid = guidFor(item),
11414
11954
  dependentGuids = getDependentKeyGuids(changeMeta),
11415
- dependentGuid = Ember.guidFor(changeMeta.arrayChanged),
11955
+ dependentGuid = guidFor(changeMeta.arrayChanged),
11416
11956
  numberOfDependentArrays = changeMeta.property._dependentKeys.length,
11417
11957
  itemCounts = instanceMeta.itemCounts;
11418
11958
 
@@ -11421,15 +11961,15 @@ Ember.computed.intersect = function () {
11421
11961
 
11422
11962
  if (++itemCounts[itemGuid][dependentGuid] === 1 &&
11423
11963
  numberOfDependentArrays === Ember.keys(itemCounts[itemGuid]).length) {
11424
-
11964
+
11425
11965
  array.addObject(item);
11426
11966
  }
11427
11967
  return array;
11428
11968
  },
11429
11969
  removedItem: function(array, item, changeMeta, instanceMeta) {
11430
- var itemGuid = Ember.guidFor(item),
11970
+ var itemGuid = guidFor(item),
11431
11971
  dependentGuids = getDependentKeyGuids(changeMeta),
11432
- dependentGuid = Ember.guidFor(changeMeta.arrayChanged),
11972
+ dependentGuid = guidFor(changeMeta.arrayChanged),
11433
11973
  numberOfDependentArrays = changeMeta.property._dependentKeys.length,
11434
11974
  numberOfArraysItemAppearsIn,
11435
11975
  itemCounts = instanceMeta.itemCounts;
@@ -11450,6 +11990,34 @@ Ember.computed.intersect = function () {
11450
11990
  return Ember.arrayComputed.apply(null, args);
11451
11991
  };
11452
11992
 
11993
+ /**
11994
+ A computed property which returns a new array with all the
11995
+ properties from the first dependent array that are not in the second
11996
+ dependent array.
11997
+
11998
+ Example
11999
+
12000
+ ```javascript
12001
+ App.Hampster = Ember.Object.extend({
12002
+ likes: ['banana', 'grape', 'kale'],
12003
+ wants: Ember.computed.setDiff('likes', 'fruits')
12004
+ });
12005
+
12006
+ var hampster = App.Hampster.create({fruits: [
12007
+ 'grape',
12008
+ 'kale',
12009
+ ]});
12010
+ hampster.get('wants'); // ['banana']
12011
+ ```
12012
+
12013
+ @method computed.setDiff
12014
+ @for Ember
12015
+ @param {String} setAProperty
12016
+ @param {String} setBProperty
12017
+ @return {Ember.ComputedProperty} computes a new array with all the
12018
+ items from the first dependent array that are not in the second
12019
+ dependent array
12020
+ */
11453
12021
  Ember.computed.setDiff = function (setAProperty, setBProperty) {
11454
12022
  if (arguments.length !== 2) {
11455
12023
  throw new Error("setDiff requires exactly two dependent arrays.");
@@ -11458,7 +12026,7 @@ Ember.computed.setDiff = function (setAProperty, setBProperty) {
11458
12026
  addedItem: function (array, item, changeMeta, instanceMeta) {
11459
12027
  var setA = get(this, setAProperty),
11460
12028
  setB = get(this, setBProperty);
11461
-
12029
+
11462
12030
  if (changeMeta.arrayChanged === setA) {
11463
12031
  if (!setB.contains(item)) {
11464
12032
  array.addObject(item);
@@ -11472,7 +12040,7 @@ Ember.computed.setDiff = function (setAProperty, setBProperty) {
11472
12040
  removedItem: function (array, item, changeMeta, instanceMeta) {
11473
12041
  var setA = get(this, setAProperty),
11474
12042
  setB = get(this, setBProperty);
11475
-
12043
+
11476
12044
  if (changeMeta.arrayChanged === setB) {
11477
12045
  if (setA.contains(item)) {
11478
12046
  array.addObject(item);
@@ -11486,7 +12054,7 @@ Ember.computed.setDiff = function (setAProperty, setBProperty) {
11486
12054
  };
11487
12055
 
11488
12056
  function binarySearch(array, item, low, high) {
11489
- var mid, midItem, res;
12057
+ var mid, midItem, res, guidMid, guidItem;
11490
12058
 
11491
12059
  if (arguments.length < 4) { high = get(array, 'length'); }
11492
12060
  if (arguments.length < 3) { low = 0; }
@@ -11498,7 +12066,18 @@ function binarySearch(array, item, low, high) {
11498
12066
  mid = low + Math.floor((high - low) / 2);
11499
12067
  midItem = array.objectAt(mid);
11500
12068
 
12069
+ guidMid = _guidFor(midItem);
12070
+ guidItem = _guidFor(item);
12071
+
12072
+ if (guidMid === guidItem) {
12073
+ return mid;
12074
+ }
12075
+
11501
12076
  res = this.order(midItem, item);
12077
+ if (res === 0) {
12078
+ res = guidMid < guidItem ? -1 : 1;
12079
+ }
12080
+
11502
12081
 
11503
12082
  if (res < 0) {
11504
12083
  return this.binarySearch(array, item, mid+1, high);
@@ -11507,8 +12086,66 @@ function binarySearch(array, item, low, high) {
11507
12086
  }
11508
12087
 
11509
12088
  return mid;
12089
+
12090
+ function _guidFor(item) {
12091
+ if (Ember.ObjectProxy.detectInstance(item)) {
12092
+ return guidFor(get(item, 'content'));
12093
+ }
12094
+ return guidFor(item);
12095
+ }
11510
12096
  }
11511
12097
 
12098
+ /**
12099
+ A computed property which returns a new array with all the
12100
+ properties from the first dependent array sorted based on a property
12101
+ or sort function.
12102
+
12103
+ The callback method you provide should have the following signature:
12104
+
12105
+ ```javascript
12106
+ function(itemA, itemB);
12107
+ ```
12108
+
12109
+ - `itemA` the first item to compare.
12110
+ - `itemB` the second item to compare.
12111
+
12112
+ This function should return `-1` when `itemA` should come before
12113
+ `itemB`. It should return `1` when `itemA` should come after
12114
+ `itemB`. If the `itemA` and `itemB` are equal this function should return `0`.
12115
+
12116
+ Example
12117
+
12118
+ ```javascript
12119
+ var ToDoList = Ember.Object.extend({
12120
+ todosSorting: ['name'],
12121
+ sortedTodos: Ember.computed.sort('todos', 'todosSorting'),
12122
+ priorityTodos: Ember.computed.sort('todos', function(a, b){
12123
+ if (a.priority > b.priority) {
12124
+ return 1;
12125
+ } else if (a.priority < b.priority) {
12126
+ return -1;
12127
+ }
12128
+ return 0;
12129
+ }),
12130
+ });
12131
+ var todoList = ToDoList.create({todos: [
12132
+ {name: 'Unit Test', priority: 2},
12133
+ {name: 'Documentation', priority: 3},
12134
+ {name: 'Release', priority: 1}
12135
+ ]});
12136
+
12137
+ todoList.get('sortedTodos'); // [{name:'Documentation', priority:3}, {name:'Release', priority:1}, {name:'Unit Test', priority:2}]
12138
+ todoList.get('priroityTodos'); // [{name:'Release', priority:1}, {name:'Unit Test', priority:2}, {name:'Documentation', priority:3}]
12139
+ ```
12140
+
12141
+ @method computed.sort
12142
+ @for Ember
12143
+ @param {String} dependentKey
12144
+ @param {String or Function} sortDefinition a dependent key to an
12145
+ array of sort properties or a function to use when sorting
12146
+ @return {Ember.ComputedProperty} computes a new sorted array based
12147
+ on the sort property array or callback function
12148
+ */
11512
12149
  Ember.computed.sort = function (itemsKey, sortDefinition) {
11513
12150
 
11514
12151
 
@@ -11595,9 +12232,8 @@ Ember.computed.sort = function (itemsKey, sortDefinition) {
11595
12232
  removedItem: function (array, item, changeMeta, instanceMeta) {
11596
12233
  var proxyProperties, index, searchItem;
11597
12234
 
11598
- if (changeMeta.keyChanged) {
11599
- proxyProperties = { content: item };
11600
- proxyProperties[changeMeta.keyChanged] = changeMeta.previousValue;
12235
+ if (changeMeta.previousValues) {
12236
+ proxyProperties = merge({ content: item }, changeMeta.previousValues);
11601
12237
 
11602
12238
  searchItem = Ember.ObjectProxy.create(proxyProperties);
11603
12239
  } else {
@@ -12021,9 +12657,9 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Function) {
12021
12657
  Computed properties allow you to treat a function like a property:
12022
12658
 
12023
12659
  ```javascript
12024
- MyApp.president = Ember.Object.create({
12025
- firstName: "Barack",
12026
- lastName: "Obama",
12660
+ MyApp.President = Ember.Object.extend({
12661
+ firstName: '',
12662
+ lastName: '',
12027
12663
 
12028
12664
  fullName: function() {
12029
12665
  return this.get('firstName') + ' ' + this.get('lastName');
@@ -12032,7 +12668,12 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Function) {
12032
12668
  }.property()
12033
12669
  });
12034
12670
 
12035
- MyApp.president.get('fullName'); // "Barack Obama"
12671
+ var president = MyApp.President.create({
12672
+ firstName: "Barack",
12673
+ lastName: "Obama"
12674
+ });
12675
+
12676
+ president.get('fullName'); // "Barack Obama"
12036
12677
  ```
12037
12678
 
12038
12679
  Treating a function like a property is useful because they can work with
@@ -12044,9 +12685,9 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Function) {
12044
12685
  about these dependencies like this:
12045
12686
 
12046
12687
  ```javascript
12047
- MyApp.president = Ember.Object.create({
12048
- firstName: "Barack",
12049
- lastName: "Obama",
12688
+ MyApp.President = Ember.Object.extend({
12689
+ firstName: '',
12690
+ lastName: '',
12050
12691
 
12051
12692
  fullName: function() {
12052
12693
  return this.get('firstName') + ' ' + this.get('lastName');
@@ -12083,15 +12724,18 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Function) {
12083
12724
  For example:
12084
12725
 
12085
12726
  ```javascript
12086
- Ember.Object.create({
12727
+ Ember.Object.extend({
12087
12728
  valueObserver: function() {
12088
12729
  // Executes whenever the "value" property changes
12089
12730
  }.observes('value')
12090
12731
  });
12091
12732
  ```
12092
12733
 
12093
- See `Ember.observes`.
12094
-
12734
+ In the future this method may become asynchronous. If you want to ensure
12735
+ synchronous behavior, use `observesImmediately`.
12736
+
12737
+ See `Ember.observer`.
12738
+
12095
12739
  @method observes
12096
12740
  @for Function
12097
12741
  */
@@ -12100,24 +12744,58 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Function) {
12100
12744
  return this;
12101
12745
  };
12102
12746
 
12747
+ /**
12748
+ The `observesImmediately` extension of Javascript's Function prototype is
12749
+ available when `Ember.EXTEND_PROTOTYPES` or
12750
+ `Ember.EXTEND_PROTOTYPES.Function` is true, which is the default.
12751
+
12752
+ You can observe property changes simply by adding the `observesImmediately`
12753
+ call to the end of your method declarations in classes that you write.
12754
+ For example:
12755
+
12756
+ ```javascript
12757
+ Ember.Object.extend({
12758
+ valueObserver: function() {
12759
+ // Executes immediately after the "value" property changes
12760
+ }.observesImmediately('value')
12761
+ });
12762
+ ```
12763
+
12764
+ In the future, `observes` may become asynchronous. In this event,
12765
+ `observesImmediately` will maintain the synchronous behavior.
12766
+
12767
+ See `Ember.immediateObserver`.
12768
+
12769
+ @method observesImmediately
12770
+ @for Function
12771
+ */
12772
+ Function.prototype.observesImmediately = function() {
12773
+ for (var i=0, l=arguments.length; i<l; i++) {
12774
+ var arg = arguments[i];
12775
+
12776
+ }
12777
+
12778
+ return this.observes.apply(this, arguments);
12779
+ };
12780
+
12103
12781
  /**
12104
12782
  The `observesBefore` extension of Javascript's Function prototype is
12105
12783
  available when `Ember.EXTEND_PROTOTYPES` or
12106
12784
  `Ember.EXTEND_PROTOTYPES.Function` is true, which is the default.
12107
12785
 
12108
- You can get notified when a property changes is about to happen by
12786
+ You can get notified when a property change is about to happen by
12109
12787
  by adding the `observesBefore` call to the end of your method
12110
12788
  declarations in classes that you write. For example:
12111
12789
 
12112
12790
  ```javascript
12113
- Ember.Object.create({
12791
+ Ember.Object.extend({
12114
12792
  valueObserver: function() {
12115
12793
  // Executes whenever the "value" property is about to change
12116
12794
  }.observesBefore('value')
12117
12795
  });
12118
12796
  ```
12119
12797
 
12120
- See `Ember.observesBefore`.
12798
+ See `Ember.beforeObserver`.
12121
12799
 
12122
12800
  @method observesBefore
12123
12801
  @for Function
@@ -13560,11 +14238,6 @@ Ember.Evented = Ember.Mixin.create({
13560
14238
  Ember.sendEvent(this, name, args);
13561
14239
  },
13562
14240
 
13563
- fire: function(name) {
13564
-
13565
- this.trigger.apply(this, arguments);
13566
- },
13567
-
13568
14241
  /**
13569
14242
  Cancels subscription for given name, target, and method.
13570
14243
 
@@ -13743,6 +14416,121 @@ Ember.ActionHandler = Ember.Mixin.create({
13743
14416
 
13744
14417
 
13745
14418
 
14419
+ (function() {
14420
+ var set = Ember.set, get = Ember.get,
14421
+ resolve = Ember.RSVP.resolve,
14422
+ rethrow = Ember.RSVP.rethrow,
14423
+ not = Ember.computed.not,
14424
+ or = Ember.computed.or;
14425
+
14426
+ /**
14427
+ @module ember
14428
+ @submodule ember-runtime
14429
+ */
14430
+
14431
+ function installPromise(proxy, promise) {
14432
+ promise.then(function(value) {
14433
+ set(proxy, 'isFulfilled', true);
14434
+ set(proxy, 'content', value);
14435
+
14436
+ return value;
14437
+ }, function(reason) {
14438
+ set(proxy, 'isRejected', true);
14439
+ set(proxy, 'reason', reason);
14440
+ }).fail(rethrow);
14441
+ }
14442
+
14443
+ /**
14444
+ A low level mixin making ObjectProxy, ObjectController or ArrayController's promise aware.
14445
+
14446
+ ```javascript
14447
+ var ObjectPromiseController = Ember.ObjectController.extend(Ember.PromiseProxyMixin);
14448
+
14449
+ var controller = ObjectPromiseController.create({
14450
+ promise: $.getJSON('/some/remote/data.json')
14451
+ });
14452
+
14453
+ controller.then(function(json){
14454
+ // the json
14455
+ }, function(reason) {
14456
+ // the reason why you have no json
14457
+ });
14458
+ ```
14459
+
14460
+ the controller has bindable attributes which
14461
+ track the promises life cycle
14462
+
14463
+ ```javascript
14464
+ controller.get('isPending') //=> true
14465
+ controller.get('isSettled') //=> false
14466
+ controller.get('isRejected') //=> false
14467
+ controller.get('isFulfilled') //=> false
14468
+ ```
14469
+
14470
+ When the the $.getJSON completes, and the promise is fulfilled
14471
+ with json, the life cycle attributes will update accordingly.
14472
+
14473
+ ```javascript
14474
+ controller.get('isPending') //=> false
14475
+ controller.get('isSettled') //=> true
14476
+ controller.get('isRejected') //=> false
14477
+ controller.get('isFulfilled') //=> true
14478
+ ```
14479
+
14480
+ As the controller is an ObjectController, and the json now its content,
14481
+ all the json properties will be available directly from the controller.
14482
+
14483
+ ```javascript
14484
+ // Assuming the following json:
14485
+ {
14486
+ firstName: 'Stefan',
14487
+ lastName: 'Penner'
14488
+ }
14489
+
14490
+ // both properties will accessible on the controller
14491
+ controller.get('firstName') //=> 'Stefan'
14492
+ controller.get('lastName') //=> 'Penner'
14493
+ ```
14494
+
14495
+ If the controller is backing a template, the attributes are
14496
+ bindable from within that template
14497
+ ```handlebars
14498
+ {{#if isPending}}
14499
+ loading...
14500
+ {{else}}
14501
+ firstName: {{firstName}}
14502
+ lastName: {{lastName}}
14503
+ {{/if}}
14504
+ ```
14505
+ @class Ember.PromiseProxyMixin
14506
+ */
14507
+ Ember.PromiseProxyMixin = Ember.Mixin.create({
14508
+ reason: null,
14509
+ isPending: not('isSettled').readOnly(),
14510
+ isSettled: or('isRejected', 'isFulfilled').readOnly(),
14511
+ isRejected: false,
14512
+ isFulfilled: false,
14513
+
14514
+ promise: Ember.computed(function(key, promise) {
14515
+ if (arguments.length === 2) {
14516
+ promise = resolve(promise);
14517
+ installPromise(this, promise);
14518
+ return promise;
14519
+ } else {
14520
+ throw new Error("PromiseProxy's promise must be set");
14521
+ }
14522
+ }),
14523
+
14524
+ then: function(fulfill, reject) {
14525
+ return get(this, 'promise').then(fulfill, reject);
14526
+ }
14527
+ });
14528
+
14529
+
14530
+ })();
14531
+
14532
+
14533
+
13746
14534
  (function() {
13747
14535
 
13748
14536
  })();
@@ -15438,7 +16226,9 @@ var get = Ember.get,
15438
16226
  removeBeforeObserver = Ember.removeBeforeObserver,
15439
16227
  removeObserver = Ember.removeObserver,
15440
16228
  propertyWillChange = Ember.propertyWillChange,
15441
- propertyDidChange = Ember.propertyDidChange;
16229
+ propertyDidChange = Ember.propertyDidChange,
16230
+ meta = Ember.meta,
16231
+ defineProperty = Ember.defineProperty;
15442
16232
 
15443
16233
  function contentPropertyWillChange(content, contentKey) {
15444
16234
  var key = contentKey.slice(8); // remove "content."
@@ -15556,6 +16346,14 @@ Ember.ObjectProxy = Ember.Object.extend(/** @scope Ember.ObjectProxy.prototype *
15556
16346
  },
15557
16347
 
15558
16348
  setUnknownProperty: function (key, value) {
16349
+ var m = meta(this);
16350
+ if (m.proto === this) {
16351
+ // if marked as prototype then just defineProperty
16352
+ // rather than delegate
16353
+ defineProperty(this, key, null, value);
16354
+ return value;
16355
+ }
16356
+
15559
16357
  var content = get(this, 'content');
15560
16358
 
15561
16359
  return set(content, key, value);
@@ -15563,25 +16361,6 @@ Ember.ObjectProxy = Ember.Object.extend(/** @scope Ember.ObjectProxy.prototype *
15563
16361
 
15564
16362
  });
15565
16363
 
15566
- Ember.ObjectProxy.reopenClass({
15567
- create: function () {
15568
- var mixin, prototype, i, l, properties, keyName;
15569
- if (arguments.length) {
15570
- prototype = this.proto();
15571
- for (i = 0, l = arguments.length; i < l; i++) {
15572
- properties = arguments[i];
15573
- for (keyName in properties) {
15574
- if (!properties.hasOwnProperty(keyName) || keyName in prototype) { continue; }
15575
- if (!mixin) mixin = {};
15576
- mixin[keyName] = null;
15577
- }
15578
- }
15579
- if (mixin) this._initMixins([mixin]);
15580
- }
15581
- return this._super.apply(this, arguments);
15582
- }
15583
- });
15584
-
15585
16364
  })();
15586
16365
 
15587
16366
 
@@ -15594,7 +16373,8 @@ Ember.ObjectProxy.reopenClass({
15594
16373
 
15595
16374
 
15596
16375
  var set = Ember.set, get = Ember.get, guidFor = Ember.guidFor;
15597
- var forEach = Ember.EnumerableUtils.forEach;
16376
+ var forEach = Ember.EnumerableUtils.forEach,
16377
+ indexOf = Ember.ArrayPolyfills.indexOf;
15598
16378
 
15599
16379
  var EachArray = Ember.Object.extend(Ember.Array, {
15600
16380
 
@@ -15652,7 +16432,7 @@ function removeObserverForContentKey(content, keyName, proxy, idx, loc) {
15652
16432
 
15653
16433
  guid = guidFor(item);
15654
16434
  indicies = objects[guid];
15655
- indicies[indicies.indexOf(loc)] = null;
16435
+ indicies[indexOf.call(indicies, loc)] = null;
15656
16436
  }
15657
16437
  }
15658
16438
  }
@@ -17056,11 +17836,15 @@ Ember.ArrayController = Ember.ArrayProxy.extend(Ember.ControllerMixin,
17056
17836
  },
17057
17837
 
17058
17838
  init: function() {
17059
- if (!this.get('content')) { Ember.defineProperty(this, 'content', undefined, Ember.A()); }
17060
17839
  this._super();
17840
+
17061
17841
  this.set('_subControllers', Ember.A());
17062
17842
  },
17063
17843
 
17844
+ content: Ember.computed(function () {
17845
+ return Ember.A();
17846
+ }),
17847
+
17064
17848
  controllerAt: function(idx, object, controllerClass) {
17065
17849
  var container = get(this, 'container'),
17066
17850
  subControllers = get(this, '_subControllers'),
@@ -18712,9 +19496,6 @@ var EMPTY_ARRAY = [];
18712
19496
  Using a value for `templateName` that does not have a Handlebars template
18713
19497
  with a matching `data-template-name` attribute will throw an error.
18714
19498
 
18715
- Assigning a value to both `template` and `templateName` properties will throw
18716
- an error.
18717
-
18718
19499
  For views classes that may have a template later defined (e.g. as the block
18719
19500
  portion of a `{{view}}` Handlebars helper call in another template or in
18720
19501
  a subclass), you can provide a `defaultTemplate` property set to compiled
@@ -21251,7 +22032,7 @@ Ember.ContainerView = Ember.View.extend(Ember.MutableArray, {
21251
22032
 
21252
22033
  length: Ember.computed(function () {
21253
22034
  return this._childViews.length;
21254
- }),
22035
+ }).volatile(),
21255
22036
 
21256
22037
  /**
21257
22038
  @private
@@ -21581,11 +22362,6 @@ var get = Ember.get, set = Ember.set, fmt = Ember.String.fmt;
21581
22362
  manipulated. Instead, add, remove, replace items from its `content` property.
21582
22363
  This will trigger appropriate changes to its rendered HTML.
21583
22364
 
21584
- ## Use in templates via the `{{collection}}` `Ember.Handlebars` helper
21585
-
21586
- `Ember.Handlebars` provides a helper specifically for adding
21587
- `CollectionView`s to templates. See [Ember.Handlebars.helpers.collection](/api/classes/Ember.Handlebars.helpers.html#method_collection)
21588
- for more details
21589
22365
 
21590
22366
  @class CollectionView
21591
22367
  @namespace Ember
@@ -21893,7 +22669,7 @@ var get = Ember.get, set = Ember.set, isNone = Ember.isNone;
21893
22669
  ```html
21894
22670
  <!-- app-profile template -->
21895
22671
  <h1>{{person.title}}</h1>
21896
- <img {{bindAttr src=person.avatar}}>
22672
+ <img {{bind-attr src=person.avatar}}>
21897
22673
  <p class='signature'>{{person.signature}}</p>
21898
22674
  ```
21899
22675
 
@@ -21915,7 +22691,7 @@ var get = Ember.get, set = Ember.set, isNone = Ember.isNone;
21915
22691
  If you want to customize the component, in order to
21916
22692
  handle events or actions, you implement a subclass
21917
22693
  of `Ember.Component` named after the name of the
21918
- component. Note that `Component` needs to be appended to the name of
22694
+ component. Note that `Component` needs to be appended to the name of
21919
22695
  your subclass like `AppProfileComponent`.
21920
22696
 
21921
22697
  For example, you could implement the action
@@ -21977,6 +22753,7 @@ Ember.Component = Ember.View.extend(Ember.TargetActionSupport, {
21977
22753
  view.appendChild(Ember.View, {
21978
22754
  isVirtual: true,
21979
22755
  tagName: '',
22756
+ _contextView: parentView,
21980
22757
  template: get(this, 'template'),
21981
22758
  context: get(parentView, 'context'),
21982
22759
  controller: get(parentView, 'controller'),
@@ -22725,17 +23502,8 @@ function makeBindings(options) {
22725
23502
  @param {String} dependentKeys*
22726
23503
  */
22727
23504
  Ember.Handlebars.helper = function(name, value) {
22728
- if (Ember.Component.detect(value)) {
22729
23505
 
22730
23506
 
22731
- var proto = value.proto();
22732
- if (!proto.layoutName && !proto.templateName) {
22733
- value.reopen({
22734
- layoutName: 'components/' + name
22735
- });
22736
- }
22737
- }
22738
-
22739
23507
  if (Ember.View.detect(value)) {
22740
23508
  Ember.Handlebars.registerHelper(name, function(options) {
22741
23509
 
@@ -23524,6 +24292,8 @@ function SimpleHandlebarsView(path, pathRoot, isEscaped, templateData) {
23524
24292
  this.morph = Metamorph();
23525
24293
  this.state = 'preRender';
23526
24294
  this.updateId = null;
24295
+ this._parentView = null;
24296
+ this.buffer = null;
23527
24297
  }
23528
24298
 
23529
24299
  Ember._SimpleHandlebarsView = SimpleHandlebarsView;
@@ -23537,7 +24307,11 @@ SimpleHandlebarsView.prototype = {
23537
24307
  Ember.run.cancel(this.updateId);
23538
24308
  this.updateId = null;
23539
24309
  }
24310
+ if (this._parentView) {
24311
+ this._parentView.removeChild(this);
24312
+ }
23540
24313
  this.morph = null;
24314
+ this.state = 'destroyed';
23541
24315
  },
23542
24316
 
23543
24317
  propertyWillChange: Ember.K,
@@ -23592,7 +24366,7 @@ SimpleHandlebarsView.prototype = {
23592
24366
  rerender: function() {
23593
24367
  switch(this.state) {
23594
24368
  case 'preRender':
23595
- case 'destroying':
24369
+ case 'destroyed':
23596
24370
  break;
23597
24371
  case 'inBuffer':
23598
24372
  throw new Ember.Error("Something you did tried to replace an {{expression}} before it was inserted into the DOM.");
@@ -25286,6 +26060,8 @@ GroupedEach.prototype = {
25286
26060
  },
25287
26061
 
25288
26062
  addArrayObservers: function() {
26063
+ if (!this.content) { return; }
26064
+
25289
26065
  this.content.addArrayObserver(this, {
25290
26066
  willChange: 'contentArrayWillChange',
25291
26067
  didChange: 'contentArrayDidChange'
@@ -25293,6 +26069,8 @@ GroupedEach.prototype = {
25293
26069
  },
25294
26070
 
25295
26071
  removeArrayObservers: function() {
26072
+ if (!this.content) { return; }
26073
+
25296
26074
  this.content.removeArrayObserver(this, {
25297
26075
  willChange: 'contentArrayWillChange',
25298
26076
  didChange: 'contentArrayDidChange'
@@ -25310,6 +26088,8 @@ GroupedEach.prototype = {
25310
26088
  },
25311
26089
 
25312
26090
  render: function() {
26091
+ if (!this.content) { return; }
26092
+
25313
26093
  var content = this.content,
25314
26094
  contentLength = get(content, 'length'),
25315
26095
  data = this.options.data,
@@ -25322,12 +26102,21 @@ GroupedEach.prototype = {
25322
26102
  },
25323
26103
 
25324
26104
  rerenderContainingView: function() {
25325
- Ember.run.scheduleOnce('render', this.containingView, 'rerender');
26105
+ var self = this;
26106
+ Ember.run.scheduleOnce('render', this, function() {
26107
+ // It's possible it's been destroyed after we enqueued a re-render call.
26108
+ if (!self.destroyed) {
26109
+ self.containingView.rerender();
26110
+ }
26111
+ });
25326
26112
  },
25327
26113
 
25328
26114
  destroy: function() {
25329
26115
  this.removeContentObservers();
25330
- this.removeArrayObservers();
26116
+ if (this.content) {
26117
+ this.removeArrayObservers();
26118
+ }
26119
+ this.destroyed = true;
25331
26120
  }
25332
26121
  };
25333
26122
 
@@ -25667,20 +26456,20 @@ var get = Ember.get, set = Ember.set;
25667
26456
  inserting the view's own rendered output at the `{{yield}}` location.
25668
26457
 
25669
26458
  An empty `<body>` and the following application code:
25670
-
26459
+
25671
26460
  ```javascript
25672
26461
  AView = Ember.View.extend({
25673
26462
  classNames: ['a-view-with-layout'],
25674
26463
  layout: Ember.Handlebars.compile('<div class="wrapper">{{yield}}</div>'),
25675
26464
  template: Ember.Handlebars.compile('<span>I am wrapped</span>')
25676
26465
  });
25677
-
26466
+
25678
26467
  aView = AView.create();
25679
26468
  aView.appendTo('body');
25680
26469
  ```
25681
-
26470
+
25682
26471
  Will result in the following HTML output:
25683
-
26472
+
25684
26473
  ```html
25685
26474
  <body>
25686
26475
  <div class='ember-view a-view-with-layout'>
@@ -25690,50 +26479,50 @@ var get = Ember.get, set = Ember.set;
25690
26479
  </div>
25691
26480
  </body>
25692
26481
  ```
25693
-
26482
+
25694
26483
  The `yield` helper cannot be used outside of a template assigned to an
25695
26484
  `Ember.View`'s `layout` property and will throw an error if attempted.
25696
-
26485
+
25697
26486
  ```javascript
25698
26487
  BView = Ember.View.extend({
25699
26488
  classNames: ['a-view-with-layout'],
25700
26489
  template: Ember.Handlebars.compile('{{yield}}')
25701
26490
  });
25702
-
26491
+
25703
26492
  bView = BView.create();
25704
26493
  bView.appendTo('body');
25705
-
26494
+
25706
26495
  // throws
25707
- // Uncaught Error: assertion failed:
26496
+ // Uncaught Error: assertion failed:
25708
26497
  // You called yield in a template that was not a layout
25709
26498
  ```
25710
26499
 
25711
26500
  ### Use with Ember.Component
25712
26501
  When designing components `{{yield}}` is used to denote where, inside the component's
25713
26502
  template, an optional block passed to the component should render:
25714
-
26503
+
25715
26504
  ```handlebars
25716
26505
  <!-- application.hbs -->
25717
26506
  {{#labeled-textfield value=someProperty}}
25718
26507
  First name:
25719
26508
  {{/my-component}}
25720
26509
  ```
25721
-
26510
+
25722
26511
  ```handlebars
25723
26512
  <!-- components/my-component.hbs -->
25724
26513
  <label>
25725
26514
  {{yield}} {{input value=value}}
25726
26515
  </label>
25727
26516
  ```
25728
-
26517
+
25729
26518
  Result:
25730
-
26519
+
25731
26520
  ```html
25732
26521
  <label>
25733
26522
  First name: <input type="text" />
25734
26523
  <label>
25735
26524
  ```
25736
-
26525
+
25737
26526
  @method yield
25738
26527
  @for Ember.Handlebars.helpers
25739
26528
  @param {Hash} options
@@ -25743,7 +26532,11 @@ Ember.Handlebars.registerHelper('yield', function(options) {
25743
26532
  var view = options.data.view;
25744
26533
 
25745
26534
  while (view && !get(view, 'layout')) {
25746
- view = get(view, 'parentView');
26535
+ if (view._contextView) {
26536
+ view = view._contextView;
26537
+ } else {
26538
+ view = get(view, 'parentView');
26539
+ }
25747
26540
  }
25748
26541
 
25749
26542
 
@@ -25884,9 +26677,6 @@ Ember.TextSupport = Ember.Mixin.create({
25884
26677
  disabled: false,
25885
26678
  maxlength: null,
25886
26679
 
25887
- insertNewline: Ember.K,
25888
- cancel: Ember.K,
25889
-
25890
26680
  init: function() {
25891
26681
  this._super();
25892
26682
  this.on("focusOut", this, this._elementValueDidChange);
@@ -25897,99 +26687,6 @@ Ember.TextSupport = Ember.Mixin.create({
25897
26687
  this.on("keyUp", this, this.interpretKeyEvents);
25898
26688
  },
25899
26689
 
25900
- interpretKeyEvents: function(event) {
25901
- var map = Ember.TextSupport.KEY_EVENTS;
25902
- var method = map[event.keyCode];
25903
-
25904
- this._elementValueDidChange();
25905
- if (method) { return this[method](event); }
25906
- },
25907
-
25908
- _elementValueDidChange: function() {
25909
- set(this, 'value', this.$().val());
25910
- }
25911
-
25912
- });
25913
-
25914
- Ember.TextSupport.KEY_EVENTS = {
25915
- 13: 'insertNewline',
25916
- 27: 'cancel'
25917
- };
25918
-
25919
- })();
25920
-
25921
-
25922
-
25923
- (function() {
25924
- /**
25925
- @module ember
25926
- @submodule ember-handlebars
25927
- */
25928
-
25929
- var get = Ember.get, set = Ember.set;
25930
-
25931
- /**
25932
-
25933
- The internal class used to create text inputs when the `{{input}}`
25934
- helper is used with `type` of `text`.
25935
-
25936
- See Handlebars.helpers.input for usage details.
25937
-
25938
- ## Layout and LayoutName properties
25939
-
25940
- Because HTML `input` elements are self closing `layout` and `layoutName`
25941
- properties will not be applied. See [Ember.View](/api/classes/Ember.View.html)'s
25942
- layout section for more information.
25943
-
25944
- @class TextField
25945
- @namespace Ember
25946
- @extends Ember.View
25947
- @uses Ember.TextSupport
25948
- */
25949
- Ember.TextField = Ember.View.extend(Ember.TextSupport,
25950
- /** @scope Ember.TextField.prototype */ {
25951
-
25952
- classNames: ['ember-text-field'],
25953
- tagName: "input",
25954
- attributeBindings: ['type', 'value', 'size', 'pattern', 'name'],
25955
-
25956
- /**
25957
- The `value` attribute of the input element. As the user inputs text, this
25958
- property is updated live.
25959
-
25960
- @property value
25961
- @type String
25962
- @default ""
25963
- */
25964
- value: "",
25965
-
25966
- /**
25967
- The `type` attribute of the input element.
25968
-
25969
- @property type
25970
- @type String
25971
- @default "text"
25972
- */
25973
- type: "text",
25974
-
25975
- /**
25976
- The `size` of the text field in characters.
25977
-
25978
- @property size
25979
- @type String
25980
- @default null
25981
- */
25982
- size: null,
25983
-
25984
- /**
25985
- The `pattern` the pattern attribute of input element.
25986
-
25987
- @property pattern
25988
- @type String
25989
- @default null
25990
- */
25991
- pattern: null,
25992
-
25993
26690
  /**
25994
26691
  The action to be sent when the user presses the return key.
25995
26692
 
@@ -26034,6 +26731,18 @@ Ember.TextField = Ember.View.extend(Ember.TextSupport,
26034
26731
  */
26035
26732
  bubbles: false,
26036
26733
 
26734
+ interpretKeyEvents: function(event) {
26735
+ var map = Ember.TextSupport.KEY_EVENTS;
26736
+ var method = map[event.keyCode];
26737
+
26738
+ this._elementValueDidChange();
26739
+ if (method) { return this[method](event); }
26740
+ },
26741
+
26742
+ _elementValueDidChange: function() {
26743
+ set(this, 'value', this.$().val());
26744
+ },
26745
+
26037
26746
  /**
26038
26747
  The action to be sent when the user inserts a new line.
26039
26748
 
@@ -26045,6 +26754,40 @@ Ember.TextField = Ember.View.extend(Ember.TextSupport,
26045
26754
  */
26046
26755
  insertNewline: function(event) {
26047
26756
  sendAction('enter', this, event);
26757
+ sendAction('insert-newline', this, event);
26758
+ },
26759
+
26760
+ /**
26761
+ Called when the user hits escape.
26762
+
26763
+ Called by the `Ember.TextSupport` mixin on keyUp if keycode matches 13.
26764
+ Uses sendAction to send the `enter` action to the controller.
26765
+
26766
+ @method cancel
26767
+ @param {Event} event
26768
+ */
26769
+ cancel: function(event) {
26770
+ sendAction('escape-press', this, event);
26771
+ },
26772
+
26773
+ /**
26774
+ Called when the text area is focused.
26775
+
26776
+ @method focusIn
26777
+ @param {Event} event
26778
+ */
26779
+ focusIn: function(event) {
26780
+ sendAction('focus-in', this, event);
26781
+ },
26782
+
26783
+ /**
26784
+ Called when the text area is blurred.
26785
+
26786
+ @method focusOut
26787
+ @param {Event} event
26788
+ */
26789
+ focusOut: function(event) {
26790
+ sendAction('focus-out', this, event);
26048
26791
  },
26049
26792
 
26050
26793
  /**
@@ -26057,22 +26800,35 @@ Ember.TextField = Ember.View.extend(Ember.TextSupport,
26057
26800
  @param {Event} event
26058
26801
  */
26059
26802
  keyPress: function(event) {
26060
- sendAction('keyPress', this, event);
26803
+ sendAction('key-press', this, event);
26061
26804
  }
26805
+
26062
26806
  });
26063
26807
 
26808
+ Ember.TextSupport.KEY_EVENTS = {
26809
+ 13: 'insertNewline',
26810
+ 27: 'cancel'
26811
+ };
26812
+
26813
+ // In principle, this shouldn't be necessary, but the legacy
26814
+ // sectionAction semantics for TextField are different from
26815
+ // the component semantics so this method normalizes them.
26064
26816
  function sendAction(eventName, view, event) {
26065
- var action = get(view, 'action'),
26066
- on = get(view, 'onEvent');
26817
+ var action = get(view, eventName),
26818
+ on = get(view, 'onEvent'),
26819
+ value = get(view, 'value');
26067
26820
 
26068
- if (action && on === eventName) {
26069
- var controller = get(view, 'controller'),
26070
- value = get(view, 'value'),
26071
- bubbles = get(view, 'bubbles');
26821
+ // back-compat support for keyPress as an event name even though
26822
+ // it's also a method name that consumes the event (and therefore
26823
+ // incompatible with sendAction semantics).
26824
+ if (on === eventName || (on === 'keyPress' && eventName === 'key-press')) {
26825
+ view.sendAction('action', value);
26826
+ }
26072
26827
 
26073
- controller.send(action, value, view);
26828
+ view.sendAction(eventName, value);
26074
26829
 
26075
- if (!bubbles) {
26830
+ if (action || on === eventName) {
26831
+ if(!get(view, 'bubbles')) {
26076
26832
  event.stopPropagation();
26077
26833
  }
26078
26834
  }
@@ -26082,6 +26838,81 @@ function sendAction(eventName, view, event) {
26082
26838
 
26083
26839
 
26084
26840
 
26841
+ (function() {
26842
+ /**
26843
+ @module ember
26844
+ @submodule ember-handlebars
26845
+ */
26846
+
26847
+ var get = Ember.get, set = Ember.set;
26848
+
26849
+ /**
26850
+
26851
+ The internal class used to create text inputs when the `{{input}}`
26852
+ helper is used with `type` of `text`.
26853
+
26854
+ See Handlebars.helpers.input for usage details.
26855
+
26856
+ ## Layout and LayoutName properties
26857
+
26858
+ Because HTML `input` elements are self closing `layout` and `layoutName`
26859
+ properties will not be applied. See [Ember.View](/api/classes/Ember.View.html)'s
26860
+ layout section for more information.
26861
+
26862
+ @class TextField
26863
+ @namespace Ember
26864
+ @extends Ember.View
26865
+ @uses Ember.TextSupport
26866
+ */
26867
+ Ember.TextField = Ember.Component.extend(Ember.TextSupport,
26868
+ /** @scope Ember.TextField.prototype */ {
26869
+
26870
+ classNames: ['ember-text-field'],
26871
+ tagName: "input",
26872
+ attributeBindings: ['type', 'value', 'size', 'pattern', 'name'],
26873
+
26874
+ /**
26875
+ The `value` attribute of the input element. As the user inputs text, this
26876
+ property is updated live.
26877
+
26878
+ @property value
26879
+ @type String
26880
+ @default ""
26881
+ */
26882
+ value: "",
26883
+
26884
+ /**
26885
+ The `type` attribute of the input element.
26886
+
26887
+ @property type
26888
+ @type String
26889
+ @default "text"
26890
+ */
26891
+ type: "text",
26892
+
26893
+ /**
26894
+ The `size` of the text field in characters.
26895
+
26896
+ @property size
26897
+ @type String
26898
+ @default null
26899
+ */
26900
+ size: null,
26901
+
26902
+ /**
26903
+ The `pattern` the pattern attribute of input element.
26904
+
26905
+ @property pattern
26906
+ @type String
26907
+ @default null
26908
+ */
26909
+ pattern: null
26910
+ });
26911
+
26912
+ })();
26913
+
26914
+
26915
+
26085
26916
  (function() {
26086
26917
  /*
26087
26918
  @module ember
@@ -26235,7 +27066,7 @@ var get = Ember.get, set = Ember.set;
26235
27066
  @extends Ember.View
26236
27067
  @uses Ember.TextSupport
26237
27068
  */
26238
- Ember.TextArea = Ember.View.extend(Ember.TextSupport, {
27069
+ Ember.TextArea = Ember.Component.extend(Ember.TextSupport, {
26239
27070
  classNames: ['ember-text-area'],
26240
27071
 
26241
27072
  tagName: "textarea",
@@ -28776,8 +29607,6 @@ define("router",
28776
29607
 
28777
29608
  var params = paramsForHandler(router, handlerName, objects);
28778
29609
 
28779
- transition.providedModelsArray = [];
28780
- transition.providedContexts = {};
28781
29610
  router.currentParams = params;
28782
29611
 
28783
29612
  var urlMethod = transition.urlMethod;
@@ -29394,6 +30223,7 @@ Ember.Router = Ember.Object.extend({
29394
30223
  if (passedName.charAt(0) === '/') {
29395
30224
  name = passedName;
29396
30225
  } else {
30226
+
29397
30227
  if (!this.router.hasRoute(passedName)) {
29398
30228
  name = args[0] = passedName + '.index';
29399
30229
  } else {
@@ -29411,6 +30241,8 @@ Ember.Router = Ember.Object.extend({
29411
30241
 
29412
30242
  transitionPromise.then(function(route) {
29413
30243
  self._transitionCompleted(route);
30244
+ }, function(error){
30245
+
29414
30246
  });
29415
30247
 
29416
30248
  // We want to return the configurable promise object
@@ -29620,18 +30452,81 @@ Ember.Route = Ember.Object.extend(Ember.ActionHandler, {
29620
30452
  this.send('playMusic');
29621
30453
  ```
29622
30454
 
30455
+ Within a route's action handler, the value of the `this` context
30456
+ is the Route object:
30457
+
30458
+ ```js
30459
+ App.SongRoute = Ember.Route.extend({
30460
+ actions: {
30461
+ myAction: function() {
30462
+ this.controllerFor("song");
30463
+ this.transitionTo("other.route");
30464
+ ...
30465
+ }
30466
+ }
30467
+ });
30468
+ ```
30469
+
29623
30470
  It is also possible to call `this._super()` from within an
29624
- action handler if it overrides a handle defined on a parent
29625
- class or mixin.
30471
+ action handler if it overrides a handler defined on a parent
30472
+ class or mixin:
29626
30473
 
29627
- Within a route's action handler, the value of the `this` context
29628
- is the Route object.
30474
+ Take for example the following routes:
30475
+
30476
+ ```js
30477
+ App.DebugRoute = Ember.Mixin.create({
30478
+ actions: {
30479
+ debugRouteInformation: function() {
30480
+ console.debug("trololo");
30481
+ }
30482
+ }
30483
+ });
30484
+
30485
+ App.AnnoyingDebugRoute = Ember.Route.extend(App.DebugRoute, {
30486
+ actions: {
30487
+ debugRouteInformation: function() {
30488
+ // also call the debugRouteInformation of mixed in App.DebugRoute
30489
+ this._super();
30490
+
30491
+ // show additional annoyance
30492
+ window.alert(...);
30493
+ }
30494
+ }
30495
+ });
30496
+ ```
29629
30497
 
29630
30498
  ## Bubbling
29631
30499
 
29632
30500
  By default, an action will stop bubbling once a handler defined
29633
30501
  on the `actions` hash handles it. To continue bubbling the action,
29634
- you must return `true` from the handler.
30502
+ you must return `true` from the handler:
30503
+
30504
+ ```js
30505
+ App.Router.map(function() {
30506
+ this.resource("album", function() {
30507
+ this.route("song");
30508
+ });
30509
+ });
30510
+
30511
+ App.AlbumRoute = Ember.Route.extend({
30512
+ actions: {
30513
+ startPlaying: function() {
30514
+ }
30515
+ }
30516
+ });
30517
+
30518
+ App.AlbumSongRoute = Ember.Route.extend({
30519
+ actions: {
30520
+ startPlaying: function() {
30521
+ // ...
30522
+
30523
+ if (actionShouldAlsoBeTriggeredOnParentRoute) {
30524
+ return true;
30525
+ }
30526
+ }
30527
+ }
30528
+ });
30529
+ ```
29635
30530
 
29636
30531
  ## Built-in actions
29637
30532
 
@@ -30099,12 +30994,48 @@ Ember.Route = Ember.Object.extend(Ember.ActionHandler, {
30099
30994
  if (!name && sawParams) { return params; }
30100
30995
  else if (!name) { return; }
30101
30996
 
30102
- var modelClass = this.container.lookupFactory('model:' + name).superclass;
30103
- var namespace = get(this, 'router.namespace');
30997
+ return this.findModel(name, value);
30998
+ },
30104
30999
 
30105
- return modelClass.find(value);
31000
+ /**
31001
+
31002
+ @method findModel
31003
+ @param {String} type the model type
31004
+ @param {Object} value the value passed to find
31005
+ */
31006
+ findModel: function(){
31007
+ var store = get(this, 'store');
31008
+ return store.find.apply(store, arguments);
30106
31009
  },
30107
31010
 
31011
+ /**
31012
+ Store property provides a hook for data persistence libraries to inject themselves.
31013
+
31014
+ By default, this store property provides the exact same functionality previously
31015
+ in the model hook.
31016
+
31017
+ Currently, the required interface is:
31018
+
31019
+ `store.find(modelName, findArguments)`
31020
+
31021
+ @method store
31022
+ @param {Object} store
31023
+ */
31024
+ store: Ember.computed(function(){
31025
+ var container = this.container;
31026
+ var routeName = this.routeName;
31027
+ var namespace = get(this, 'router.namespace');
31028
+
31029
+ return {
31030
+ find: function(name, value) {
31031
+ var modelClass = container.lookupFactory('model:' + name);
31032
+
31033
+
31034
+ return modelClass.find(value);
31035
+ }
31036
+ };
31037
+ }),
31038
+
30108
31039
  /**
30109
31040
  A hook you can implement to convert the route's model into parameters
30110
31041
  for the URL.
@@ -30127,8 +31058,10 @@ Ember.Route = Ember.Object.extend(Ember.ActionHandler, {
30127
31058
  });
30128
31059
  ```
30129
31060
 
30130
- The default `serialize` method inserts the model's `id` into the
30131
- route's dynamic segment (in this case, `:post_id`).
31061
+ The default `serialize` method will insert the model's `id` into the
31062
+ route's dynamic segment (in this case, `:post_id`) if the segment contains '_id'.
31063
+ If the route has multiple dynamic segments or does not contain '_id', `serialize`
31064
+ will return `Ember.getProperties(model, params)`
30132
31065
 
30133
31066
  This method is called when `transitionTo` is called with a context
30134
31067
  in order to populate the URL.
@@ -30411,13 +31344,18 @@ Ember.Route = Ember.Object.extend(Ember.ActionHandler, {
30411
31344
  name = this.routeName;
30412
31345
  }
30413
31346
 
31347
+ options = options || {};
30414
31348
  name = name ? name.replace(/\//g, '.') : this.routeName;
30415
- var viewName = this.viewName || name;
31349
+ var viewName = options.view || this.viewName || name;
30416
31350
  var templateName = this.templateName || name;
30417
31351
 
30418
31352
  var container = this.container,
30419
31353
  view = container.lookup('view:' + viewName),
30420
- template = container.lookup('template:' + templateName);
31354
+ template = view ? view.get('template') : null;
31355
+
31356
+ if (!template) {
31357
+ template = container.lookup('template:' + templateName);
31358
+ }
30421
31359
 
30422
31360
  if (!view && !template) {
30423
31361
 
@@ -30544,7 +31482,7 @@ function normalizeOptions(route, name, template, options) {
30544
31482
  } else if (namedController = route.container.lookup('controller:' + name)) {
30545
31483
  controller = namedController;
30546
31484
  } else {
30547
- controller = route.routeName;
31485
+ controller = route.controllerName || route.routeName;
30548
31486
  }
30549
31487
 
30550
31488
  if (typeof controller === 'string') {
@@ -30626,7 +31564,7 @@ Ember.onLoad('Ember.Handlebars', function() {
30626
31564
  handlebarsGet = Ember.Handlebars.get;
30627
31565
 
30628
31566
  function resolveParams(context, params, options) {
30629
- return resolvePaths(context, params, options).map(function(path, i) {
31567
+ return map.call(resolvePaths(context, params, options), function(path, i) {
30630
31568
  if (null === path) {
30631
31569
  // Param was string/number, not a path, so just return raw string/number.
30632
31570
  return params[i];
@@ -30873,7 +31811,7 @@ Ember.onLoad('Ember.Handlebars', function(Handlebars) {
30873
31811
  whenever the helpers
30874
31812
  */
30875
31813
  _paramsChanged: function() {
30876
- this.notifyPropertyChange('routeArgs');
31814
+ this.notifyPropertyChange('resolvedParams');
30877
31815
  },
30878
31816
 
30879
31817
  /**
@@ -30918,13 +31856,14 @@ Ember.onLoad('Ember.Handlebars', function(Handlebars) {
30918
31856
  var router = get(this, 'router'),
30919
31857
  routeArgs = get(this, 'routeArgs'),
30920
31858
  contexts = routeArgs.slice(1),
30921
- currentWhen = this.currentWhen || routeArgs[0],
31859
+ resolvedParams = get(this, 'resolvedParams'),
31860
+ currentWhen = this.currentWhen || resolvedParams[0],
30922
31861
  currentWithIndex = currentWhen + '.index',
30923
31862
  isActive = router.isActive.apply(router, [currentWhen].concat(contexts)) ||
30924
31863
  router.isActive.apply(router, [currentWithIndex].concat(contexts));
30925
31864
 
30926
31865
  if (isActive) { return get(this, 'activeClass'); }
30927
- }).property('routeArgs', 'router.url'),
31866
+ }).property('resolvedParams', 'routeArgs', 'router.url'),
30928
31867
 
30929
31868
  /**
30930
31869
  Accessed as a classname binding to apply the `LinkView`'s `loadingClass`
@@ -30983,6 +31922,23 @@ Ember.onLoad('Ember.Handlebars', function(Handlebars) {
30983
31922
  }
30984
31923
  },
30985
31924
 
31925
+ /**
31926
+ @private
31927
+
31928
+ Computed property that returns the resolved parameters.
31929
+
31930
+ @property
31931
+ @return {Array}
31932
+ */
31933
+ resolvedParams: Ember.computed(function() {
31934
+ var parameters = this.parameters,
31935
+ options = parameters.options,
31936
+ types = options.types,
31937
+ data = options.data;
31938
+
31939
+ return resolveParams(parameters.context, parameters.params, { types: types, data: data });
31940
+ }).property(),
31941
+
30986
31942
  /**
30987
31943
  @private
30988
31944
 
@@ -30994,11 +31950,7 @@ Ember.onLoad('Ember.Handlebars', function(Handlebars) {
30994
31950
  */
30995
31951
  routeArgs: Ember.computed(function() {
30996
31952
 
30997
- var parameters = this.parameters,
30998
- options = parameters.options,
30999
- types = options.types,
31000
- data = options.data,
31001
- resolvedParams = resolveParams(parameters.context, parameters.params, { types: types, data: data }),
31953
+ var resolvedParams = get(this, 'resolvedParams').slice(0),
31002
31954
  router = get(this, 'router'),
31003
31955
  namedRoute = resolvedParams[0];
31004
31956
 
@@ -31017,7 +31969,7 @@ Ember.onLoad('Ember.Handlebars', function(Handlebars) {
31017
31969
  }
31018
31970
 
31019
31971
  return resolvedParams;
31020
- }).property(),
31972
+ }).property('resolvedParams'),
31021
31973
 
31022
31974
  /**
31023
31975
  Sets the element's `href` attribute to the url for
@@ -32743,7 +33695,6 @@ Ember Routing
32743
33695
 
32744
33696
  @module ember
32745
33697
  @submodule ember-routing
32746
- @requires ember-states
32747
33698
  @requires ember-views
32748
33699
  */
32749
33700
 
@@ -33969,11 +34920,8 @@ Ember.runLoadHooks('Ember.Application', Ember.Application);
33969
34920
 
33970
34921
  var get = Ember.get, set = Ember.set;
33971
34922
 
33972
- function verifyDependencies(controller) {
33973
- var needs = get(controller, 'needs'),
33974
- container = get(controller, 'container'),
33975
- satisfied = true,
33976
- dependency, i, l;
34923
+ function verifyNeedsDependencies(controller, container, needs) {
34924
+ var dependency, i, l;
33977
34925
 
33978
34926
  for (i=0, l=needs.length; i<l; i++) {
33979
34927
  dependency = needs[i];
@@ -33981,26 +34929,11 @@ function verifyDependencies(controller) {
33981
34929
  dependency = "controller:" + dependency;
33982
34930
  }
33983
34931
 
34932
+ // Structure assert to still do verification but not string concat in production
33984
34933
  if (!container.has(dependency)) {
33985
- satisfied = false;
33986
34934
 
33987
34935
  }
33988
34936
  }
33989
-
33990
- if (l > 0) {
33991
- set(controller, 'controllers', {
33992
- unknownProperty: function(controllerName) {
33993
- var dependency, i, l;
33994
- for (i=0, l=needs.length; i<l; i++) {
33995
- dependency = needs[i];
33996
- if (dependency === controllerName) {
33997
- return container.lookup('controller:' + controllerName);
33998
- }
33999
- }
34000
- }
34001
- });
34002
- }
34003
- return satisfied;
34004
34937
  }
34005
34938
 
34006
34939
  /**
@@ -34039,12 +34972,17 @@ Ember.ControllerMixin.reopen({
34039
34972
  needs: [],
34040
34973
 
34041
34974
  init: function() {
34042
- this._super.apply(this, arguments);
34975
+ var needs = get(this, 'needs'),
34976
+ length = get(needs, 'length');
34043
34977
 
34044
- // Structure asserts to still do verification but not string concat in production
34045
- if (!verifyDependencies(this)) {
34978
+ if (length > 0) {
34979
+ verifyNeedsDependencies(this, this.container, needs);
34046
34980
 
34981
+ // if needs then initialize controllers proxy
34982
+ get(this, 'controllers');
34047
34983
  }
34984
+
34985
+ this._super.apply(this, arguments);
34048
34986
  },
34049
34987
 
34050
34988
  controllerFor: function(controllerName) {
@@ -34054,7 +34992,7 @@ Ember.ControllerMixin.reopen({
34054
34992
 
34055
34993
  /**
34056
34994
  Stores the instances of other controllers available from within
34057
- this controller. Any controller listed by name in the `needs`
34995
+ this controller. Any controller listed by name in the `needs`
34058
34996
  property will be accessible by name through this property.
34059
34997
 
34060
34998
  ```javascript
@@ -34066,398 +35004,32 @@ Ember.ControllerMixin.reopen({
34066
35004
  }.property('controllers.post.title')
34067
35005
  });
34068
35006
  ```
34069
-
35007
+
34070
35008
  @see {Ember.ControllerMixin#needs}
34071
35009
  @property {Object} controllers
34072
35010
  @default null
34073
35011
  */
34074
- controllers: null
34075
- });
34076
-
34077
- })();
34078
-
34079
-
34080
-
34081
- (function() {
34082
-
34083
- })();
34084
-
34085
-
34086
-
34087
- (function() {
34088
- /**
34089
- Ember Application
34090
-
34091
- @module ember
34092
- @submodule ember-application
34093
- @requires ember-views, ember-states, ember-routing
34094
- */
34095
-
34096
- })();
34097
-
34098
- (function() {
34099
- var get = Ember.get, set = Ember.set;
34100
-
34101
- /**
34102
- @module ember
34103
- @submodule ember-states
34104
- */
34105
-
34106
- /**
34107
- The State class allows you to define individual states within a finite state machine
34108
- inside your Ember application.
34109
-
34110
- ### How States Work
34111
-
34112
- When you setup a finite state machine this means you are setting up a mechanism to precisely
34113
- manage the change within a system. You can control the various states or modes that your
34114
- application can be in at any given time. Additionally, you can manage what specific states
34115
- are allowed to transition to other states.
34116
-
34117
- The state machine is in only one state at a time. This state is known as the current state.
34118
- It is possible to change from one state to another by a triggering event or condition.
34119
- This is called a transition.
34120
-
34121
- Finite state machines are important because they allow the application developer to be
34122
- deterministic about the the sequence of events that can happen within a system. Some states
34123
- cannot be entered when the application is a given state.
34124
-
34125
- For example:
34126
-
34127
- A door that is in the `locked` state cannot be `opened` (you must transition to the `unlocked`
34128
- state first).
34129
-
34130
- A door that is in the `open` state cannot be `locked` (you must transition to the `closed`
34131
- state first).
34132
-
34133
-
34134
- Each state instance has the following characteristics:
34135
-
34136
- - Zero or more parent states
34137
- - A start state
34138
- - A name
34139
- - A path (a computed value that prefixes parent states and the complete hierarchy to itself )
34140
-
34141
- A state is known as a "leafState" when it is the last item on the path and has no children
34142
- beneath it.
34143
-
34144
- The isLeaf property returns a boolean.
34145
-
34146
- Each state can emit the following transition events
34147
-
34148
- - setup
34149
- - enter
34150
- - exit
34151
-
34152
- A state object is ususally created in the context of a state manager.
34153
-
34154
- ```javascript
34155
- doorStateManager = Ember.StateManager.create({
34156
- locked: Ember.State.create(),
34157
- closed: Ember.State.create(),
34158
- unlocked: Ember.State.create(),
34159
- open: Ember.State.create()
34160
- });
34161
- ```
34162
-
34163
- @class State
34164
- @namespace Ember
34165
- @extends Ember.Object
34166
- @uses Ember.Evented
34167
- */
34168
- Ember.State = Ember.Object.extend(Ember.Evented,
34169
- /** @scope Ember.State.prototype */{
34170
- /**
34171
- A reference to the parent state.
34172
-
34173
- @property parentState
34174
- @type Ember.State
34175
- */
34176
- parentState: null,
34177
- start: null,
34178
-
34179
- /**
34180
- The name of this state.
34181
-
34182
- @property name
34183
- @type String
34184
- */
34185
- name: null,
34186
-
34187
- /**
34188
- The full path to this state.
34189
-
34190
- @property path
34191
- @type String
34192
- */
34193
- path: Ember.computed(function() {
34194
- var parentPath = get(this, 'parentState.path'),
34195
- path = get(this, 'name');
34196
-
34197
- if (parentPath) {
34198
- path = parentPath + '.' + path;
34199
- }
34200
-
34201
- return path;
34202
- }),
34203
-
34204
- /**
34205
- @private
34206
-
34207
- Override the default event firing from `Ember.Evented` to
34208
- also call methods with the given name.
34209
-
34210
- @method trigger
34211
- @param name
34212
- */
34213
- trigger: function(name) {
34214
- if (this[name]) {
34215
- this[name].apply(this, [].slice.call(arguments, 1));
34216
- }
34217
- this._super.apply(this, arguments);
34218
- },
34219
-
34220
- /**
34221
- Initialize Ember.State object
34222
- Sets childStates to Ember.NativeArray
34223
- Sets eventTransitions to empty object unless already defined.
34224
- Loops over properties of this state and ensures that any property that
34225
- is an instance of Ember.State is moved to `states` hash.
34226
-
34227
-
34228
- @method init
34229
- */
34230
- init: function() {
34231
- var states = get(this, 'states');
34232
- set(this, 'childStates', Ember.A());
34233
- set(this, 'eventTransitions', get(this, 'eventTransitions') || {});
34234
-
34235
- var name, value, transitionTarget;
35012
+ controllers: Ember.computed(function() {
35013
+ var controller = this;
34236
35014
 
34237
- // As a convenience, loop over the properties
34238
- // of this state and look for any that are other
34239
- // Ember.State instances or classes, and move them
34240
- // to the `states` hash. This avoids having to
34241
- // create an explicit separate hash.
34242
-
34243
- if (!states) {
34244
- states = {};
34245
-
34246
- for (name in this) {
34247
- if (name === "constructor") { continue; }
34248
-
34249
- if (value = this[name]) {
34250
- if (transitionTarget = value.transitionTarget) {
34251
- this.eventTransitions[name] = transitionTarget;
35015
+ return {
35016
+ needs: get(controller, 'needs'),
35017
+ container: get(controller, 'container'),
35018
+ unknownProperty: function(controllerName) {
35019
+ var needs = this.needs,
35020
+ dependency, i, l;
35021
+ for (i=0, l=needs.length; i<l; i++) {
35022
+ dependency = needs[i];
35023
+ if (dependency === controllerName) {
35024
+ return this.container.lookup('controller:' + controllerName);
34252
35025
  }
34253
-
34254
- this.setupChild(states, name, value);
34255
35026
  }
34256
- }
34257
35027
 
34258
- set(this, 'states', states);
34259
- } else {
34260
- for (name in states) {
34261
- this.setupChild(states, name, states[name]);
35028
+ var errorMessage = Ember.inspect(controller) + '#needs does not include `' + controllerName + '`. To access the ' + controllerName + ' controller from ' + Ember.inspect(controller) + ', ' + Ember.inspect(controller) + ' should have a `needs` property that is an array of the controllers it has access to.';
35029
+ throw new ReferenceError(errorMessage);
34262
35030
  }
34263
- }
34264
-
34265
- // pathsCaches is a nested hash of the form:
34266
- // pathsCaches[stateManagerTypeGuid][path] == transitions_hash
34267
- set(this, 'pathsCaches', {});
34268
- },
34269
-
34270
- /**
34271
- Sets a cached instance of the state. Ember.guidFor is used
34272
- to find the guid of the associated state manager. If a cache can be found
34273
- the state path is added to that cache, otherwise an empty JavaScript object
34274
- is created. And the state path is appended to that instead.
34275
-
34276
- @method setPathsCache
34277
- @param stateManager
34278
- @param path
34279
- @param transitions
34280
- */
34281
- setPathsCache: function(stateManager, path, transitions) {
34282
- var stateManagerTypeGuid = Ember.guidFor(stateManager.constructor),
34283
- pathsCaches = get(this, 'pathsCaches'),
34284
- pathsCacheForManager = pathsCaches[stateManagerTypeGuid] || {};
34285
-
34286
- pathsCacheForManager[path] = transitions;
34287
- pathsCaches[stateManagerTypeGuid] = pathsCacheForManager;
34288
- },
34289
-
34290
- /**
34291
- Returns a cached path for the state instance. Each state manager
34292
- has a GUID and this is used to look up a cached path if it has already
34293
- been created. If a cached path is not found an empty JavaScript object
34294
- is returned instead.
34295
-
34296
- @method getPathsCache
34297
- @param stateManager
34298
- @param path
34299
- */
34300
- getPathsCache: function(stateManager, path) {
34301
- var stateManagerTypeGuid = Ember.guidFor(stateManager.constructor),
34302
- pathsCaches = get(this, 'pathsCaches'),
34303
- pathsCacheForManager = pathsCaches[stateManagerTypeGuid] || {};
34304
-
34305
- return pathsCacheForManager[path];
34306
- },
34307
-
34308
- /**
34309
- @private
34310
-
34311
- Create the child instance and ensure that it is an instance of Ember.State
34312
-
34313
- @method setupChild
34314
- @param states
34315
- @param name
34316
- @param value
34317
- */
34318
- setupChild: function(states, name, value) {
34319
- if (!value) { return false; }
34320
- var instance;
34321
-
34322
- if (value instanceof Ember.State) {
34323
- set(value, 'name', name);
34324
- instance = value;
34325
- instance.container = this.container;
34326
- } else if (Ember.State.detect(value)) {
34327
- instance = value.create({
34328
- name: name,
34329
- container: this.container
34330
- });
34331
- }
34332
-
34333
- if (instance instanceof Ember.State) {
34334
- set(instance, 'parentState', this);
34335
- get(this, 'childStates').pushObject(instance);
34336
- states[name] = instance;
34337
- return instance;
34338
- }
34339
- },
34340
-
34341
- /**
34342
- @private
34343
-
34344
- @method lookupEventTransition
34345
- @param name
34346
- */
34347
- lookupEventTransition: function(name) {
34348
- var path, state = this;
34349
-
34350
- while(state && !path) {
34351
- path = state.eventTransitions[name];
34352
- state = state.get('parentState');
34353
- }
34354
-
34355
- return path;
34356
- },
34357
-
34358
- /**
34359
- A Boolean value indicating whether the state is a leaf state
34360
- in the state hierarchy. This is `false` if the state has child
34361
- states; otherwise it is true.
34362
-
34363
- @property isLeaf
34364
- @type Boolean
34365
- */
34366
- isLeaf: Ember.computed(function() {
34367
- return !get(this, 'childStates').length;
34368
- }),
34369
-
34370
- /**
34371
- A boolean value indicating whether the state takes a context.
34372
- By default we assume all states take contexts.
34373
-
34374
- @property hasContext
34375
- @default true
34376
- */
34377
- hasContext: true,
34378
-
34379
- /**
34380
- This is the default transition event.
34381
-
34382
- @event setup
34383
- @param {Ember.StateManager} manager
34384
- @param context
34385
- @see Ember.StateManager#transitionEvent
34386
- */
34387
- setup: Ember.K,
34388
-
34389
- /**
34390
- This event fires when the state is entered.
34391
-
34392
- @event enter
34393
- @param {Ember.StateManager} manager
34394
- */
34395
- enter: Ember.K,
34396
-
34397
- /**
34398
- This event fires when the state is exited.
34399
-
34400
- @event exit
34401
- @param {Ember.StateManager} manager
34402
- */
34403
- exit: Ember.K
34404
- });
34405
-
34406
- Ember.State.reopenClass({
34407
-
34408
- /**
34409
- Creates an action function for transitioning to the named state while
34410
- preserving context.
34411
-
34412
- The following example StateManagers are equivalent:
34413
-
34414
- ```javascript
34415
- aManager = Ember.StateManager.create({
34416
- stateOne: Ember.State.create({
34417
- changeToStateTwo: Ember.State.transitionTo('stateTwo')
34418
- }),
34419
- stateTwo: Ember.State.create({})
34420
- })
34421
-
34422
- bManager = Ember.StateManager.create({
34423
- stateOne: Ember.State.create({
34424
- changeToStateTwo: function(manager, context) {
34425
- manager.transitionTo('stateTwo', context)
34426
- }
34427
- }),
34428
- stateTwo: Ember.State.create({})
34429
- })
34430
- ```
34431
-
34432
- @method transitionTo
34433
- @static
34434
- @param {String} target
34435
- */
34436
-
34437
- transitionTo: function(target) {
34438
-
34439
- var transitionFunction = function(stateManager, contextOrEvent) {
34440
- var contexts = [],
34441
- Event = Ember.$ && Ember.$.Event;
34442
-
34443
- if (contextOrEvent && (Event && contextOrEvent instanceof Event)) {
34444
- if (contextOrEvent.hasOwnProperty('contexts')) {
34445
- contexts = contextOrEvent.contexts.slice();
34446
- }
34447
- }
34448
- else {
34449
- contexts = [].slice.call(arguments, 1);
34450
- }
34451
-
34452
- contexts.unshift(target);
34453
- stateManager.transitionTo.apply(stateManager, contexts);
34454
35031
  };
34455
-
34456
- transitionFunction.transitionTarget = target;
34457
-
34458
- return transitionFunction;
34459
- }
34460
-
35032
+ }).readOnly()
34461
35033
  });
34462
35034
 
34463
35035
  })();
@@ -34465,1103 +35037,6 @@ Ember.State.reopenClass({
34465
35037
 
34466
35038
 
34467
35039
  (function() {
34468
- /**
34469
- @module ember
34470
- @submodule ember-states
34471
- */
34472
-
34473
- var get = Ember.get, set = Ember.set, fmt = Ember.String.fmt;
34474
- var arrayForEach = Ember.ArrayPolyfills.forEach;
34475
- /**
34476
- A Transition takes the enter, exit and resolve states and normalizes
34477
- them:
34478
-
34479
- * takes any passed in contexts into consideration
34480
- * adds in `initialState`s
34481
-
34482
- @class Transition
34483
- @private
34484
- */
34485
- var Transition = function(raw) {
34486
- this.enterStates = raw.enterStates.slice();
34487
- this.exitStates = raw.exitStates.slice();
34488
- this.resolveState = raw.resolveState;
34489
-
34490
- this.finalState = raw.enterStates[raw.enterStates.length - 1] || raw.resolveState;
34491
- };
34492
-
34493
- Transition.prototype = {
34494
- /**
34495
- Normalize the passed in enter, exit and resolve states.
34496
-
34497
- This process also adds `finalState` and `contexts` to the Transition object.
34498
-
34499
- @method normalize
34500
- @param {Ember.StateManager} manager the state manager running the transition
34501
- @param {Array} contexts a list of contexts passed into `transitionTo`
34502
- */
34503
- normalize: function(manager, contexts) {
34504
- this.matchContextsToStates(contexts);
34505
- this.addInitialStates();
34506
- this.removeUnchangedContexts(manager);
34507
- return this;
34508
- },
34509
-
34510
- /**
34511
- Match each of the contexts passed to `transitionTo` to a state.
34512
- This process may also require adding additional enter and exit
34513
- states if there are more contexts than enter states.
34514
-
34515
- @method matchContextsToStates
34516
- @param {Array} contexts a list of contexts passed into `transitionTo`
34517
- */
34518
- matchContextsToStates: function(contexts) {
34519
- var stateIdx = this.enterStates.length - 1,
34520
- matchedContexts = [],
34521
- state,
34522
- context;
34523
-
34524
- // Next, we will match the passed in contexts to the states they
34525
- // represent.
34526
- //
34527
- // First, assign a context to each enter state in reverse order. If
34528
- // any contexts are left, add a parent state to the list of states
34529
- // to enter and exit, and assign a context to the parent state.
34530
- //
34531
- // If there are still contexts left when the state manager is
34532
- // reached, raise an exception.
34533
- //
34534
- // This allows the following:
34535
- //
34536
- // |- root
34537
- // | |- post
34538
- // | | |- comments
34539
- // | |- about (* current state)
34540
- //
34541
- // For `transitionTo('post.comments', post, post.get('comments')`,
34542
- // the first context (`post`) will be assigned to `root.post`, and
34543
- // the second context (`post.get('comments')`) will be assigned
34544
- // to `root.post.comments`.
34545
- //
34546
- // For the following:
34547
- //
34548
- // |- root
34549
- // | |- post
34550
- // | | |- index (* current state)
34551
- // | | |- comments
34552
- //
34553
- // For `transitionTo('post.comments', otherPost, otherPost.get('comments')`,
34554
- // the `<root.post>` state will be added to the list of enter and exit
34555
- // states because its context has changed.
34556
-
34557
- while (contexts.length > 0) {
34558
- if (stateIdx >= 0) {
34559
- state = this.enterStates[stateIdx--];
34560
- } else {
34561
- if (this.enterStates.length) {
34562
- state = get(this.enterStates[0], 'parentState');
34563
- if (!state) { throw "Cannot match all contexts to states"; }
34564
- } else {
34565
- // If re-entering the current state with a context, the resolve
34566
- // state will be the current state.
34567
- state = this.resolveState;
34568
- }
34569
-
34570
- this.enterStates.unshift(state);
34571
- this.exitStates.unshift(state);
34572
- }
34573
-
34574
- // in routers, only states with dynamic segments have a context
34575
- if (get(state, 'hasContext')) {
34576
- context = contexts.pop();
34577
- } else {
34578
- context = null;
34579
- }
34580
-
34581
- matchedContexts.unshift(context);
34582
- }
34583
-
34584
- this.contexts = matchedContexts;
34585
- },
34586
-
34587
- /**
34588
- Add any `initialState`s to the list of enter states.
34589
-
34590
- @method addInitialStates
34591
- */
34592
- addInitialStates: function() {
34593
- var finalState = this.finalState, initialState;
34594
-
34595
- while(true) {
34596
- initialState = get(finalState, 'initialState') || 'start';
34597
- finalState = get(finalState, 'states.' + initialState);
34598
-
34599
- if (!finalState) { break; }
34600
-
34601
- this.finalState = finalState;
34602
- this.enterStates.push(finalState);
34603
- this.contexts.push(undefined);
34604
- }
34605
- },
34606
-
34607
- /**
34608
- Remove any states that were added because the number of contexts
34609
- exceeded the number of explicit enter states, but the context has
34610
- not changed since the last time the state was entered.
34611
-
34612
- @method removeUnchangedContexts
34613
- @param {Ember.StateManager} manager passed in to look up the last
34614
- context for a state
34615
- */
34616
- removeUnchangedContexts: function(manager) {
34617
- // Start from the beginning of the enter states. If the state was added
34618
- // to the list during the context matching phase, make sure the context
34619
- // has actually changed since the last time the state was entered.
34620
- while (this.enterStates.length > 0) {
34621
- if (this.enterStates[0] !== this.exitStates[0]) { break; }
34622
-
34623
- if (this.enterStates.length === this.contexts.length) {
34624
- if (manager.getStateMeta(this.enterStates[0], 'context') !== this.contexts[0]) { break; }
34625
- this.contexts.shift();
34626
- }
34627
-
34628
- this.resolveState = this.enterStates.shift();
34629
- this.exitStates.shift();
34630
- }
34631
- }
34632
- };
34633
-
34634
-
34635
- /**
34636
- Sends the event to the currentState, if the event is not handled this method
34637
- will proceed to call the parentState recursively until it encounters an
34638
- event handler or reaches the top or root of the state path hierarchy.
34639
-
34640
- @method sendRecursively
34641
- @param event
34642
- @param currentState
34643
- @param isUnhandledPass
34644
- */
34645
- var sendRecursively = function(event, currentState, isUnhandledPass) {
34646
- var log = this.enableLogging,
34647
- eventName = isUnhandledPass ? 'unhandledEvent' : event,
34648
- action = currentState[eventName],
34649
- contexts, sendRecursiveArguments, actionArguments;
34650
-
34651
- contexts = [].slice.call(arguments, 3);
34652
-
34653
- // Test to see if the action is a method that
34654
- // can be invoked. Don't blindly check just for
34655
- // existence, because it is possible the state
34656
- // manager has a child state of the given name,
34657
- // and we should still raise an exception in that
34658
- // case.
34659
- if (typeof action === 'function') {
34660
- if (log) {
34661
- if (isUnhandledPass) {
34662
- Ember.Logger.log(fmt("STATEMANAGER: Unhandled event '%@' being sent to state %@.", [event, get(currentState, 'path')]));
34663
- } else {
34664
- Ember.Logger.log(fmt("STATEMANAGER: Sending event '%@' to state %@.", [event, get(currentState, 'path')]));
34665
- }
34666
- }
34667
-
34668
- actionArguments = contexts;
34669
- if (isUnhandledPass) {
34670
- actionArguments.unshift(event);
34671
- }
34672
- actionArguments.unshift(this);
34673
-
34674
- return action.apply(currentState, actionArguments);
34675
- } else {
34676
- var parentState = get(currentState, 'parentState');
34677
- if (parentState) {
34678
-
34679
- sendRecursiveArguments = contexts;
34680
- sendRecursiveArguments.unshift(event, parentState, isUnhandledPass);
34681
-
34682
- return sendRecursively.apply(this, sendRecursiveArguments);
34683
- } else if (!isUnhandledPass) {
34684
- return sendEvent.call(this, event, contexts, true);
34685
- }
34686
- }
34687
- };
34688
-
34689
- /**
34690
- Send an event to the currentState.
34691
-
34692
- @method sendEvent
34693
- @param eventName
34694
- @param sendRecursiveArguments
34695
- @param isUnhandledPass
34696
- */
34697
- var sendEvent = function(eventName, sendRecursiveArguments, isUnhandledPass) {
34698
- sendRecursiveArguments.unshift(eventName, get(this, 'currentState'), isUnhandledPass);
34699
- return sendRecursively.apply(this, sendRecursiveArguments);
34700
- };
34701
-
34702
- /**
34703
- StateManager is part of Ember's implementation of a finite state machine. A
34704
- StateManager instance manages a number of properties that are instances of
34705
- `Ember.State`,
34706
- tracks the current active state, and triggers callbacks when states have changed.
34707
-
34708
- ## Defining States
34709
-
34710
- The states of StateManager can be declared in one of two ways. First, you can
34711
- define a `states` property that contains all the states:
34712
-
34713
- ```javascript
34714
- var managerA = Ember.StateManager.create({
34715
- states: {
34716
- stateOne: Ember.State.create(),
34717
- stateTwo: Ember.State.create()
34718
- }
34719
- });
34720
-
34721
- managerA.get('states');
34722
- // {
34723
- // stateOne: Ember.State.create(),
34724
- // stateTwo: Ember.State.create()
34725
- // }
34726
- ```
34727
-
34728
- You can also add instances of `Ember.State` (or an `Ember.State` subclass)
34729
- directly as properties of a StateManager. These states will be collected into
34730
- the `states` property for you.
34731
-
34732
- ```javascript
34733
- var managerA = Ember.StateManager.create({
34734
- stateOne: Ember.State.create(),
34735
- stateTwo: Ember.State.create()
34736
- });
34737
-
34738
- managerA.get('states');
34739
- // {
34740
- // stateOne: Ember.State.create(),
34741
- // stateTwo: Ember.State.create()
34742
- // }
34743
- ```
34744
-
34745
- ## The Initial State
34746
-
34747
- When created, a StateManager instance will immediately enter into the state
34748
- defined as its `start` property or the state referenced by name in its
34749
- `initialState` property:
34750
-
34751
- ```javascript
34752
- var managerA = Ember.StateManager.create({
34753
- start: Ember.State.create({})
34754
- });
34755
-
34756
- managerA.get('currentState.name'); // 'start'
34757
-
34758
- var managerB = Ember.StateManager.create({
34759
- initialState: 'beginHere',
34760
- beginHere: Ember.State.create({})
34761
- });
34762
-
34763
- managerB.get('currentState.name'); // 'beginHere'
34764
- ```
34765
-
34766
- Because it is a property you may also provide a computed function if you wish
34767
- to derive an `initialState` programmatically:
34768
-
34769
- ```javascript
34770
- var managerC = Ember.StateManager.create({
34771
- initialState: function() {
34772
- if (someLogic) {
34773
- return 'active';
34774
- } else {
34775
- return 'passive';
34776
- }
34777
- }.property(),
34778
- active: Ember.State.create({}),
34779
- passive: Ember.State.create({})
34780
- });
34781
- ```
34782
-
34783
- ## Moving Between States
34784
-
34785
- A StateManager can have any number of `Ember.State` objects as properties
34786
- and can have a single one of these states as its current state.
34787
-
34788
- Calling `transitionTo` transitions between states:
34789
-
34790
- ```javascript
34791
- var robotManager = Ember.StateManager.create({
34792
- initialState: 'poweredDown',
34793
- poweredDown: Ember.State.create({}),
34794
- poweredUp: Ember.State.create({})
34795
- });
34796
-
34797
- robotManager.get('currentState.name'); // 'poweredDown'
34798
- robotManager.transitionTo('poweredUp');
34799
- robotManager.get('currentState.name'); // 'poweredUp'
34800
- ```
34801
-
34802
- Before transitioning into a new state the existing `currentState` will have
34803
- its `exit` method called with the StateManager instance as its first argument
34804
- and an object representing the transition as its second argument.
34805
-
34806
- After transitioning into a new state the new `currentState` will have its
34807
- `enter` method called with the StateManager instance as its first argument
34808
- and an object representing the transition as its second argument.
34809
-
34810
- ```javascript
34811
- var robotManager = Ember.StateManager.create({
34812
- initialState: 'poweredDown',
34813
- poweredDown: Ember.State.create({
34814
- exit: function(stateManager) {
34815
- console.log("exiting the poweredDown state")
34816
- }
34817
- }),
34818
- poweredUp: Ember.State.create({
34819
- enter: function(stateManager) {
34820
- console.log("entering the poweredUp state. Destroy all humans.")
34821
- }
34822
- })
34823
- });
34824
-
34825
- robotManager.get('currentState.name'); // 'poweredDown'
34826
- robotManager.transitionTo('poweredUp');
34827
-
34828
- // will log
34829
- // 'exiting the poweredDown state'
34830
- // 'entering the poweredUp state. Destroy all humans.'
34831
- ```
34832
-
34833
- Once a StateManager is already in a state, subsequent attempts to enter that
34834
- state will not trigger enter or exit method calls. Attempts to transition
34835
- into a state that the manager does not have will result in no changes in the
34836
- StateManager's current state:
34837
-
34838
- ```javascript
34839
- var robotManager = Ember.StateManager.create({
34840
- initialState: 'poweredDown',
34841
- poweredDown: Ember.State.create({
34842
- exit: function(stateManager) {
34843
- console.log("exiting the poweredDown state")
34844
- }
34845
- }),
34846
- poweredUp: Ember.State.create({
34847
- enter: function(stateManager) {
34848
- console.log("entering the poweredUp state. Destroy all humans.")
34849
- }
34850
- })
34851
- });
34852
-
34853
- robotManager.get('currentState.name'); // 'poweredDown'
34854
- robotManager.transitionTo('poweredUp');
34855
- // will log
34856
- // 'exiting the poweredDown state'
34857
- // 'entering the poweredUp state. Destroy all humans.'
34858
- robotManager.transitionTo('poweredUp'); // no logging, no state change
34859
-
34860
- robotManager.transitionTo('someUnknownState'); // silently fails
34861
- robotManager.get('currentState.name'); // 'poweredUp'
34862
- ```
34863
-
34864
- Each state property may itself contain properties that are instances of
34865
- `Ember.State`. The StateManager can transition to specific sub-states in a
34866
- series of transitionTo method calls or via a single transitionTo with the
34867
- full path to the specific state. The StateManager will also keep track of the
34868
- full path to its currentState
34869
-
34870
- ```javascript
34871
- var robotManager = Ember.StateManager.create({
34872
- initialState: 'poweredDown',
34873
- poweredDown: Ember.State.create({
34874
- charging: Ember.State.create(),
34875
- charged: Ember.State.create()
34876
- }),
34877
- poweredUp: Ember.State.create({
34878
- mobile: Ember.State.create(),
34879
- stationary: Ember.State.create()
34880
- })
34881
- });
34882
-
34883
- robotManager.get('currentState.name'); // 'poweredDown'
34884
-
34885
- robotManager.transitionTo('poweredUp');
34886
- robotManager.get('currentState.name'); // 'poweredUp'
34887
-
34888
- robotManager.transitionTo('mobile');
34889
- robotManager.get('currentState.name'); // 'mobile'
34890
-
34891
- // transition via a state path
34892
- robotManager.transitionTo('poweredDown.charging');
34893
- robotManager.get('currentState.name'); // 'charging'
34894
-
34895
- robotManager.get('currentState.path'); // 'poweredDown.charging'
34896
- ```
34897
-
34898
- Enter transition methods will be called for each state and nested child state
34899
- in their hierarchical order. Exit methods will be called for each state and
34900
- its nested states in reverse hierarchical order.
34901
-
34902
- Exit transitions for a parent state are not called when entering into one of
34903
- its child states, only when transitioning to a new section of possible states
34904
- in the hierarchy.
34905
-
34906
- ```javascript
34907
- var robotManager = Ember.StateManager.create({
34908
- initialState: 'poweredDown',
34909
- poweredDown: Ember.State.create({
34910
- enter: function() {},
34911
- exit: function() {
34912
- console.log("exited poweredDown state")
34913
- },
34914
- charging: Ember.State.create({
34915
- enter: function() {},
34916
- exit: function() {}
34917
- }),
34918
- charged: Ember.State.create({
34919
- enter: function() {
34920
- console.log("entered charged state")
34921
- },
34922
- exit: function() {
34923
- console.log("exited charged state")
34924
- }
34925
- })
34926
- }),
34927
- poweredUp: Ember.State.create({
34928
- enter: function() {
34929
- console.log("entered poweredUp state")
34930
- },
34931
- exit: function() {},
34932
- mobile: Ember.State.create({
34933
- enter: function() {
34934
- console.log("entered mobile state")
34935
- },
34936
- exit: function() {}
34937
- }),
34938
- stationary: Ember.State.create({
34939
- enter: function() {},
34940
- exit: function() {}
34941
- })
34942
- })
34943
- });
34944
-
34945
-
34946
- robotManager.get('currentState.path'); // 'poweredDown'
34947
- robotManager.transitionTo('charged');
34948
- // logs 'entered charged state'
34949
- // but does *not* log 'exited poweredDown state'
34950
- robotManager.get('currentState.name'); // 'charged
34951
-
34952
- robotManager.transitionTo('poweredUp.mobile');
34953
- // logs
34954
- // 'exited charged state'
34955
- // 'exited poweredDown state'
34956
- // 'entered poweredUp state'
34957
- // 'entered mobile state'
34958
- ```
34959
-
34960
- During development you can set a StateManager's `enableLogging` property to
34961
- `true` to receive console messages of state transitions.
34962
-
34963
- ```javascript
34964
- var robotManager = Ember.StateManager.create({
34965
- enableLogging: true
34966
- });
34967
- ```
34968
-
34969
- ## Managing currentState with Actions
34970
-
34971
- To control which transitions are possible for a given state, and
34972
- appropriately handle external events, the StateManager can receive and
34973
- route action messages to its states via the `send` method. Calling to
34974
- `send` with an action name will begin searching for a method with the same
34975
- name starting at the current state and moving up through the parent states
34976
- in a state hierarchy until an appropriate method is found or the StateManager
34977
- instance itself is reached.
34978
-
34979
- If an appropriately named method is found it will be called with the state
34980
- manager as the first argument and an optional `context` object as the second
34981
- argument.
34982
-
34983
- ```javascript
34984
- var managerA = Ember.StateManager.create({
34985
- initialState: 'stateOne.substateOne.subsubstateOne',
34986
- stateOne: Ember.State.create({
34987
- substateOne: Ember.State.create({
34988
- anAction: function(manager, context) {
34989
- console.log("an action was called")
34990
- },
34991
- subsubstateOne: Ember.State.create({})
34992
- })
34993
- })
34994
- });
34995
-
34996
- managerA.get('currentState.name'); // 'subsubstateOne'
34997
- managerA.send('anAction');
34998
- // 'stateOne.substateOne.subsubstateOne' has no anAction method
34999
- // so the 'anAction' method of 'stateOne.substateOne' is called
35000
- // and logs "an action was called"
35001
- // with managerA as the first argument
35002
- // and no second argument
35003
-
35004
- var someObject = {};
35005
- managerA.send('anAction', someObject);
35006
- // the 'anAction' method of 'stateOne.substateOne' is called again
35007
- // with managerA as the first argument and
35008
- // someObject as the second argument.
35009
- ```
35010
-
35011
- If the StateManager attempts to send an action but does not find an appropriately named
35012
- method in the current state or while moving upwards through the state hierarchy, it will
35013
- repeat the process looking for a `unhandledEvent` method. If an `unhandledEvent` method is
35014
- found, it will be called with the original event name as the second argument. If an
35015
- `unhandledEvent` method is not found, the StateManager will throw a new Ember.Error.
35016
-
35017
- ```javascript
35018
- var managerB = Ember.StateManager.create({
35019
- initialState: 'stateOne.substateOne.subsubstateOne',
35020
- stateOne: Ember.State.create({
35021
- substateOne: Ember.State.create({
35022
- subsubstateOne: Ember.State.create({}),
35023
- unhandledEvent: function(manager, eventName, context) {
35024
- console.log("got an unhandledEvent with name " + eventName);
35025
- }
35026
- })
35027
- })
35028
- });
35029
-
35030
- managerB.get('currentState.name'); // 'subsubstateOne'
35031
- managerB.send('anAction');
35032
- // neither `stateOne.substateOne.subsubstateOne` nor any of it's
35033
- // parent states have a handler for `anAction`. `subsubstateOne`
35034
- // also does not have a `unhandledEvent` method, but its parent
35035
- // state, `substateOne`, does, and it gets fired. It will log
35036
- // "got an unhandledEvent with name anAction"
35037
- ```
35038
-
35039
- Action detection only moves upwards through the state hierarchy from the current state.
35040
- It does not search in other portions of the hierarchy.
35041
-
35042
- ```javascript
35043
- var managerC = Ember.StateManager.create({
35044
- initialState: 'stateOne.substateOne.subsubstateOne',
35045
- stateOne: Ember.State.create({
35046
- substateOne: Ember.State.create({
35047
- subsubstateOne: Ember.State.create({})
35048
- })
35049
- }),
35050
- stateTwo: Ember.State.create({
35051
- anAction: function(manager, context) {
35052
- // will not be called below because it is
35053
- // not a parent of the current state
35054
- }
35055
- })
35056
- });
35057
-
35058
- managerC.get('currentState.name'); // 'subsubstateOne'
35059
- managerC.send('anAction');
35060
- // Error: <Ember.StateManager:ember132> could not
35061
- // respond to event anAction in state stateOne.substateOne.subsubstateOne.
35062
- ```
35063
-
35064
- Inside of an action method the given state should delegate `transitionTo` calls on its
35065
- StateManager.
35066
-
35067
- ```javascript
35068
- var robotManager = Ember.StateManager.create({
35069
- initialState: 'poweredDown.charging',
35070
- poweredDown: Ember.State.create({
35071
- charging: Ember.State.create({
35072
- chargeComplete: function(manager, context) {
35073
- manager.transitionTo('charged')
35074
- }
35075
- }),
35076
- charged: Ember.State.create({
35077
- boot: function(manager, context) {
35078
- manager.transitionTo('poweredUp')
35079
- }
35080
- })
35081
- }),
35082
- poweredUp: Ember.State.create({
35083
- beginExtermination: function(manager, context) {
35084
- manager.transitionTo('rampaging')
35085
- },
35086
- rampaging: Ember.State.create()
35087
- })
35088
- });
35089
-
35090
- robotManager.get('currentState.name'); // 'charging'
35091
- robotManager.send('boot'); // throws error, no boot action
35092
- // in current hierarchy
35093
- robotManager.get('currentState.name'); // remains 'charging'
35094
-
35095
- robotManager.send('beginExtermination'); // throws error, no beginExtermination
35096
- // action in current hierarchy
35097
- robotManager.get('currentState.name'); // remains 'charging'
35098
-
35099
- robotManager.send('chargeComplete');
35100
- robotManager.get('currentState.name'); // 'charged'
35101
-
35102
- robotManager.send('boot');
35103
- robotManager.get('currentState.name'); // 'poweredUp'
35104
-
35105
- robotManager.send('beginExtermination', allHumans);
35106
- robotManager.get('currentState.name'); // 'rampaging'
35107
- ```
35108
-
35109
- Transition actions can also be created using the `transitionTo` method of the `Ember.State` class. The
35110
- following example StateManagers are equivalent:
35111
-
35112
- ```javascript
35113
- var aManager = Ember.StateManager.create({
35114
- stateOne: Ember.State.create({
35115
- changeToStateTwo: Ember.State.transitionTo('stateTwo')
35116
- }),
35117
- stateTwo: Ember.State.create({})
35118
- });
35119
-
35120
- var bManager = Ember.StateManager.create({
35121
- stateOne: Ember.State.create({
35122
- changeToStateTwo: function(manager, context) {
35123
- manager.transitionTo('stateTwo', context)
35124
- }
35125
- }),
35126
- stateTwo: Ember.State.create({})
35127
- });
35128
- ```
35129
-
35130
- @class StateManager
35131
- @namespace Ember
35132
- @extends Ember.State
35133
- **/
35134
- Ember.StateManager = Ember.State.extend({
35135
- /**
35136
- @private
35137
-
35138
- When creating a new statemanager, look for a default state to transition
35139
- into. This state can either be named `start`, or can be specified using the
35140
- `initialState` property.
35141
-
35142
- @method init
35143
- */
35144
- init: function() {
35145
- this._super();
35146
-
35147
- set(this, 'stateMeta', Ember.Map.create());
35148
-
35149
- var initialState = get(this, 'initialState');
35150
-
35151
- if (!initialState && get(this, 'states.start')) {
35152
- initialState = 'start';
35153
- }
35154
-
35155
- if (initialState) {
35156
- this.transitionTo(initialState);
35157
-
35158
- }
35159
- },
35160
-
35161
- /**
35162
- Return the stateMeta, a hash of possible states. If no items exist in the stateMeta hash
35163
- this method sets the stateMeta to an empty JavaScript object and returns that instead.
35164
-
35165
- @method stateMetaFor
35166
- @param state
35167
- */
35168
- stateMetaFor: function(state) {
35169
- var meta = get(this, 'stateMeta'),
35170
- stateMeta = meta.get(state);
35171
-
35172
- if (!stateMeta) {
35173
- stateMeta = {};
35174
- meta.set(state, stateMeta);
35175
- }
35176
-
35177
- return stateMeta;
35178
- },
35179
-
35180
- /**
35181
- Sets a key value pair on the stateMeta hash.
35182
-
35183
- @method setStateMeta
35184
- @param state
35185
- @param key
35186
- @param value
35187
- */
35188
- setStateMeta: function(state, key, value) {
35189
- return set(this.stateMetaFor(state), key, value);
35190
- },
35191
-
35192
- /**
35193
- Returns the value of an item in the stateMeta hash at the given key.
35194
-
35195
- @method getStateMeta
35196
- @param state
35197
- @param key
35198
- */
35199
- getStateMeta: function(state, key) {
35200
- return get(this.stateMetaFor(state), key);
35201
- },
35202
-
35203
- /**
35204
- The current state from among the manager's possible states. This property should
35205
- not be set directly. Use `transitionTo` to move between states by name.
35206
-
35207
- @property currentState
35208
- @type Ember.State
35209
- */
35210
- currentState: null,
35211
-
35212
- /**
35213
- The path of the current state. Returns a string representation of the current
35214
- state.
35215
-
35216
- @property currentPath
35217
- @type String
35218
- */
35219
- currentPath: Ember.computed.alias('currentState.path'),
35220
-
35221
- /**
35222
- The name of transitionEvent that this stateManager will dispatch
35223
-
35224
- @property transitionEvent
35225
- @type String
35226
- @default 'setup'
35227
- */
35228
- transitionEvent: 'setup',
35229
-
35230
- /**
35231
- If set to true, `errorOnUnhandledEvents` will cause an exception to be
35232
- raised if you attempt to send an event to a state manager that is not
35233
- handled by the current state or any of its parent states.
35234
-
35235
- @property errorOnUnhandledEvents
35236
- @type Boolean
35237
- @default true
35238
- */
35239
- errorOnUnhandledEvent: true,
35240
-
35241
- /**
35242
- An alias to sendEvent method
35243
-
35244
- @method send
35245
- @param event
35246
- */
35247
- send: function(event) {
35248
- var contexts = [].slice.call(arguments, 1);
35249
-
35250
- return sendEvent.call(this, event, contexts, false);
35251
- },
35252
-
35253
- /**
35254
- If errorOnUnhandledEvent is true this event with throw an Ember.Error
35255
- indicating that the no state could respond to the event passed through the
35256
- state machine.
35257
-
35258
- @method unhandledEvent
35259
- @param manager
35260
- @param event
35261
- */
35262
- unhandledEvent: function(manager, event) {
35263
- if (get(this, 'errorOnUnhandledEvent')) {
35264
- throw new Ember.Error(this.toString() + " could not respond to event " + event + " in state " + get(this, 'currentState.path') + ".");
35265
- }
35266
- },
35267
-
35268
- /**
35269
- Finds a state by its state path.
35270
-
35271
- Example:
35272
-
35273
- ```javascript
35274
- var manager = Ember.StateManager.create({
35275
- root: Ember.State.create({
35276
- dashboard: Ember.State.create()
35277
- })
35278
- });
35279
-
35280
- manager.getStateByPath(manager, "root.dashboard");
35281
- // returns the dashboard state
35282
-
35283
- var aState = manager.getStateByPath(manager, "root.dashboard");
35284
-
35285
- var path = aState.get('path');
35286
- // path is 'root.dashboard'
35287
-
35288
- var name = aState.get('name');
35289
- // name is 'dashboard'
35290
- ```
35291
-
35292
- @method getStateByPath
35293
- @param {Ember.State} root the state to start searching from
35294
- @param {String} path the state path to follow
35295
- @return {Ember.State} the state at the end of the path
35296
- */
35297
- getStateByPath: function(root, path) {
35298
- var parts = path.split('.'),
35299
- state = root;
35300
-
35301
- for (var i=0, len=parts.length; i<len; i++) {
35302
- state = get(get(state, 'states'), parts[i]);
35303
- if (!state) { break; }
35304
- }
35305
-
35306
- return state;
35307
- },
35308
-
35309
- findStateByPath: function(state, path) {
35310
- var possible;
35311
-
35312
- while (!possible && state) {
35313
- possible = this.getStateByPath(state, path);
35314
- state = get(state, 'parentState');
35315
- }
35316
-
35317
- return possible;
35318
- },
35319
-
35320
- /**
35321
- A state stores its child states in its `states` hash.
35322
- This code takes a path like `posts.show` and looks
35323
- up `root.states.posts.states.show`.
35324
-
35325
- It returns a list of all of the states from the
35326
- root, which is the list of states to call `enter`
35327
- on.
35328
-
35329
- @method getStatesInPath
35330
- @param root
35331
- @param path
35332
- */
35333
- getStatesInPath: function(root, path) {
35334
- if (!path || path === "") { return undefined; }
35335
- var parts = path.split('.'),
35336
- result = [],
35337
- states,
35338
- state;
35339
-
35340
- for (var i=0, len=parts.length; i<len; i++) {
35341
- states = get(root, 'states');
35342
- if (!states) { return undefined; }
35343
- state = get(states, parts[i]);
35344
- if (state) { root = state; result.push(state); }
35345
- else { return undefined; }
35346
- }
35347
-
35348
- return result;
35349
- },
35350
-
35351
- /**
35352
- Alias for transitionTo.
35353
- This method applies a transitionTo to the arguments passed into this method.
35354
-
35355
- @method goToState
35356
- */
35357
- goToState: function() {
35358
- // not deprecating this yet so people don't constantly need to
35359
- // make trivial changes for little reason.
35360
- return this.transitionTo.apply(this, arguments);
35361
- },
35362
-
35363
- /**
35364
- Transition to another state within the state machine. If the path is empty returns
35365
- immediately. This method attempts to get a hash of the enter, exit and resolve states
35366
- from the existing state cache. Processes the raw state information based on the
35367
- passed in context. Creates a new transition object and triggers a new setupContext.
35368
-
35369
- @method transitionTo
35370
- @param path
35371
- @param context
35372
- */
35373
- transitionTo: function(path, context) {
35374
- // XXX When is transitionTo called with no path
35375
- if (Ember.isEmpty(path)) { return; }
35376
-
35377
- // The ES6 signature of this function is `path, ...contexts`
35378
- var contexts = context ? Array.prototype.slice.call(arguments, 1) : [],
35379
- currentState = get(this, 'currentState') || this;
35380
-
35381
- // First, get the enter, exit and resolve states for the current state
35382
- // and specified path. If possible, use an existing cache.
35383
- var hash = this.contextFreeTransition(currentState, path);
35384
-
35385
- // Next, process the raw state information for the contexts passed in.
35386
- var transition = new Transition(hash).normalize(this, contexts);
35387
-
35388
- this.enterState(transition);
35389
- this.triggerSetupContext(transition);
35390
- },
35391
-
35392
- /**
35393
- Allows you to transition to any other state in the state manager without
35394
- being constrained by the state hierarchy of the current state path.
35395
- This method will traverse the state path upwards through its parents until
35396
- it finds the specified state path. All the transitions are captured during the
35397
- traversal.
35398
-
35399
- Caches and returns hash of transitions, which contain the exitSates, enterStates and
35400
- resolvedState
35401
-
35402
- @method contextFreeTransition
35403
- @param currentState
35404
- @param path
35405
- */
35406
- contextFreeTransition: function(currentState, path) {
35407
- var cache = currentState.getPathsCache(this, path);
35408
- if (cache) { return cache; }
35409
-
35410
- var enterStates = this.getStatesInPath(currentState, path),
35411
- exitStates = [],
35412
- resolveState = currentState;
35413
-
35414
- // Walk up the states. For each state, check whether a state matching
35415
- // the `path` is nested underneath. This will find the closest
35416
- // parent state containing `path`.
35417
- //
35418
- // This allows the user to pass in a relative path. For example, for
35419
- // the following state hierarchy:
35420
- //
35421
- // | |root
35422
- // | |- posts
35423
- // | | |- show (* current)
35424
- // | |- comments
35425
- // | | |- show
35426
- //
35427
- // If the current state is `<root.posts.show>`, an attempt to
35428
- // transition to `comments.show` will match `<root.comments.show>`.
35429
- //
35430
- // First, this code will look for root.posts.show.comments.show.
35431
- // Next, it will look for root.posts.comments.show. Finally,
35432
- // it will look for `root.comments.show`, and find the state.
35433
- //
35434
- // After this process, the following variables will exist:
35435
- //
35436
- // * resolveState: a common parent state between the current
35437
- // and target state. In the above example, `<root>` is the
35438
- // `resolveState`.
35439
- // * enterStates: a list of all of the states represented
35440
- // by the path from the `resolveState`. For example, for
35441
- // the path `root.comments.show`, `enterStates` would have
35442
- // `[<root.comments>, <root.comments.show>]`
35443
- // * exitStates: a list of all of the states from the
35444
- // `resolveState` to the `currentState`. In the above
35445
- // example, `exitStates` would have
35446
- // `[<root.posts>`, `<root.posts.show>]`.
35447
- while (resolveState && !enterStates) {
35448
- exitStates.unshift(resolveState);
35449
-
35450
- resolveState = get(resolveState, 'parentState');
35451
- if (!resolveState) {
35452
- enterStates = this.getStatesInPath(this, path);
35453
- if (!enterStates) {
35454
-
35455
- return;
35456
- }
35457
- }
35458
- enterStates = this.getStatesInPath(resolveState, path);
35459
- }
35460
-
35461
- // If the path contains some states that are parents of both the
35462
- // current state and the target state, remove them.
35463
- //
35464
- // For example, in the following hierarchy:
35465
- //
35466
- // |- root
35467
- // | |- post
35468
- // | | |- index (* current)
35469
- // | | |- show
35470
- //
35471
- // If the `path` is `root.post.show`, the three variables will
35472
- // be:
35473
- //
35474
- // * resolveState: `<state manager>`
35475
- // * enterStates: `[<root>, <root.post>, <root.post.show>]`
35476
- // * exitStates: `[<root>, <root.post>, <root.post.index>]`
35477
- //
35478
- // The goal of this code is to remove the common states, so we
35479
- // have:
35480
- //
35481
- // * resolveState: `<root.post>`
35482
- // * enterStates: `[<root.post.show>]`
35483
- // * exitStates: `[<root.post.index>]`
35484
- //
35485
- // This avoid unnecessary calls to the enter and exit transitions.
35486
- while (enterStates.length > 0 && enterStates[0] === exitStates[0]) {
35487
- resolveState = enterStates.shift();
35488
- exitStates.shift();
35489
- }
35490
-
35491
- // Cache the enterStates, exitStates, and resolveState for the
35492
- // current state and the `path`.
35493
- var transitions = {
35494
- exitStates: exitStates,
35495
- enterStates: enterStates,
35496
- resolveState: resolveState
35497
- };
35498
-
35499
- currentState.setPathsCache(this, path, transitions);
35500
-
35501
- return transitions;
35502
- },
35503
-
35504
- /**
35505
- A trigger to setup the state contexts. Each state is setup with
35506
- an enterState.
35507
-
35508
- @method triggerSetupContext
35509
- @param transitions
35510
- */
35511
- triggerSetupContext: function(transitions) {
35512
- var contexts = transitions.contexts,
35513
- offset = transitions.enterStates.length - contexts.length,
35514
- enterStates = transitions.enterStates,
35515
- transitionEvent = get(this, 'transitionEvent');
35516
-
35517
-
35518
- arrayForEach.call(enterStates, function(state, idx) {
35519
- state.trigger(transitionEvent, this, contexts[idx-offset]);
35520
- }, this);
35521
- },
35522
-
35523
- /**
35524
- Returns the state instance by name. If state is not found the parentState
35525
- is returned instead.
35526
-
35527
- @method getState
35528
- @param name
35529
- */
35530
- getState: function(name) {
35531
- var state = get(this, name),
35532
- parentState = get(this, 'parentState');
35533
-
35534
- if (state) {
35535
- return state;
35536
- } else if (parentState) {
35537
- return parentState.getState(name);
35538
- }
35539
- },
35540
-
35541
- /**
35542
- Causes a transition from the exitState of one state to the enterState of another
35543
- state in the state machine. At the end of the transition the currentState is set
35544
- to the finalState of the transition passed into this method.
35545
-
35546
- @method enterState
35547
- @param transition
35548
- */
35549
- enterState: function(transition) {
35550
- var log = this.enableLogging;
35551
-
35552
- var exitStates = transition.exitStates.slice(0).reverse();
35553
- arrayForEach.call(exitStates, function(state) {
35554
- state.trigger('exit', this);
35555
- }, this);
35556
-
35557
- arrayForEach.call(transition.enterStates, function(state) {
35558
- if (log) { Ember.Logger.log("STATEMANAGER: Entering " + get(state, 'path')); }
35559
- state.trigger('enter', this);
35560
- }, this);
35561
-
35562
- set(this, 'currentState', transition.finalState);
35563
- }
35564
- });
35565
35040
 
35566
35041
  })();
35567
35042
 
@@ -35569,11 +35044,11 @@ Ember.StateManager = Ember.State.extend({
35569
35044
 
35570
35045
  (function() {
35571
35046
  /**
35572
- Ember States
35047
+ Ember Application
35573
35048
 
35574
35049
  @module ember
35575
- @submodule ember-states
35576
- @requires ember-runtime
35050
+ @submodule ember-application
35051
+ @requires ember-views, ember-routing
35577
35052
  */
35578
35053
 
35579
35054
  })();