ember-source 1.0.0.rc8 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ember-source might be problematic. Click here for more details.

@@ -1,7 +1,7 @@
1
1
  (function() {
2
2
  var Ember = { assert: function() {} };
3
- // Version: v1.0.0-rc.7-148-g694beed
4
- // Last commit: 694beed (2013-08-26 17:12:34 -0400)
3
+ // Version: v1.0.0
4
+ // Last commit: e2ea0cf (2013-08-31 23:47:39 -0700)
5
5
 
6
6
 
7
7
  (function() {
@@ -158,6 +158,18 @@ Ember.deprecateFunc = function(message, func) {
158
158
  };
159
159
  };
160
160
 
161
+
162
+ // Inform the developer about the Ember Inspector if not installed.
163
+ if (!Ember.testing) {
164
+ if (typeof window !== 'undefined' && window.chrome && window.addEventListener) {
165
+ window.addEventListener("load", function() {
166
+ if (document.body && document.body.dataset && !document.body.dataset.emberExtension) {
167
+ Ember.debug('For more advanced debugging, install the Ember Inspector from https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi');
168
+ }
169
+ }, false);
170
+ }
171
+ }
172
+
161
173
  })();
162
174
 
163
175
 
@@ -1,5 +1,5 @@
1
- // Version: v1.0.0-rc.7-148-g694beed
2
- // Last commit: 694beed (2013-08-26 17:12:34 -0400)
1
+ // Version: v1.0.0
2
+ // Last commit: e2ea0cf (2013-08-31 23:47:39 -0700)
3
3
 
4
4
 
5
5
  (function() {
@@ -156,10 +156,22 @@ Ember.deprecateFunc = function(message, func) {
156
156
  };
157
157
  };
158
158
 
159
+
160
+ // Inform the developer about the Ember Inspector if not installed.
161
+ if (!Ember.testing) {
162
+ if (typeof window !== 'undefined' && window.chrome && window.addEventListener) {
163
+ window.addEventListener("load", function() {
164
+ if (document.body && document.body.dataset && !document.body.dataset.emberExtension) {
165
+ Ember.debug('For more advanced debugging, install the Ember Inspector from https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi');
166
+ }
167
+ }, false);
168
+ }
169
+ }
170
+
159
171
  })();
160
172
 
161
- // Version: v1.0.0-rc.8-3-gf0c90f8
162
- // Last commit: f0c90f8 (2013-08-29 00:12:09 -0700)
173
+ // Version: v1.0.0
174
+ // Last commit: e2ea0cf (2013-08-31 23:47:39 -0700)
163
175
 
164
176
 
165
177
  (function() {
@@ -225,7 +237,7 @@ var define, requireModule;
225
237
 
226
238
  @class Ember
227
239
  @static
228
- @version 1.0.0-rc.8
240
+ @version 1.0.0
229
241
  */
230
242
 
231
243
  if ('undefined' === typeof Ember) {
@@ -252,10 +264,10 @@ Ember.toString = function() { return "Ember"; };
252
264
  /**
253
265
  @property VERSION
254
266
  @type String
255
- @default '1.0.0-rc.8'
267
+ @default '1.0.0'
256
268
  @final
257
269
  */
258
- Ember.VERSION = '1.0.0-rc.8';
270
+ Ember.VERSION = '1.0.0';
259
271
 
260
272
  /**
261
273
  Standard environmental variables. You can define these in a global `ENV`
@@ -4601,8 +4613,8 @@ function registerComputedWithProperties(name, macro) {
4601
4613
  property is null, an empty string, empty array, or empty function.
4602
4614
 
4603
4615
  Note: When using `Ember.computed.empty` to watch an array make sure to
4604
- use the `array.length` or `array.@each` syntax so the computed can
4605
- subscribe to transitions from empty to non-empty states.
4616
+ use the `array.length` syntax so the computed can subscribe to transitions
4617
+ from empty to non-empty states.
4606
4618
 
4607
4619
  Example
4608
4620
 
@@ -4610,9 +4622,9 @@ function registerComputedWithProperties(name, macro) {
4610
4622
  var ToDoList = Ember.Object.extend({
4611
4623
  done: Ember.computed.empty('todos.length')
4612
4624
  });
4613
- var todoList = ToDoList.create({todoList: ['Unit Test', 'Documentation', 'Release']});
4625
+ var todoList = ToDoList.create({todos: ['Unit Test', 'Documentation', 'Release']});
4614
4626
  todoList.get('done'); // false
4615
- todoList.get('todoList').clear(); // []
4627
+ todoList.get('todos').clear(); // []
4616
4628
  todoList.get('done'); // true
4617
4629
  ```
4618
4630
 
@@ -5714,7 +5726,7 @@ define("backburner",
5714
5726
  clearTimeout(debouncee[2]);
5715
5727
  }
5716
5728
 
5717
- var timer = window.setTimeout(function() {
5729
+ var timer = global.setTimeout(function() {
5718
5730
  if (!immediate) {
5719
5731
  self.run.apply(self, args);
5720
5732
  }
@@ -5783,8 +5795,8 @@ define("backburner",
5783
5795
  function createAutorun(backburner) {
5784
5796
  backburner.begin();
5785
5797
  autorun = global.setTimeout(function() {
5786
- backburner.end();
5787
5798
  autorun = null;
5799
+ backburner.end();
5788
5800
  });
5789
5801
  }
5790
5802
 
@@ -7225,19 +7237,19 @@ Ember.mixin = function(obj) {
7225
7237
  `Ember.Mixin.extend`.
7226
7238
 
7227
7239
  Note that mixins extend a constructor's prototype so arrays and object literals
7228
- defined as properties will be shared amongst objects that implement the mixin.
7240
+ defined as properties will be shared amongst objects that implement the mixin.
7229
7241
  If you want to define an property in a mixin that is not shared, you can define
7230
7242
  it either as a computed property or have it be created on initialization of the object.
7231
-
7243
+
7232
7244
  ```javascript
7233
7245
  //filters array will be shared amongst any object implementing mixin
7234
7246
  App.Filterable = Ember.Mixin.create({
7235
- filters: Ember.A()
7247
+ filters: Ember.A()
7236
7248
  });
7237
7249
 
7238
7250
  //filters will be a separate array for every object implementing the mixin
7239
7251
  App.Filterable = Ember.Mixin.create({
7240
- filters: Ember.computed(function(){return Ember.A();})
7252
+ filters: Ember.computed(function(){return Ember.A();})
7241
7253
  });
7242
7254
 
7243
7255
  //filters will be created as a separate array during the object's initialization
@@ -7484,6 +7496,22 @@ Ember.aliasMethod = function(methodName) {
7484
7496
  //
7485
7497
 
7486
7498
  /**
7499
+ Specify a method that observes property changes.
7500
+
7501
+ ```javascript
7502
+ Ember.Object.extend({
7503
+ valueObserver: Ember.observer(function() {
7504
+ // Executes whenever the "value" property changes
7505
+ }, 'value')
7506
+ });
7507
+ ```
7508
+
7509
+ In the future this method may become asynchronous. If you want to ensure
7510
+ synchronous behavior, use `immediateObserver`.
7511
+
7512
+ Also available as `Function.prototype.observes` if prototype extensions are
7513
+ enabled.
7514
+
7487
7515
  @method observer
7488
7516
  @for Ember
7489
7517
  @param {Function} func
@@ -7496,9 +7524,23 @@ Ember.observer = function(func) {
7496
7524
  return func;
7497
7525
  };
7498
7526
 
7499
- // If observers ever become asynchronous, Ember.immediateObserver
7500
- // must remain synchronous.
7501
7527
  /**
7528
+ Specify a method that observes property changes.
7529
+
7530
+ ```javascript
7531
+ Ember.Object.extend({
7532
+ valueObserver: Ember.immediateObserver(function() {
7533
+ // Executes whenever the "value" property changes
7534
+ }, 'value')
7535
+ });
7536
+ ```
7537
+
7538
+ In the future, `Ember.observer` may become asynchronous. In this event,
7539
+ `Ember.immediateObserver` will maintain the synchronous behavior.
7540
+
7541
+ Also available as `Function.prototype.observesImmediately` if prototype extensions are
7542
+ enabled.
7543
+
7502
7544
  @method immediateObserver
7503
7545
  @for Ember
7504
7546
  @param {Function} func
@@ -7526,24 +7568,31 @@ Ember.immediateObserver = function() {
7526
7568
 
7527
7569
  ```javascript
7528
7570
  App.PersonView = Ember.View.extend({
7571
+
7529
7572
  friends: [{ name: 'Tom' }, { name: 'Stefan' }, { name: 'Kris' }],
7530
- valueWillChange: function (obj, keyName) {
7573
+
7574
+ valueWillChange: Ember.beforeObserver(function(obj, keyName) {
7531
7575
  this.changingFrom = obj.get(keyName);
7532
- }.observesBefore('content.value'),
7533
- valueDidChange: function(obj, keyName) {
7576
+ }, 'content.value'),
7577
+
7578
+ valueDidChange: Ember.observer(function(obj, keyName) {
7534
7579
  // only run if updating a value already in the DOM
7535
7580
  if (this.get('state') === 'inDOM') {
7536
- var color = obj.get(keyName) > this.changingFrom ? 'green' : 'red';
7537
- // logic
7581
+ var color = obj.get(keyName) > this.changingFrom ? 'green' : 'red';
7582
+ // logic
7538
7583
  }
7539
- }.observes('content.value'),
7540
- friendsDidChange: function(obj, keyName) {
7584
+ }, 'content.value'),
7585
+
7586
+ friendsDidChange: Ember.observer(function(obj, keyName) {
7541
7587
  // some logic
7542
7588
  // obj.get(keyName) returns friends array
7543
- }.observes('friends.@each.name')
7589
+ }, 'friends.@each.name')
7544
7590
  });
7545
7591
  ```
7546
7592
 
7593
+ Also available as `Function.prototype.observesBefore` if prototype extensions are
7594
+ enabled.
7595
+
7547
7596
  @method beforeObserver
7548
7597
  @for Ember
7549
7598
  @param {Function} func
@@ -7627,6 +7676,7 @@ define("rsvp/async",
7627
7676
  var browserGlobal = (typeof window !== 'undefined') ? window : {};
7628
7677
  var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
7629
7678
  var async;
7679
+ var local = (typeof global !== 'undefined') ? global : this;
7630
7680
 
7631
7681
  // old node
7632
7682
  function useNextTick() {
@@ -7677,7 +7727,7 @@ define("rsvp/async",
7677
7727
 
7678
7728
  function useSetTimeout() {
7679
7729
  return function(callback, arg) {
7680
- global.setTimeout(function() {
7730
+ local.setTimeout(function() {
7681
7731
  callback(arg);
7682
7732
  }, 1);
7683
7733
  };
@@ -8216,6 +8266,13 @@ define("rsvp",
8216
8266
  })();
8217
8267
 
8218
8268
  (function() {
8269
+ /**
8270
+ Flag to enable/disable model factory injections (disabled by default)
8271
+ If model factory injections are enabled, models should not be
8272
+ accessed globally (only through `container.lookupFactory('model:modelName'))`);
8273
+ */
8274
+ Ember.MODEL_FACTORY_INJECTIONS = false || !!Ember.ENV.MODEL_FACTORY_INJECTIONS;
8275
+
8219
8276
  define("container",
8220
8277
  [],
8221
8278
  function() {
@@ -8494,6 +8551,7 @@ define("container",
8494
8551
 
8495
8552
  container.unregister('model:user')
8496
8553
  container.lookup('model:user') === undefined //=> true
8554
+ ```
8497
8555
 
8498
8556
  @method unregister
8499
8557
  @param {String} fullName
@@ -8577,7 +8635,7 @@ define("container",
8577
8635
  */
8578
8636
  makeToString: function(factory, fullName) {
8579
8637
  return factory.toString();
8580
- },
8638
+ },
8581
8639
 
8582
8640
  /**
8583
8641
  Given a fullName return a corresponding instance.
@@ -8985,6 +9043,7 @@ define("container",
8985
9043
  var factory = container.resolve(name);
8986
9044
  var injectedFactory;
8987
9045
  var cache = container.factoryCache;
9046
+ var type = fullName.split(":")[0];
8988
9047
 
8989
9048
  if (!factory) { return; }
8990
9049
 
@@ -8992,7 +9051,7 @@ define("container",
8992
9051
  return cache.get(fullName);
8993
9052
  }
8994
9053
 
8995
- if (typeof factory.extend !== 'function') {
9054
+ if (typeof factory.extend !== 'function' || (!Ember.MODEL_FACTORY_INJECTIONS && type === 'model')) {
8996
9055
  // TODO: think about a 'safe' merge style extension
8997
9056
  // for now just fallback to create time injection
8998
9057
  return factory;
@@ -10796,6 +10855,9 @@ Ember.Array = Ember.Mixin.create(Ember.Enumerable, /** @scope Ember.Array.protot
10796
10855
  return an enumerable that maps automatically to the named key on the
10797
10856
  member objects.
10798
10857
 
10858
+ If you merely want to watch for any items being added or removed to the array,
10859
+ use the `[]` property instead of `@each`.
10860
+
10799
10861
  @property @each
10800
10862
  */
10801
10863
  '@each': Ember.computed(function() {
@@ -10827,7 +10889,7 @@ var get = Ember.get,
10827
10889
  eachPropertyPattern = /^(.*)\.@each\.(.*)/,
10828
10890
  doubleEachPropertyPattern = /(.*\.@each){2,}/;
10829
10891
 
10830
- /**
10892
+ /*
10831
10893
  Tracks changes to dependent arrays, as well as to properties of items in
10832
10894
  dependent arrays.
10833
10895
 
@@ -11016,22 +11078,29 @@ DependentArraysObserver.prototype = {
11016
11078
  guid = guidFor(dependentArray),
11017
11079
  dependentKey = this.dependentKeysByGuid[guid],
11018
11080
  itemPropertyKeys = this.cp._itemPropertyKeys[dependentKey] || [],
11081
+ item,
11019
11082
  itemIndex,
11083
+ sliceIndex,
11020
11084
  observerContexts;
11021
11085
 
11022
11086
  observerContexts = this.removeTransformation(dependentKey, index, removedCount);
11023
- forEach(dependentArray.slice(index, index + removedCount), function (item, sliceIndex) {
11087
+
11088
+
11089
+ function removeObservers(propertyKey) {
11090
+ removeBeforeObserver(item, propertyKey, this, observerContexts[sliceIndex].beforeObserver);
11091
+ removeObserver(item, propertyKey, this, observerContexts[sliceIndex].observer);
11092
+ }
11093
+
11094
+ for (sliceIndex = removedCount - 1; sliceIndex >= 0; --sliceIndex) {
11024
11095
  itemIndex = index + sliceIndex;
11096
+ item = dependentArray.objectAt(itemIndex);
11025
11097
 
11026
- forEach(itemPropertyKeys, function (propertyKey) {
11027
- removeBeforeObserver(item, propertyKey, this, observerContexts[sliceIndex].beforeObserver);
11028
- removeObserver(item, propertyKey, this, observerContexts[sliceIndex].observer);
11029
- }, this);
11098
+ forEach(itemPropertyKeys, removeObservers, this);
11030
11099
 
11031
11100
  changeMeta = createChangeMeta(dependentArray, item, itemIndex, this.instanceMeta.propertyName, this.cp);
11032
11101
  this.setValue( removedItem.call(
11033
11102
  this.instanceMeta.context, this.getValue(), item, changeMeta, this.instanceMeta.sugarMeta));
11034
- }, this);
11103
+ }
11035
11104
  },
11036
11105
 
11037
11106
  dependentArrayDidChange: function (dependentArray, index, removedCount, addedCount) {
@@ -11045,8 +11114,8 @@ DependentArraysObserver.prototype = {
11045
11114
 
11046
11115
  forEach(dependentArray.slice(index, index + addedCount), function (item, sliceIndex) {
11047
11116
  if (itemPropertyKeys) {
11048
- observerContext =
11049
- observerContexts[sliceIndex] =
11117
+ observerContext =
11118
+ observerContexts[sliceIndex] =
11050
11119
  this.createPropertyObserverContext(dependentArray, index + sliceIndex, this.trackedArraysByGuid[dependentKey]);
11051
11120
  forEach(itemPropertyKeys, function (propertyKey) {
11052
11121
  addBeforeObserver(item, propertyKey, this, observerContext.beforeObserver);
@@ -11063,30 +11132,29 @@ DependentArraysObserver.prototype = {
11063
11132
  },
11064
11133
 
11065
11134
  itemPropertyWillChange: function (obj, keyName, array, index) {
11066
- var changeId = guidFor(obj)+":"+keyName;
11135
+ var guid = guidFor(obj);
11067
11136
 
11068
- if (!this.changedItems[changeId]) {
11069
- this.changedItems[changeId] = {
11070
- array: array,
11137
+ if (!this.changedItems[guid]) {
11138
+ this.changedItems[guid] = {
11139
+ array: array,
11071
11140
  index: index,
11072
11141
  obj: obj,
11073
- keyChanged: keyName,
11074
- previousValue: get(obj, keyName)
11142
+ previousValues: {}
11075
11143
  };
11076
11144
  }
11145
+
11146
+ this.changedItems[guid].previousValues[keyName] = get(obj, keyName);
11077
11147
  },
11078
11148
 
11079
11149
  itemPropertyDidChange: function(obj, keyName, array, index) {
11080
11150
  Ember.run.once(this, 'flushChanges');
11081
11151
  },
11082
11152
 
11083
- // TODO: it probably makes more sense to remove the item during `willChange`
11084
- // and add it back (with the new value) during `didChange`
11085
11153
  flushChanges: function() {
11086
11154
  var changedItems = this.changedItems, key, c, changeMeta;
11087
11155
  for (key in changedItems) {
11088
11156
  c = changedItems[key];
11089
- changeMeta = createChangeMeta(c.array, c.obj, c.index, this.instanceMeta.propertyName, this.cp, c.keyChanged, c.previousValue);
11157
+ changeMeta = createChangeMeta(c.array, c.obj, c.index, this.instanceMeta.propertyName, this.cp, c.previousValues);
11090
11158
  this.setValue(
11091
11159
  this.callbacks.removedItem.call(this.instanceMeta.context, this.getValue(), c.obj, changeMeta, this.instanceMeta.sugarMeta));
11092
11160
  this.setValue(
@@ -11096,18 +11164,19 @@ DependentArraysObserver.prototype = {
11096
11164
  }
11097
11165
  };
11098
11166
 
11099
- function createChangeMeta(dependentArray, item, index, propertyName, property, key, previousValue) {
11167
+ function createChangeMeta(dependentArray, item, index, propertyName, property, previousValues) {
11100
11168
  var meta = {
11101
11169
  arrayChanged: dependentArray,
11102
11170
  index: index,
11103
11171
  item: item,
11104
11172
  propertyName: propertyName,
11105
- property: property,
11106
- // previous value is only available for item property changes!
11107
- previousValue: previousValue
11173
+ property: property
11108
11174
  };
11109
11175
 
11110
- if (key) { meta.keyChanged = key; }
11176
+ if (previousValues) {
11177
+ // previous values only available for item property changes
11178
+ meta.previousValues = previousValues;
11179
+ }
11111
11180
 
11112
11181
  return meta;
11113
11182
  }
@@ -11231,7 +11300,9 @@ function ReduceComputedProperty(options) {
11231
11300
 
11232
11301
  forEach(cp._dependentKeys, function(dependentKey) {
11233
11302
  var dependentArray = get(this, dependentKey);
11234
- addItems.call(this, dependentArray, callbacks, cp, propertyName, meta);
11303
+ if (dependentArray) {
11304
+ addItems.call(this, dependentArray, callbacks, cp, propertyName, meta);
11305
+ }
11235
11306
  }, this);
11236
11307
  };
11237
11308
 
@@ -11333,7 +11404,122 @@ ReduceComputedProperty.prototype.property = function () {
11333
11404
  return ComputedProperty.prototype.property.apply(this, propertyArgs);
11334
11405
  };
11335
11406
 
11407
+ /**
11408
+ Creates a computed property which operates on dependent arrays and
11409
+ is updated with "one at a time" semantics. When items are added or
11410
+ removed from the dependent array(s) a reduce computed only operates
11411
+ on the change instead of re-evaluating the entire array.
11412
+
11413
+ If there are more than one arguments the first arguments are
11414
+ considered to be dependent property keys. The last argument is
11415
+ required to be an options object. The options object can have the
11416
+ following four properties.
11417
+
11418
+ `initialValue` - A value or function that will be used as the initial
11419
+ value for the computed. If this property is a function the result of calling
11420
+ the function will be used as the initial value. This property is required.
11421
+
11422
+ `initialize` - An optional initialize function. Typically this will be used
11423
+ to set up state on the instanceMeta object.
11424
+
11425
+ `removedItem` - A function that is called each time an element is removed
11426
+ from the array.
11427
+
11428
+ `addedItem` - A function that is called each time an element is added to
11429
+ the array.
11430
+
11431
+
11432
+ The `initialize` function has the following signature:
11433
+
11434
+ ```javascript
11435
+ function (initialValue, changeMeta, instanceMeta)
11436
+ ```
11437
+
11438
+ `initialValue` - The value of the `initialValue` property from the
11439
+ options object.
11440
+
11441
+ `changeMeta` - An object which contains meta information about the
11442
+ computed. It contains the following properties:
11443
+
11444
+ - `property` the computed property
11445
+ - `propertyName` the name of the property on the object
11446
+
11447
+ `instanceMeta` - An object that can be used to store meta
11448
+ information needed for calculating your computed. For example a
11449
+ unique computed might use this to store the number of times a given
11450
+ element is found in the dependent array.
11451
+
11452
+
11453
+ The `removedItem` and `addedItem` functions both have the following signature:
11454
+
11455
+ ```javascript
11456
+ function (accumulatedValue, item, changeMeta, instanceMeta)
11457
+ ```
11458
+
11459
+ `accumulatedValue` - The value returned from the last time
11460
+ `removedItem` or `addedItem` was called or `initialValue`.
11461
+
11462
+ `item` - the element added or removed from the array
11463
+
11464
+ `changeMeta` - An object which contains meta information about the
11465
+ change. It contains the following properties:
11466
+
11467
+ - `property` the computed property
11468
+ - `propertyName` the name of the property on the object
11469
+ - `index` the index of the added or removed item
11470
+ - `item` the added or removed item: this is exactly the same as
11471
+ the second arg
11472
+ - `arrayChanged` the array that triggered the change. Can be
11473
+ useful when depending on multiple arrays.
11336
11474
 
11475
+ For property changes triggered on an item property change (when
11476
+ depKey is something like `someArray.@each.someProperty`),
11477
+ `changeMeta` will also contain the following property:
11478
+
11479
+ - `previousValues` an object whose keys are the properties that changed on
11480
+ the item, and whose values are the item's previous values.
11481
+
11482
+ `previousValues` is important Ember coalesces item property changes via
11483
+ Ember.run.once. This means that by the time removedItem gets called, item has
11484
+ the new values, but you may need the previous value (eg for sorting &
11485
+ filtering).
11486
+
11487
+ `instanceMeta` - An object that can be used to store meta
11488
+ information needed for calculating your computed. For example a
11489
+ unique computed might use this to store the number of times a given
11490
+ element is found in the dependent array.
11491
+
11492
+ The `removedItem` and `addedItem` functions should return the accumulated
11493
+ value. It is acceptable to not return anything (ie return undefined)
11494
+ to invalidate the computation. This is generally not a good idea for
11495
+ arrayComputed but it's used in eg max and min.
11496
+
11497
+ Example
11498
+
11499
+ ```javascript
11500
+ Ember.computed.max = function (dependentKey) {
11501
+ return Ember.reduceComputed.call(null, dependentKey, {
11502
+ initialValue: -Infinity,
11503
+
11504
+ addedItem: function (accumulatedValue, item, changeMeta, instanceMeta) {
11505
+ return Math.max(accumulatedValue, item);
11506
+ },
11507
+
11508
+ removedItem: function (accumulatedValue, item, changeMeta, instanceMeta) {
11509
+ if (item < accumulatedValue) {
11510
+ return accumulatedValue;
11511
+ }
11512
+ }
11513
+ });
11514
+ };
11515
+ ```
11516
+
11517
+ @method reduceComputed
11518
+ @for Ember
11519
+ @param {String} [dependentKeys*]
11520
+ @param {Object} options
11521
+ @returns {Ember.ComputedProperty}
11522
+ */
11337
11523
  Ember.reduceComputed = function (options) {
11338
11524
  var args;
11339
11525
 
@@ -11359,7 +11545,6 @@ Ember.reduceComputed = function (options) {
11359
11545
  return cp;
11360
11546
  };
11361
11547
 
11362
-
11363
11548
  })();
11364
11549
 
11365
11550
 
@@ -11404,7 +11589,120 @@ ArrayComputedProperty.prototype.resetValue = function (array) {
11404
11589
  return array;
11405
11590
  };
11406
11591
 
11592
+ /**
11593
+ Creates a computed property which operates on dependent arrays and
11594
+ is updated with "one at a time" semantics. When items are added or
11595
+ removed from the dependent array(s) an array computed only operates
11596
+ on the change instead of re-evaluating the entire array. This should
11597
+ return an array, if you'd like to use "one at a time" semantics and
11598
+ compute some value other then an array look at
11599
+ `Ember.reduceComputed`.
11600
+
11601
+ If there are more than one arguments the first arguments are
11602
+ considered to be dependent property keys. The last argument is
11603
+ required to be an options object. The options object can have the
11604
+ following three properties.
11605
+
11606
+ `initialize` - An optional initialize function. Typically this will be used
11607
+ to set up state on the instanceMeta object.
11608
+
11609
+ `removedItem` - A function that is called each time an element is
11610
+ removed from the array.
11611
+
11612
+ `addedItem` - A function that is called each time an element is
11613
+ added to the array.
11407
11614
 
11615
+
11616
+ The `initialize` function has the following signature:
11617
+
11618
+ ```javascript
11619
+ function (array, changeMeta, instanceMeta)
11620
+ ```
11621
+
11622
+ `array` - The initial value of the arrayComputed, an empty array.
11623
+
11624
+ `changeMeta` - An object which contains meta information about the
11625
+ computed. It contains the following properties:
11626
+
11627
+ - `property` the computed property
11628
+ - `propertyName` the name of the property on the object
11629
+
11630
+ `instanceMeta` - An object that can be used to store meta
11631
+ information needed for calculating your computed. For example a
11632
+ unique computed might use this to store the number of times a given
11633
+ element is found in the dependent array.
11634
+
11635
+
11636
+ The `removedItem` and `addedItem` functions both have the following signature:
11637
+
11638
+ ```javascript
11639
+ function (accumulatedValue, item, changeMeta, instanceMeta)
11640
+ ```
11641
+
11642
+ `accumulatedValue` - The value returned from the last time
11643
+ `removedItem` or `addedItem` was called or an empty array.
11644
+
11645
+ `item` - the element added or removed from the array
11646
+
11647
+ `changeMeta` - An object which contains meta information about the
11648
+ change. It contains the following properties:
11649
+
11650
+ - `property` the computed property
11651
+ - `propertyName` the name of the property on the object
11652
+ - `index` the index of the added or removed item
11653
+ - `item` the added or removed item: this is exactly the same as
11654
+ the second arg
11655
+ - `arrayChanged` the array that triggered the change. Can be
11656
+ useful when depending on multiple arrays.
11657
+
11658
+ For property changes triggered on an item property change (when
11659
+ depKey is something like `someArray.@each.someProperty`),
11660
+ `changeMeta` will also contain the following property:
11661
+
11662
+ - `previousValues` an object whose keys are the properties that changed on
11663
+ the item, and whose values are the item's previous values.
11664
+
11665
+ `previousValues` is important Ember coalesces item property changes via
11666
+ Ember.run.once. This means that by the time removedItem gets called, item has
11667
+ the new values, but you may need the previous value (eg for sorting &
11668
+ filtering).
11669
+
11670
+ `instanceMeta` - An object that can be used to store meta
11671
+ information needed for calculating your computed. For example a
11672
+ unique computed might use this to store the number of times a given
11673
+ element is found in the dependent array.
11674
+
11675
+ The `removedItem` and `addedItem` functions should return the accumulated
11676
+ value. It is acceptable to not return anything (ie return undefined)
11677
+ to invalidate the computation. This is generally not a good idea for
11678
+ arrayComputed but it's used in eg max and min.
11679
+
11680
+ Example
11681
+
11682
+ ```javascript
11683
+ Ember.computed.map = function(dependentKey, callback) {
11684
+ var options = {
11685
+ addedItem: function(array, item, changeMeta, instanceMeta) {
11686
+ var mapped = callback(item);
11687
+ array.insertAt(changeMeta.index, mapped);
11688
+ return array;
11689
+ },
11690
+ removedItem: function(array, item, changeMeta, instanceMeta) {
11691
+ array.removeAt(changeMeta.index, 1);
11692
+ return array;
11693
+ }
11694
+ };
11695
+
11696
+ return Ember.arrayComputed(dependentKey, options);
11697
+ };
11698
+ ```
11699
+
11700
+ @method arrayComputed
11701
+ @for Ember
11702
+ @param {String} [dependentKeys*]
11703
+ @param {Object} options
11704
+ @returns {Ember.ComputedProperty}
11705
+ */
11408
11706
  Ember.arrayComputed = function (options) {
11409
11707
  var args;
11410
11708
 
@@ -11431,12 +11729,45 @@ Ember.arrayComputed = function (options) {
11431
11729
 
11432
11730
 
11433
11731
  (function() {
11732
+ /**
11733
+ @module ember
11734
+ @submodule ember-runtime
11735
+ */
11736
+
11434
11737
  var get = Ember.get,
11435
11738
  set = Ember.set,
11739
+ guidFor = Ember.guidFor,
11740
+ merge = Ember.merge,
11436
11741
  a_slice = [].slice,
11437
11742
  forEach = Ember.EnumerableUtils.forEach,
11438
11743
  map = Ember.EnumerableUtils.map;
11439
11744
 
11745
+ /**
11746
+ A computed property that calculates the maximum value in the
11747
+ dependent array. This will return `-Infinity` when the dependent
11748
+ array is empty.
11749
+
11750
+ Example
11751
+
11752
+ ```javascript
11753
+ App.Person = Ember.Object.extend({
11754
+ childAges: Ember.computed.mapBy('children', 'age'),
11755
+ maxChildAge: Ember.computed.max('childAges')
11756
+ });
11757
+
11758
+ var lordByron = App.Person.create({children: []});
11759
+ lordByron.get('maxChildAge'); // -Infinity
11760
+ lordByron.get('children').pushObject({name: 'Augusta Ada Byron', age: 7});
11761
+ lordByron.get('maxChildAge'); // 7
11762
+ lordByron.get('children').pushObjects([{name: 'Allegra Byron', age: 5}, {name: 'Elizabeth Medora Leigh', age: 8}]);
11763
+ lordByron.get('maxChildAge'); // 8
11764
+ ```
11765
+
11766
+ @method computed.max
11767
+ @for Ember
11768
+ @param {String} dependentKey
11769
+ @return {Ember.ComputedProperty} computes the largest value in the dependentKey's array
11770
+ */
11440
11771
  Ember.computed.max = function (dependentKey) {
11441
11772
  return Ember.reduceComputed.call(null, dependentKey, {
11442
11773
  initialValue: -Infinity,
@@ -11453,6 +11784,32 @@ Ember.computed.max = function (dependentKey) {
11453
11784
  });
11454
11785
  };
11455
11786
 
11787
+ /**
11788
+ A computed property that calculates the minimum value in the
11789
+ dependent array. This will return `Infinity` when the dependent
11790
+ array is empty.
11791
+
11792
+ Example
11793
+
11794
+ ```javascript
11795
+ App.Person = Ember.Object.extend({
11796
+ childAges: Ember.computed.mapBy('children', 'age'),
11797
+ minChildAge: Ember.computed.min('childAges')
11798
+ });
11799
+
11800
+ var lordByron = App.Person.create({children: []});
11801
+ lordByron.get('minChildAge'); // Infinity
11802
+ lordByron.get('children').pushObject({name: 'Augusta Ada Byron', age: 7});
11803
+ lordByron.get('minChildAge'); // 7
11804
+ lordByron.get('children').pushObjects([{name: 'Allegra Byron', age: 5}, {name: 'Elizabeth Medora Leigh', age: 8}]);
11805
+ lordByron.get('minChildAge'); // 5
11806
+ ```
11807
+
11808
+ @method computed.min
11809
+ @for Ember
11810
+ @param {String} dependentKey
11811
+ @return {Ember.ComputedProperty} computes the smallest value in the dependentKey's array
11812
+ */
11456
11813
  Ember.computed.min = function (dependentKey) {
11457
11814
  return Ember.reduceComputed.call(null, dependentKey, {
11458
11815
  initialValue: Infinity,
@@ -11469,6 +11826,36 @@ Ember.computed.min = function (dependentKey) {
11469
11826
  });
11470
11827
  };
11471
11828
 
11829
+ /**
11830
+ Returns an array mapped via the callback
11831
+
11832
+ The callback method you provide should have the following signature:
11833
+
11834
+ ```javascript
11835
+ function(item);
11836
+ ```
11837
+
11838
+ - `item` is the current item in the iteration.
11839
+
11840
+ Example
11841
+
11842
+ ```javascript
11843
+ App.Hampster = Ember.Object.extend({
11844
+ excitingChores: Ember.computed.map('chores', function(chore) {
11845
+ return chore.toUpperCase() + '!';
11846
+ })
11847
+ });
11848
+
11849
+ var hampster = App.Hampster.create({chores: ['cook', 'clean', 'write more unit tests']});
11850
+ hampster.get('excitingChores'); // ['COOK!', 'CLEAN!', 'WRITE MORE UNIT TESTS!']
11851
+ ```
11852
+
11853
+ @method computed.map
11854
+ @for Ember
11855
+ @param {String} dependentKey
11856
+ @param {Function} callback
11857
+ @return {Ember.ComputedProperty} an array mapped via the callback
11858
+ */
11472
11859
  Ember.computed.map = function(dependentKey, callback) {
11473
11860
  var options = {
11474
11861
  addedItem: function(array, item, changeMeta, instanceMeta) {
@@ -11485,11 +11872,79 @@ Ember.computed.map = function(dependentKey, callback) {
11485
11872
  return Ember.arrayComputed(dependentKey, options);
11486
11873
  };
11487
11874
 
11488
- Ember.computed.mapProperty = function(dependentKey, propertyKey) {
11875
+ /**
11876
+ Returns an array mapped to the specified key.
11877
+
11878
+ Example
11879
+
11880
+ ```javascript
11881
+ App.Person = Ember.Object.extend({
11882
+ childAges: Ember.computed.mapBy('children', 'age'),
11883
+ minChildAge: Ember.computed.min('childAges')
11884
+ });
11885
+
11886
+ var lordByron = App.Person.create({children: []});
11887
+ lordByron.get('childAge'); // []
11888
+ lordByron.get('children').pushObject({name: 'Augusta Ada Byron', age: 7});
11889
+ lordByron.get('childAge'); // [7]
11890
+ lordByron.get('children').pushObjects([{name: 'Allegra Byron', age: 5}, {name: 'Elizabeth Medora Leigh', age: 8}]);
11891
+ lordByron.get('childAge'); // [7, 5, 8]
11892
+ ```
11893
+
11894
+ @method computed.mapBy
11895
+ @for Ember
11896
+ @param {String} dependentKey
11897
+ @param {String} propertyKey
11898
+ @return {Ember.ComputedProperty} an array mapped to the specified key
11899
+ */
11900
+ Ember.computed.mapBy = function(dependentKey, propertyKey) {
11489
11901
  var callback = function(item) { return get(item, propertyKey); };
11490
11902
  return Ember.computed.map(dependentKey + '.@each.' + propertyKey, callback);
11491
11903
  };
11492
11904
 
11905
+ /**
11906
+ @method computed.mapProperty
11907
+ @for Ember
11908
+ @deprecated Use `Ember.computed.mapBy` instead
11909
+ @param dependentKey
11910
+ @param propertyKey
11911
+ */
11912
+ Ember.computed.mapProperty = Ember.computed.mapBy;
11913
+
11914
+ /**
11915
+ Filters the array by the callback.
11916
+
11917
+ The callback method you provide should have the following signature:
11918
+
11919
+ ```javascript
11920
+ function(item);
11921
+ ```
11922
+
11923
+ - `item` is the current item in the iteration.
11924
+
11925
+ Example
11926
+
11927
+ ```javascript
11928
+ App.Hampster = Ember.Object.extend({
11929
+ remainingChores: Ember.computed.filter('chores', function(chore) {
11930
+ return !chore.done;
11931
+ })
11932
+ });
11933
+
11934
+ var hampster = App.Hampster.create({chores: [
11935
+ {name: 'cook', done: true},
11936
+ {name: 'clean', done: true},
11937
+ {name: 'write more unit tests', done: false}
11938
+ ]});
11939
+ hampster.get('remainingChores'); // [{name: 'write more unit tests', done: false}]
11940
+ ```
11941
+
11942
+ @method computed.filter
11943
+ @for Ember
11944
+ @param {String} dependentKey
11945
+ @param {Function} callback
11946
+ @return {Ember.ComputedProperty} the filtered array
11947
+ */
11493
11948
  Ember.computed.filter = function(dependentKey, callback) {
11494
11949
  var options = {
11495
11950
  initialize: function (array, changeMeta, instanceMeta) {
@@ -11503,6 +11958,8 @@ Ember.computed.filter = function(dependentKey, callback) {
11503
11958
  if (match) {
11504
11959
  array.insertAt(filterIndex, item);
11505
11960
  }
11961
+
11962
+ return array;
11506
11963
  },
11507
11964
 
11508
11965
  removedItem: function(array, item, changeMeta, instanceMeta) {
@@ -11511,13 +11968,40 @@ Ember.computed.filter = function(dependentKey, callback) {
11511
11968
  if (filterIndex > -1) {
11512
11969
  array.removeAt(filterIndex);
11513
11970
  }
11971
+
11972
+ return array;
11514
11973
  }
11515
11974
  };
11516
11975
 
11517
11976
  return Ember.arrayComputed(dependentKey, options);
11518
11977
  };
11519
11978
 
11520
- Ember.computed.filterProperty = function(dependentKey, propertyKey, value) {
11979
+ /**
11980
+ Filters the array by the property and value
11981
+
11982
+ Example
11983
+
11984
+ ```javascript
11985
+ App.Hampster = Ember.Object.extend({
11986
+ remainingChores: Ember.computed.filterBy('chores', 'done', false)
11987
+ });
11988
+
11989
+ var hampster = App.Hampster.create({chores: [
11990
+ {name: 'cook', done: true},
11991
+ {name: 'clean', done: true},
11992
+ {name: 'write more unit tests', done: false}
11993
+ ]});
11994
+ hampster.get('remainingChores'); // [{name: 'write more unit tests', done: false}]
11995
+ ```
11996
+
11997
+ @method computed.filterBy
11998
+ @for Ember
11999
+ @param {String} dependentKey
12000
+ @param {String} propertyKey
12001
+ @param {String} value
12002
+ @return {Ember.ComputedProperty} the filtered array
12003
+ */
12004
+ Ember.computed.filterBy = function(dependentKey, propertyKey, value) {
11521
12005
  var callback;
11522
12006
 
11523
12007
  if (arguments.length === 2) {
@@ -11533,6 +12017,42 @@ Ember.computed.filterProperty = function(dependentKey, propertyKey, value) {
11533
12017
  return Ember.computed.filter(dependentKey + '.@each.' + propertyKey, callback);
11534
12018
  };
11535
12019
 
12020
+ /**
12021
+ @method computed.filterProperty
12022
+ @for Ember
12023
+ @param dependentKey
12024
+ @param propertyKey
12025
+ @param value
12026
+ @deprecated Use `Ember.computed.filterBy` instead
12027
+ */
12028
+ Ember.computed.filterProperty = Ember.computed.filterBy;
12029
+
12030
+ /**
12031
+ A computed property which returns a new array with all the unique
12032
+ elements from one or more dependent arrays.
12033
+
12034
+ Example
12035
+
12036
+ ```javascript
12037
+ App.Hampster = Ember.Object.extend({
12038
+ uniqueFruits: Ember.computed.uniq('fruits')
12039
+ });
12040
+
12041
+ var hampster = App.Hampster.create({fruits: [
12042
+ 'banana',
12043
+ 'grape',
12044
+ 'kale',
12045
+ 'banana'
12046
+ ]});
12047
+ hampster.get('uniqueFruits'); // ['banana', 'grape', 'kale']
12048
+ ```
12049
+
12050
+ @method computed.uniq
12051
+ @for Ember
12052
+ @param {String} propertyKey*
12053
+ @return {Ember.ComputedProperty} computes a new array with all the
12054
+ unique elements from the dependent array
12055
+ */
11536
12056
  Ember.computed.uniq = function() {
11537
12057
  var args = a_slice.call(arguments);
11538
12058
  args.push({
@@ -11541,7 +12061,7 @@ Ember.computed.uniq = function() {
11541
12061
  },
11542
12062
 
11543
12063
  addedItem: function(array, item, changeMeta, instanceMeta) {
11544
- var guid = Ember.guidFor(item);
12064
+ var guid = guidFor(item);
11545
12065
 
11546
12066
  if (!instanceMeta.itemCounts[guid]) {
11547
12067
  instanceMeta.itemCounts[guid] = 1;
@@ -11552,7 +12072,7 @@ Ember.computed.uniq = function() {
11552
12072
  return array;
11553
12073
  },
11554
12074
  removedItem: function(array, item, _, instanceMeta) {
11555
- var guid = Ember.guidFor(item),
12075
+ var guid = guidFor(item),
11556
12076
  itemCounts = instanceMeta.itemCounts;
11557
12077
 
11558
12078
  if (--itemCounts[guid] === 0) {
@@ -11563,12 +12083,44 @@ Ember.computed.uniq = function() {
11563
12083
  });
11564
12084
  return Ember.arrayComputed.apply(null, args);
11565
12085
  };
12086
+
12087
+ /**
12088
+ Alias for [Ember.computed.uniq](/api/#method_computed_uniq).
12089
+
12090
+ @method computed.union
12091
+ @for Ember
12092
+ @param {String} propertyKey*
12093
+ @return {Ember.ComputedProperty} computes a new array with all the
12094
+ unique elements from the dependent array
12095
+ */
11566
12096
  Ember.computed.union = Ember.computed.uniq;
11567
12097
 
12098
+ /**
12099
+ A computed property which returns a new array with all the duplicated
12100
+ elements from two or more dependeny arrays.
12101
+
12102
+ Example
12103
+
12104
+ ```javascript
12105
+ var obj = Ember.Object.createWithMixins({
12106
+ adaFriends: ['Charles Babbage', 'John Hobhouse', 'William King', 'Mary Somerville'],
12107
+ charlesFriends: ['William King', 'Mary Somerville', 'Ada Lovelace', 'George Peacock'],
12108
+ friendsInCommon: Ember.computed.intersect('adaFriends', 'charlesFriends')
12109
+ });
12110
+
12111
+ obj.get('friendsInCommon'); // ['William King', 'Mary Somerville']
12112
+ ```
12113
+
12114
+ @method computed.intersect
12115
+ @for Ember
12116
+ @param {String} propertyKey*
12117
+ @return {Ember.ComputedProperty} computes a new array with all the
12118
+ duplicated elements from the dependent arrays
12119
+ */
11568
12120
  Ember.computed.intersect = function () {
11569
12121
  var getDependentKeyGuids = function (changeMeta) {
11570
12122
  return map(changeMeta.property._dependentKeys, function (dependentKey) {
11571
- return Ember.guidFor(dependentKey);
12123
+ return guidFor(dependentKey);
11572
12124
  });
11573
12125
  };
11574
12126
 
@@ -11579,9 +12131,9 @@ Ember.computed.intersect = function () {
11579
12131
  },
11580
12132
 
11581
12133
  addedItem: function(array, item, changeMeta, instanceMeta) {
11582
- var itemGuid = Ember.guidFor(item),
12134
+ var itemGuid = guidFor(item),
11583
12135
  dependentGuids = getDependentKeyGuids(changeMeta),
11584
- dependentGuid = Ember.guidFor(changeMeta.arrayChanged),
12136
+ dependentGuid = guidFor(changeMeta.arrayChanged),
11585
12137
  numberOfDependentArrays = changeMeta.property._dependentKeys.length,
11586
12138
  itemCounts = instanceMeta.itemCounts;
11587
12139
 
@@ -11590,15 +12142,15 @@ Ember.computed.intersect = function () {
11590
12142
 
11591
12143
  if (++itemCounts[itemGuid][dependentGuid] === 1 &&
11592
12144
  numberOfDependentArrays === Ember.keys(itemCounts[itemGuid]).length) {
11593
-
12145
+
11594
12146
  array.addObject(item);
11595
12147
  }
11596
12148
  return array;
11597
12149
  },
11598
12150
  removedItem: function(array, item, changeMeta, instanceMeta) {
11599
- var itemGuid = Ember.guidFor(item),
12151
+ var itemGuid = guidFor(item),
11600
12152
  dependentGuids = getDependentKeyGuids(changeMeta),
11601
- dependentGuid = Ember.guidFor(changeMeta.arrayChanged),
12153
+ dependentGuid = guidFor(changeMeta.arrayChanged),
11602
12154
  numberOfDependentArrays = changeMeta.property._dependentKeys.length,
11603
12155
  numberOfArraysItemAppearsIn,
11604
12156
  itemCounts = instanceMeta.itemCounts;
@@ -11619,6 +12171,34 @@ Ember.computed.intersect = function () {
11619
12171
  return Ember.arrayComputed.apply(null, args);
11620
12172
  };
11621
12173
 
12174
+ /**
12175
+ A computed property which returns a new array with all the
12176
+ properties from the first dependent array that are not in the second
12177
+ dependent array.
12178
+
12179
+ Example
12180
+
12181
+ ```javascript
12182
+ App.Hampster = Ember.Object.extend({
12183
+ likes: ['banana', 'grape', 'kale'],
12184
+ wants: Ember.computed.setDiff('likes', 'fruits')
12185
+ });
12186
+
12187
+ var hampster = App.Hampster.create({fruits: [
12188
+ 'grape',
12189
+ 'kale',
12190
+ ]});
12191
+ hampster.get('wants'); // ['banana']
12192
+ ```
12193
+
12194
+ @method computed.setDiff
12195
+ @for Ember
12196
+ @param {String} setAProperty
12197
+ @param {String} setBProperty
12198
+ @return {Ember.ComputedProperty} computes a new array with all the
12199
+ items from the first dependent array that are not in the second
12200
+ dependent array
12201
+ */
11622
12202
  Ember.computed.setDiff = function (setAProperty, setBProperty) {
11623
12203
  if (arguments.length !== 2) {
11624
12204
  throw new Error("setDiff requires exactly two dependent arrays.");
@@ -11627,7 +12207,7 @@ Ember.computed.setDiff = function (setAProperty, setBProperty) {
11627
12207
  addedItem: function (array, item, changeMeta, instanceMeta) {
11628
12208
  var setA = get(this, setAProperty),
11629
12209
  setB = get(this, setBProperty);
11630
-
12210
+
11631
12211
  if (changeMeta.arrayChanged === setA) {
11632
12212
  if (!setB.contains(item)) {
11633
12213
  array.addObject(item);
@@ -11641,7 +12221,7 @@ Ember.computed.setDiff = function (setAProperty, setBProperty) {
11641
12221
  removedItem: function (array, item, changeMeta, instanceMeta) {
11642
12222
  var setA = get(this, setAProperty),
11643
12223
  setB = get(this, setBProperty);
11644
-
12224
+
11645
12225
  if (changeMeta.arrayChanged === setB) {
11646
12226
  if (setA.contains(item)) {
11647
12227
  array.addObject(item);
@@ -11655,7 +12235,7 @@ Ember.computed.setDiff = function (setAProperty, setBProperty) {
11655
12235
  };
11656
12236
 
11657
12237
  function binarySearch(array, item, low, high) {
11658
- var mid, midItem, res;
12238
+ var mid, midItem, res, guidMid, guidItem;
11659
12239
 
11660
12240
  if (arguments.length < 4) { high = get(array, 'length'); }
11661
12241
  if (arguments.length < 3) { low = 0; }
@@ -11667,7 +12247,18 @@ function binarySearch(array, item, low, high) {
11667
12247
  mid = low + Math.floor((high - low) / 2);
11668
12248
  midItem = array.objectAt(mid);
11669
12249
 
12250
+ guidMid = _guidFor(midItem);
12251
+ guidItem = _guidFor(item);
12252
+
12253
+ if (guidMid === guidItem) {
12254
+ return mid;
12255
+ }
12256
+
11670
12257
  res = this.order(midItem, item);
12258
+ if (res === 0) {
12259
+ res = guidMid < guidItem ? -1 : 1;
12260
+ }
12261
+
11671
12262
 
11672
12263
  if (res < 0) {
11673
12264
  return this.binarySearch(array, item, mid+1, high);
@@ -11676,8 +12267,66 @@ function binarySearch(array, item, low, high) {
11676
12267
  }
11677
12268
 
11678
12269
  return mid;
12270
+
12271
+ function _guidFor(item) {
12272
+ if (Ember.ObjectProxy.detectInstance(item)) {
12273
+ return guidFor(get(item, 'content'));
12274
+ }
12275
+ return guidFor(item);
12276
+ }
11679
12277
  }
11680
12278
 
12279
+ /**
12280
+ A computed property which returns a new array with all the
12281
+ properties from the first dependent array sorted based on a property
12282
+ or sort function.
12283
+
12284
+ The callback method you provide should have the following signature:
12285
+
12286
+ ```javascript
12287
+ function(itemA, itemB);
12288
+ ```
12289
+
12290
+ - `itemA` the first item to compare.
12291
+ - `itemB` the second item to compare.
12292
+
12293
+ This function should return `-1` when `itemA` should come before
12294
+ `itemB`. It should return `1` when `itemA` should come after
12295
+ `itemB`. If the `itemA` and `itemB` are equal this function should return `0`.
12296
+
12297
+ Example
12298
+
12299
+ ```javascript
12300
+ var ToDoList = Ember.Object.extend({
12301
+ todosSorting: ['name'],
12302
+ sortedTodos: Ember.computed.sort('todos', 'todosSorting'),
12303
+ priorityTodos: Ember.computed.sort('todos', function(a, b){
12304
+ if (a.priority > b.priority) {
12305
+ return 1;
12306
+ } else if (a.priority < b.priority) {
12307
+ return -1;
12308
+ }
12309
+ return 0;
12310
+ }),
12311
+ });
12312
+ var todoList = ToDoList.create({todos: [
12313
+ {name: 'Unit Test', priority: 2},
12314
+ {name: 'Documentation', priority: 3},
12315
+ {name: 'Release', priority: 1}
12316
+ ]});
12317
+
12318
+ todoList.get('sortedTodos'); // [{name:'Documentation', priority:3}, {name:'Release', priority:1}, {name:'Unit Test', priority:2}]
12319
+ todoList.get('priroityTodos'); // [{name:'Release', priority:1}, {name:'Unit Test', priority:2}, {name:'Documentation', priority:3}]
12320
+ ```
12321
+
12322
+ @method computed.sort
12323
+ @for Ember
12324
+ @param {String} dependentKey
12325
+ @param {String or Function} sortDefinition a dependent key to an
12326
+ array of sort properties or a function to use when sorting
12327
+ @return {Ember.ComputedProperty} computes a new sorted array based
12328
+ on the sort property array or callback function
12329
+ */
11681
12330
  Ember.computed.sort = function (itemsKey, sortDefinition) {
11682
12331
  Ember.assert("Ember.computed.sort requires two arguments: an array key to sort and either a sort properties key or sort function", arguments.length === 2);
11683
12332
 
@@ -11765,9 +12414,8 @@ Ember.computed.sort = function (itemsKey, sortDefinition) {
11765
12414
  removedItem: function (array, item, changeMeta, instanceMeta) {
11766
12415
  var proxyProperties, index, searchItem;
11767
12416
 
11768
- if (changeMeta.keyChanged) {
11769
- proxyProperties = { content: item };
11770
- proxyProperties[changeMeta.keyChanged] = changeMeta.previousValue;
12417
+ if (changeMeta.previousValues) {
12418
+ proxyProperties = merge({ content: item }, changeMeta.previousValues);
11771
12419
 
11772
12420
  searchItem = Ember.ObjectProxy.create(proxyProperties);
11773
12421
  } else {
@@ -12191,9 +12839,9 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Function) {
12191
12839
  Computed properties allow you to treat a function like a property:
12192
12840
 
12193
12841
  ```javascript
12194
- MyApp.president = Ember.Object.create({
12195
- firstName: "Barack",
12196
- lastName: "Obama",
12842
+ MyApp.President = Ember.Object.extend({
12843
+ firstName: '',
12844
+ lastName: '',
12197
12845
 
12198
12846
  fullName: function() {
12199
12847
  return this.get('firstName') + ' ' + this.get('lastName');
@@ -12202,7 +12850,12 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Function) {
12202
12850
  }.property()
12203
12851
  });
12204
12852
 
12205
- MyApp.president.get('fullName'); // "Barack Obama"
12853
+ var president = MyApp.President.create({
12854
+ firstName: "Barack",
12855
+ lastName: "Obama"
12856
+ });
12857
+
12858
+ president.get('fullName'); // "Barack Obama"
12206
12859
  ```
12207
12860
 
12208
12861
  Treating a function like a property is useful because they can work with
@@ -12214,9 +12867,9 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Function) {
12214
12867
  about these dependencies like this:
12215
12868
 
12216
12869
  ```javascript
12217
- MyApp.president = Ember.Object.create({
12218
- firstName: "Barack",
12219
- lastName: "Obama",
12870
+ MyApp.President = Ember.Object.extend({
12871
+ firstName: '',
12872
+ lastName: '',
12220
12873
 
12221
12874
  fullName: function() {
12222
12875
  return this.get('firstName') + ' ' + this.get('lastName');
@@ -12253,15 +12906,18 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Function) {
12253
12906
  For example:
12254
12907
 
12255
12908
  ```javascript
12256
- Ember.Object.create({
12909
+ Ember.Object.extend({
12257
12910
  valueObserver: function() {
12258
12911
  // Executes whenever the "value" property changes
12259
12912
  }.observes('value')
12260
12913
  });
12261
12914
  ```
12262
12915
 
12263
- See `Ember.observes`.
12264
-
12916
+ In the future this method may become asynchronous. If you want to ensure
12917
+ synchronous behavior, use `observesImmediately`.
12918
+
12919
+ See `Ember.observer`.
12920
+
12265
12921
  @method observes
12266
12922
  @for Function
12267
12923
  */
@@ -12270,24 +12926,58 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Function) {
12270
12926
  return this;
12271
12927
  };
12272
12928
 
12929
+ /**
12930
+ The `observesImmediately` extension of Javascript's Function prototype is
12931
+ available when `Ember.EXTEND_PROTOTYPES` or
12932
+ `Ember.EXTEND_PROTOTYPES.Function` is true, which is the default.
12933
+
12934
+ You can observe property changes simply by adding the `observesImmediately`
12935
+ call to the end of your method declarations in classes that you write.
12936
+ For example:
12937
+
12938
+ ```javascript
12939
+ Ember.Object.extend({
12940
+ valueObserver: function() {
12941
+ // Executes immediately after the "value" property changes
12942
+ }.observesImmediately('value')
12943
+ });
12944
+ ```
12945
+
12946
+ In the future, `observes` may become asynchronous. In this event,
12947
+ `observesImmediately` will maintain the synchronous behavior.
12948
+
12949
+ See `Ember.immediateObserver`.
12950
+
12951
+ @method observesImmediately
12952
+ @for Function
12953
+ */
12954
+ Function.prototype.observesImmediately = function() {
12955
+ for (var i=0, l=arguments.length; i<l; i++) {
12956
+ var arg = arguments[i];
12957
+ Ember.assert("Immediate observers must observe internal properties only, not properties on other objects.", arg.indexOf('.') === -1);
12958
+ }
12959
+
12960
+ return this.observes.apply(this, arguments);
12961
+ };
12962
+
12273
12963
  /**
12274
12964
  The `observesBefore` extension of Javascript's Function prototype is
12275
12965
  available when `Ember.EXTEND_PROTOTYPES` or
12276
12966
  `Ember.EXTEND_PROTOTYPES.Function` is true, which is the default.
12277
12967
 
12278
- You can get notified when a property changes is about to happen by
12968
+ You can get notified when a property change is about to happen by
12279
12969
  by adding the `observesBefore` call to the end of your method
12280
12970
  declarations in classes that you write. For example:
12281
12971
 
12282
12972
  ```javascript
12283
- Ember.Object.create({
12973
+ Ember.Object.extend({
12284
12974
  valueObserver: function() {
12285
12975
  // Executes whenever the "value" property is about to change
12286
12976
  }.observesBefore('value')
12287
12977
  });
12288
12978
  ```
12289
12979
 
12290
- See `Ember.observesBefore`.
12980
+ See `Ember.beforeObserver`.
12291
12981
 
12292
12982
  @method observesBefore
12293
12983
  @for Function
@@ -13730,11 +14420,6 @@ Ember.Evented = Ember.Mixin.create({
13730
14420
  Ember.sendEvent(this, name, args);
13731
14421
  },
13732
14422
 
13733
- fire: function(name) {
13734
- Ember.deprecate("Ember.Evented#fire() has been deprecated in favor of trigger() for compatibility with jQuery. It will be removed in 1.0. Please update your code to call trigger() instead.");
13735
- this.trigger.apply(this, arguments);
13736
- },
13737
-
13738
14423
  /**
13739
14424
  Cancels subscription for given name, target, and method.
13740
14425
 
@@ -13913,6 +14598,121 @@ Ember.ActionHandler = Ember.Mixin.create({
13913
14598
 
13914
14599
 
13915
14600
 
14601
+ (function() {
14602
+ var set = Ember.set, get = Ember.get,
14603
+ resolve = Ember.RSVP.resolve,
14604
+ rethrow = Ember.RSVP.rethrow,
14605
+ not = Ember.computed.not,
14606
+ or = Ember.computed.or;
14607
+
14608
+ /**
14609
+ @module ember
14610
+ @submodule ember-runtime
14611
+ */
14612
+
14613
+ function installPromise(proxy, promise) {
14614
+ promise.then(function(value) {
14615
+ set(proxy, 'isFulfilled', true);
14616
+ set(proxy, 'content', value);
14617
+
14618
+ return value;
14619
+ }, function(reason) {
14620
+ set(proxy, 'isRejected', true);
14621
+ set(proxy, 'reason', reason);
14622
+ }).fail(rethrow);
14623
+ }
14624
+
14625
+ /**
14626
+ A low level mixin making ObjectProxy, ObjectController or ArrayController's promise aware.
14627
+
14628
+ ```javascript
14629
+ var ObjectPromiseController = Ember.ObjectController.extend(Ember.PromiseProxyMixin);
14630
+
14631
+ var controller = ObjectPromiseController.create({
14632
+ promise: $.getJSON('/some/remote/data.json')
14633
+ });
14634
+
14635
+ controller.then(function(json){
14636
+ // the json
14637
+ }, function(reason) {
14638
+ // the reason why you have no json
14639
+ });
14640
+ ```
14641
+
14642
+ the controller has bindable attributes which
14643
+ track the promises life cycle
14644
+
14645
+ ```javascript
14646
+ controller.get('isPending') //=> true
14647
+ controller.get('isSettled') //=> false
14648
+ controller.get('isRejected') //=> false
14649
+ controller.get('isFulfilled') //=> false
14650
+ ```
14651
+
14652
+ When the the $.getJSON completes, and the promise is fulfilled
14653
+ with json, the life cycle attributes will update accordingly.
14654
+
14655
+ ```javascript
14656
+ controller.get('isPending') //=> false
14657
+ controller.get('isSettled') //=> true
14658
+ controller.get('isRejected') //=> false
14659
+ controller.get('isFulfilled') //=> true
14660
+ ```
14661
+
14662
+ As the controller is an ObjectController, and the json now its content,
14663
+ all the json properties will be available directly from the controller.
14664
+
14665
+ ```javascript
14666
+ // Assuming the following json:
14667
+ {
14668
+ firstName: 'Stefan',
14669
+ lastName: 'Penner'
14670
+ }
14671
+
14672
+ // both properties will accessible on the controller
14673
+ controller.get('firstName') //=> 'Stefan'
14674
+ controller.get('lastName') //=> 'Penner'
14675
+ ```
14676
+
14677
+ If the controller is backing a template, the attributes are
14678
+ bindable from within that template
14679
+ ```handlebars
14680
+ {{#if isPending}}
14681
+ loading...
14682
+ {{else}}
14683
+ firstName: {{firstName}}
14684
+ lastName: {{lastName}}
14685
+ {{/if}}
14686
+ ```
14687
+ @class Ember.PromiseProxyMixin
14688
+ */
14689
+ Ember.PromiseProxyMixin = Ember.Mixin.create({
14690
+ reason: null,
14691
+ isPending: not('isSettled').readOnly(),
14692
+ isSettled: or('isRejected', 'isFulfilled').readOnly(),
14693
+ isRejected: false,
14694
+ isFulfilled: false,
14695
+
14696
+ promise: Ember.computed(function(key, promise) {
14697
+ if (arguments.length === 2) {
14698
+ promise = resolve(promise);
14699
+ installPromise(this, promise);
14700
+ return promise;
14701
+ } else {
14702
+ throw new Error("PromiseProxy's promise must be set");
14703
+ }
14704
+ }),
14705
+
14706
+ then: function(fulfill, reject) {
14707
+ return get(this, 'promise').then(fulfill, reject);
14708
+ }
14709
+ });
14710
+
14711
+
14712
+ })();
14713
+
14714
+
14715
+
13916
14716
  (function() {
13917
14717
 
13918
14718
  })();
@@ -15613,7 +16413,9 @@ var get = Ember.get,
15613
16413
  removeBeforeObserver = Ember.removeBeforeObserver,
15614
16414
  removeObserver = Ember.removeObserver,
15615
16415
  propertyWillChange = Ember.propertyWillChange,
15616
- propertyDidChange = Ember.propertyDidChange;
16416
+ propertyDidChange = Ember.propertyDidChange,
16417
+ meta = Ember.meta,
16418
+ defineProperty = Ember.defineProperty;
15617
16419
 
15618
16420
  function contentPropertyWillChange(content, contentKey) {
15619
16421
  var key = contentKey.slice(8); // remove "content."
@@ -15731,6 +16533,14 @@ Ember.ObjectProxy = Ember.Object.extend(/** @scope Ember.ObjectProxy.prototype *
15731
16533
  },
15732
16534
 
15733
16535
  setUnknownProperty: function (key, value) {
16536
+ var m = meta(this);
16537
+ if (m.proto === this) {
16538
+ // if marked as prototype then just defineProperty
16539
+ // rather than delegate
16540
+ defineProperty(this, key, null, value);
16541
+ return value;
16542
+ }
16543
+
15734
16544
  var content = get(this, 'content');
15735
16545
  Ember.assert(fmt("Cannot delegate set('%@', %@) to the 'content' property of object proxy %@: its 'content' is undefined.", [key, value, this]), content);
15736
16546
  return set(content, key, value);
@@ -15738,25 +16548,6 @@ Ember.ObjectProxy = Ember.Object.extend(/** @scope Ember.ObjectProxy.prototype *
15738
16548
 
15739
16549
  });
15740
16550
 
15741
- Ember.ObjectProxy.reopenClass({
15742
- create: function () {
15743
- var mixin, prototype, i, l, properties, keyName;
15744
- if (arguments.length) {
15745
- prototype = this.proto();
15746
- for (i = 0, l = arguments.length; i < l; i++) {
15747
- properties = arguments[i];
15748
- for (keyName in properties) {
15749
- if (!properties.hasOwnProperty(keyName) || keyName in prototype) { continue; }
15750
- if (!mixin) mixin = {};
15751
- mixin[keyName] = null;
15752
- }
15753
- }
15754
- if (mixin) this._initMixins([mixin]);
15755
- }
15756
- return this._super.apply(this, arguments);
15757
- }
15758
- });
15759
-
15760
16551
  })();
15761
16552
 
15762
16553
 
@@ -15769,7 +16560,8 @@ Ember.ObjectProxy.reopenClass({
15769
16560
 
15770
16561
 
15771
16562
  var set = Ember.set, get = Ember.get, guidFor = Ember.guidFor;
15772
- var forEach = Ember.EnumerableUtils.forEach;
16563
+ var forEach = Ember.EnumerableUtils.forEach,
16564
+ indexOf = Ember.ArrayPolyfills.indexOf;
15773
16565
 
15774
16566
  var EachArray = Ember.Object.extend(Ember.Array, {
15775
16567
 
@@ -15827,7 +16619,7 @@ function removeObserverForContentKey(content, keyName, proxy, idx, loc) {
15827
16619
 
15828
16620
  guid = guidFor(item);
15829
16621
  indicies = objects[guid];
15830
- indicies[indicies.indexOf(loc)] = null;
16622
+ indicies[indexOf.call(indicies, loc)] = null;
15831
16623
  }
15832
16624
  }
15833
16625
  }
@@ -16752,7 +17544,7 @@ Ember.ControllerMixin = Ember.Mixin.create(Ember.ActionHandler, {
16752
17544
  deprecatedSend: function(actionName) {
16753
17545
  var args = [].slice.call(arguments, 1);
16754
17546
  Ember.assert('' + this + " has the action " + actionName + " but it is not a function", typeof this[actionName] === 'function');
16755
- Ember.deprecate('Action handlers implemented directly on controllers are deprecated in favor of action handlers on an `actions` object', false);
17547
+ Ember.deprecate('Action handlers implemented directly on controllers are deprecated in favor of action handlers on an `actions` object (' + actionName + ' on ' + this + ')', false);
16756
17548
  this[actionName].apply(this, args);
16757
17549
  return;
16758
17550
  }
@@ -17232,11 +18024,15 @@ Ember.ArrayController = Ember.ArrayProxy.extend(Ember.ControllerMixin,
17232
18024
  },
17233
18025
 
17234
18026
  init: function() {
17235
- if (!this.get('content')) { Ember.defineProperty(this, 'content', undefined, Ember.A()); }
17236
18027
  this._super();
18028
+
17237
18029
  this.set('_subControllers', Ember.A());
17238
18030
  },
17239
18031
 
18032
+ content: Ember.computed(function () {
18033
+ return Ember.A();
18034
+ }),
18035
+
17240
18036
  controllerAt: function(idx, object, controllerClass) {
17241
18037
  var container = get(this, 'container'),
17242
18038
  subControllers = get(this, '_subControllers'),