ember-source 1.0.0.rc6.2 → 1.0.0.rc6.4

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.6-56-g19271bc
4
- // Last commit: 19271bc (2013-06-30 23:18:40 -0700)
3
+ // Version: v1.0.0-rc.6-221-g9d051c2
4
+ // Last commit: 9d051c2 (2013-07-28 23:13:59 -0700)
5
5
 
6
6
 
7
7
  (function() {
@@ -1,5 +1,5 @@
1
- // Version: v1.0.0-rc.6-56-g19271bc
2
- // Last commit: 19271bc (2013-06-30 23:18:40 -0700)
1
+ // Version: v1.0.0-rc.6-221-g9d051c2
2
+ // Last commit: 9d051c2 (2013-07-28 23:13:59 -0700)
3
3
 
4
4
 
5
5
  (function() {
@@ -156,8 +156,8 @@ Ember.deprecateFunc = function(message, func) {
156
156
 
157
157
  })();
158
158
 
159
- // Version: v1.0.0-rc.6-56-g19271bc
160
- // Last commit: 19271bc (2013-06-30 23:18:40 -0700)
159
+ // Version: v1.0.0-rc.6-221-g9d051c2
160
+ // Last commit: 9d051c2 (2013-07-28 23:13:59 -0700)
161
161
 
162
162
 
163
163
  (function() {
@@ -251,10 +251,10 @@ Ember.toString = function() { return "Ember"; };
251
251
  /**
252
252
  @property VERSION
253
253
  @type String
254
- @default '1.0.0-rc.6'
254
+ @default '1.0.0-rc.6.1'
255
255
  @final
256
256
  */
257
- Ember.VERSION = '1.0.0-rc.6';
257
+ Ember.VERSION = '1.0.0-rc.6.1';
258
258
 
259
259
  /**
260
260
  Standard environmental variables. You can define these in a global `ENV`
@@ -354,16 +354,19 @@ Ember.uuid = 0;
354
354
  //
355
355
 
356
356
  function consoleMethod(name) {
357
- if (imports.console && imports.console[name]) {
357
+ var console = imports.console,
358
+ method = typeof console === 'object' ? console[name] : null;
359
+
360
+ if (method) {
358
361
  // Older IE doesn't support apply, but Chrome needs it
359
- if (imports.console[name].apply) {
362
+ if (method.apply) {
360
363
  return function() {
361
- imports.console[name].apply(imports.console, arguments);
364
+ method.apply(console, arguments);
362
365
  };
363
366
  } else {
364
367
  return function() {
365
368
  var message = Array.prototype.join.call(arguments, ', ');
366
- imports.console[name](message);
369
+ method(message);
367
370
  };
368
371
  }
369
372
  }
@@ -375,7 +378,7 @@ function assertPolyfill(test, message) {
375
378
  // attempt to preserve the stack
376
379
  throw new Error("assertion failed: " + message);
377
380
  } catch(error) {
378
- setTimeout(function(){
381
+ setTimeout(function() {
379
382
  throw error;
380
383
  }, 0);
381
384
  }
@@ -457,7 +460,7 @@ Ember.merge = function(original, updates) {
457
460
  Ember.isNone(undefined); // true
458
461
  Ember.isNone(''); // false
459
462
  Ember.isNone([]); // false
460
- Ember.isNone(function(){}); // false
463
+ Ember.isNone(function() {}); // false
461
464
  ```
462
465
 
463
466
  @method isNone
@@ -562,7 +565,7 @@ var canRedefineProperties, canDefinePropertyOnDOM;
562
565
  // Catch IE8 where Object.defineProperty exists but only works on DOM elements
563
566
  if (defineProperty) {
564
567
  try {
565
- defineProperty({}, 'a',{get:function(){}});
568
+ defineProperty({}, 'a',{get:function() {}});
566
569
  } catch (e) {
567
570
  defineProperty = null;
568
571
  }
@@ -593,7 +596,7 @@ if (defineProperty) {
593
596
 
594
597
  // This is for Safari 5.0, which supports Object.defineProperty, but not
595
598
  // on DOM nodes.
596
- canDefinePropertyOnDOM = (function(){
599
+ canDefinePropertyOnDOM = (function() {
597
600
  try {
598
601
  defineProperty(document.createElement('div'), 'definePropertyOnDOM', {});
599
602
  return true;
@@ -605,7 +608,7 @@ if (defineProperty) {
605
608
  if (!canRedefineProperties) {
606
609
  defineProperty = null;
607
610
  } else if (!canDefinePropertyOnDOM) {
608
- defineProperty = function(obj, keyName, desc){
611
+ defineProperty = function(obj, keyName, desc) {
609
612
  var isNode;
610
613
 
611
614
  if (typeof Node === "object") {
@@ -1215,7 +1218,7 @@ if (needsFinallyFix) {
1215
1218
  } finally {
1216
1219
  try {
1217
1220
  finalResult = finalizer.call(binding);
1218
- } catch (e){
1221
+ } catch (e) {
1219
1222
  finalError = e;
1220
1223
  }
1221
1224
  }
@@ -1267,7 +1270,7 @@ if (needsFinallyFix) {
1267
1270
  } finally {
1268
1271
  try {
1269
1272
  finalResult = finalizer.call(binding);
1270
- } catch (e){
1273
+ } catch (e) {
1271
1274
  finalError = e;
1272
1275
  }
1273
1276
  }
@@ -1466,7 +1469,7 @@ Ember.Instrumentation.instrument = function(name, payload, callback, binding) {
1466
1469
 
1467
1470
  var beforeValues = [], listener, i, l;
1468
1471
 
1469
- function tryable(){
1472
+ function tryable() {
1470
1473
  for (i=0, l=listeners.length; i<l; i++) {
1471
1474
  listener = listeners[i];
1472
1475
  beforeValues[i] = listener.before(name, time(), payload);
@@ -1475,7 +1478,7 @@ Ember.Instrumentation.instrument = function(name, payload, callback, binding) {
1475
1478
  return callback.call(binding);
1476
1479
  }
1477
1480
 
1478
- function catchable(e){
1481
+ function catchable(e) {
1479
1482
  payload = payload || {};
1480
1483
  payload.exception = e;
1481
1484
  }
@@ -1994,14 +1997,10 @@ function suspendListener(obj, eventName, target, method, callback) {
1994
1997
  /**
1995
1998
  @private
1996
1999
 
1997
- Suspend listener during callback.
1998
-
1999
- This should only be used by the target of the event listener
2000
- when it is taking an action that would cause the event, e.g.
2001
- an object might suspend its property change listener while it is
2002
- setting that property.
2000
+ Suspends multiple listeners during a callback.
2003
2001
 
2004
- @method suspendListener
2002
+
2003
+ @method suspendListeners
2005
2004
  @for Ember
2006
2005
  @param obj
2007
2006
  @param {Array} eventName Array of event names
@@ -2063,12 +2062,17 @@ function watchedEvents(obj) {
2063
2062
  }
2064
2063
 
2065
2064
  /**
2065
+ Send an event. The execution of suspended listeners
2066
+ is skipped, and once listeners are removed. A listener without
2067
+ a target is executed on the passed object. If an array of actions
2068
+ is not passed, the actions stored on the passed object are invoked.
2069
+
2066
2070
  @method sendEvent
2067
2071
  @for Ember
2068
2072
  @param obj
2069
2073
  @param {String} eventName
2070
- @param {Array} params
2071
- @param {Array} actions
2074
+ @param {Array} params Optional parameters for each listener.
2075
+ @param {Array} actions Optional array of actions (listeners).
2072
2076
  @return true
2073
2077
  */
2074
2078
  function sendEvent(obj, eventName, params, actions) {
@@ -2402,7 +2406,7 @@ var endPropertyChanges = Ember.endPropertyChanges = function() {
2402
2406
  @param {Function} callback
2403
2407
  @param [binding]
2404
2408
  */
2405
- Ember.changeProperties = function(cb, binding){
2409
+ Ember.changeProperties = function(cb, binding) {
2406
2410
  beginPropertyChanges();
2407
2411
  tryFinally(cb, endPropertyChanges, binding);
2408
2412
  };
@@ -2431,6 +2435,7 @@ var notifyObservers = function(obj, keyName) {
2431
2435
  sendEvent(obj, eventName, [obj, keyName]);
2432
2436
  }
2433
2437
  };
2438
+
2434
2439
  })();
2435
2440
 
2436
2441
 
@@ -2607,8 +2612,7 @@ Ember.trySetPath = Ember.deprecateFunc('trySetPath has been renamed to trySet',
2607
2612
  Map is mocked out to look like an Ember object, so you can do
2608
2613
  `Ember.Map.create()` for symmetry with other Ember classes.
2609
2614
  */
2610
- var get = Ember.get,
2611
- set = Ember.set,
2615
+ var set = Ember.set,
2612
2616
  guidFor = Ember.guidFor,
2613
2617
  indexOf = Ember.ArrayPolyfills.indexOf;
2614
2618
 
@@ -3134,13 +3138,14 @@ var changeProperties = Ember.changeProperties,
3134
3138
  @return self
3135
3139
  */
3136
3140
  Ember.setProperties = function(self, hash) {
3137
- changeProperties(function(){
3141
+ changeProperties(function() {
3138
3142
  for(var prop in hash) {
3139
3143
  if (hash.hasOwnProperty(prop)) { set(self, prop, hash[prop]); }
3140
3144
  }
3141
3145
  });
3142
3146
  return self;
3143
3147
  };
3148
+
3144
3149
  })();
3145
3150
 
3146
3151
 
@@ -3997,7 +4002,7 @@ ComputedPropertyPrototype.set = function(obj, keyName, value) {
3997
4002
  oldSuspended = this._suspended,
3998
4003
  hadCachedValue = false,
3999
4004
  cache = meta.cache,
4000
- cachedValue, ret;
4005
+ funcArgLength, cachedValue, ret;
4001
4006
 
4002
4007
  if (this._readOnly) {
4003
4008
  throw new Error('Cannot Set: ' + keyName + ' on: ' + obj.toString() );
@@ -4012,17 +4017,18 @@ ComputedPropertyPrototype.set = function(obj, keyName, value) {
4012
4017
  hadCachedValue = true;
4013
4018
  }
4014
4019
 
4015
- // Check if the CP has been wrapped
4016
- if (func.wrappedFunction) { func = func.wrappedFunction; }
4020
+ // Check if the CP has been wrapped. If if has, use the
4021
+ // length from the wrapped function.
4022
+ funcArgLength = (func.wrappedFunction ? func.wrappedFunction.length : func.length);
4017
4023
 
4018
4024
  // For backwards-compatibility with computed properties
4019
4025
  // that check for arguments.length === 2 to determine if
4020
4026
  // they are being get or set, only pass the old cached
4021
4027
  // value if the computed property opts into a third
4022
4028
  // argument.
4023
- if (func.length === 3) {
4029
+ if (funcArgLength === 3) {
4024
4030
  ret = func.call(obj, keyName, value, cachedValue);
4025
- } else if (func.length === 2) {
4031
+ } else if (funcArgLength === 2) {
4026
4032
  ret = func.call(obj, keyName, value);
4027
4033
  } else {
4028
4034
  Ember.defineProperty(obj, keyName, null, cachedValue);
@@ -4096,7 +4102,7 @@ Ember.computed = function(func) {
4096
4102
  func = a_slice.call(arguments, -1)[0];
4097
4103
  }
4098
4104
 
4099
- if ( typeof func !== "function" ) {
4105
+ if (typeof func !== "function") {
4100
4106
  throw new Error("Computed Property declared without a property function");
4101
4107
  }
4102
4108
 
@@ -4186,7 +4192,7 @@ registerComputed('notEmpty', function(dependentKey) {
4186
4192
  @for Ember
4187
4193
  @param {String} dependentKey
4188
4194
  @return {Ember.ComputedProperty} computed property which
4189
- rturns true if original value for property is null or undefined.
4195
+ returns true if original value for property is null or undefined.
4190
4196
  */
4191
4197
  registerComputed('none', function(dependentKey) {
4192
4198
  return Ember.isNone(get(this, dependentKey));
@@ -4357,6 +4363,23 @@ registerComputedWithProperties('map', function(properties) {
4357
4363
  });
4358
4364
 
4359
4365
  /**
4366
+ Creates a new property that is an alias for another property
4367
+ on an object. Calls to `get` or `set` this property behave as
4368
+ though they were called on the original property.
4369
+
4370
+ ```javascript
4371
+ Person = Ember.Object.extend({
4372
+ name: 'Alex Matchneer',
4373
+ nomen: Ember.computed.alias('name')
4374
+ });
4375
+
4376
+ alex = Person.create();
4377
+ alex.get('nomen'); // 'Alex Matchneer'
4378
+ alex.get('name'); // 'Alex Matchneer'
4379
+
4380
+ alex.set('nomen', '@machty');
4381
+ alex.get('name'); // '@machty'
4382
+ ```
4360
4383
  @method computed.alias
4361
4384
  @for Ember
4362
4385
  @param {String} dependentKey
@@ -4364,7 +4387,7 @@ registerComputedWithProperties('map', function(properties) {
4364
4387
  alias to the original value for property.
4365
4388
  */
4366
4389
  Ember.computed.alias = function(dependentKey) {
4367
- return Ember.computed(dependentKey, function(key, value){
4390
+ return Ember.computed(dependentKey, function(key, value) {
4368
4391
  if (arguments.length > 1) {
4369
4392
  set(this, dependentKey, value);
4370
4393
  return value;
@@ -4541,6 +4564,220 @@ Ember.removeBeforeObserver = function(obj, path, target, method) {
4541
4564
 
4542
4565
 
4543
4566
  (function() {
4567
+ define("backburner/queue",
4568
+ ["exports"],
4569
+ function(__exports__) {
4570
+ "use strict";
4571
+ function Queue(daq, name, options) {
4572
+ this.daq = daq;
4573
+ this.name = name;
4574
+ this.options = options;
4575
+ this._queue = [];
4576
+ }
4577
+
4578
+ Queue.prototype = {
4579
+ daq: null,
4580
+ name: null,
4581
+ options: null,
4582
+ _queue: null,
4583
+
4584
+ push: function(target, method, args, stack) {
4585
+ var queue = this._queue;
4586
+ queue.push(target, method, args, stack);
4587
+ return {queue: this, target: target, method: method};
4588
+ },
4589
+
4590
+ pushUnique: function(target, method, args, stack) {
4591
+ var queue = this._queue, currentTarget, currentMethod, i, l;
4592
+
4593
+ for (i = 0, l = queue.length; i < l; i += 4) {
4594
+ currentTarget = queue[i];
4595
+ currentMethod = queue[i+1];
4596
+
4597
+ if (currentTarget === target && currentMethod === method) {
4598
+ queue[i+2] = args; // replace args
4599
+ queue[i+3] = stack; // replace stack
4600
+ return {queue: this, target: target, method: method}; // TODO: test this code path
4601
+ }
4602
+ }
4603
+
4604
+ this._queue.push(target, method, args, stack);
4605
+ return {queue: this, target: target, method: method};
4606
+ },
4607
+
4608
+ // TODO: remove me, only being used for Ember.run.sync
4609
+ flush: function() {
4610
+ var queue = this._queue,
4611
+ options = this.options,
4612
+ before = options && options.before,
4613
+ after = options && options.after,
4614
+ target, method, args, stack, i, l = queue.length;
4615
+
4616
+ if (l && before) { before(); }
4617
+ for (i = 0; i < l; i += 4) {
4618
+ target = queue[i];
4619
+ method = queue[i+1];
4620
+ args = queue[i+2];
4621
+ stack = queue[i+3]; // Debugging assistance
4622
+
4623
+ // TODO: error handling
4624
+ if (args && args.length > 0) {
4625
+ method.apply(target, args);
4626
+ } else {
4627
+ method.call(target);
4628
+ }
4629
+ }
4630
+ if (l && after) { after(); }
4631
+
4632
+ // check if new items have been added
4633
+ if (queue.length > l) {
4634
+ this._queue = queue.slice(l);
4635
+ this.flush();
4636
+ } else {
4637
+ this._queue.length = 0;
4638
+ }
4639
+ },
4640
+
4641
+ cancel: function(actionToCancel) {
4642
+ var queue = this._queue, currentTarget, currentMethod, i, l;
4643
+
4644
+ for (i = 0, l = queue.length; i < l; i += 4) {
4645
+ currentTarget = queue[i];
4646
+ currentMethod = queue[i+1];
4647
+
4648
+ if (currentTarget === actionToCancel.target && currentMethod === actionToCancel.method) {
4649
+ queue.splice(i, 4);
4650
+ return true;
4651
+ }
4652
+ }
4653
+
4654
+ // if not found in current queue
4655
+ // could be in the queue that is being flushed
4656
+ queue = this._queueBeingFlushed;
4657
+ if (!queue) {
4658
+ return;
4659
+ }
4660
+ for (i = 0, l = queue.length; i < l; i += 4) {
4661
+ currentTarget = queue[i];
4662
+ currentMethod = queue[i+1];
4663
+
4664
+ if (currentTarget === actionToCancel.target && currentMethod === actionToCancel.method) {
4665
+ // don't mess with array during flush
4666
+ // just nullify the method
4667
+ queue[i+1] = null;
4668
+ return true;
4669
+ }
4670
+ }
4671
+ }
4672
+ };
4673
+
4674
+
4675
+ __exports__.Queue = Queue;
4676
+ });
4677
+
4678
+ define("backburner/deferred_action_queues",
4679
+ ["backburner/queue","exports"],
4680
+ function(__dependency1__, __exports__) {
4681
+ "use strict";
4682
+ var Queue = __dependency1__.Queue;
4683
+
4684
+ function DeferredActionQueues(queueNames, options) {
4685
+ var queues = this.queues = {};
4686
+ this.queueNames = queueNames = queueNames || [];
4687
+
4688
+ var queueName;
4689
+ for (var i = 0, l = queueNames.length; i < l; i++) {
4690
+ queueName = queueNames[i];
4691
+ queues[queueName] = new Queue(this, queueName, options[queueName]);
4692
+ }
4693
+ }
4694
+
4695
+ DeferredActionQueues.prototype = {
4696
+ queueNames: null,
4697
+ queues: null,
4698
+
4699
+ schedule: function(queueName, target, method, args, onceFlag, stack) {
4700
+ var queues = this.queues,
4701
+ queue = queues[queueName];
4702
+
4703
+ if (!queue) { throw new Error("You attempted to schedule an action in a queue (" + queueName + ") that doesn't exist"); }
4704
+
4705
+ if (onceFlag) {
4706
+ return queue.pushUnique(target, method, args, stack);
4707
+ } else {
4708
+ return queue.push(target, method, args, stack);
4709
+ }
4710
+ },
4711
+
4712
+ flush: function() {
4713
+ var queues = this.queues,
4714
+ queueNames = this.queueNames,
4715
+ queueName, queue, queueItems, priorQueueNameIndex,
4716
+ queueNameIndex = 0, numberOfQueues = queueNames.length;
4717
+
4718
+ outerloop:
4719
+ while (queueNameIndex < numberOfQueues) {
4720
+ queueName = queueNames[queueNameIndex];
4721
+ queue = queues[queueName];
4722
+ queueItems = queue._queueBeingFlushed = queue._queue.slice();
4723
+ queue._queue = [];
4724
+
4725
+ var options = queue.options,
4726
+ before = options && options.before,
4727
+ after = options && options.after,
4728
+ target, method, args, stack,
4729
+ queueIndex = 0, numberOfQueueItems = queueItems.length;
4730
+
4731
+ if (numberOfQueueItems && before) { before(); }
4732
+ while (queueIndex < numberOfQueueItems) {
4733
+ target = queueItems[queueIndex];
4734
+ method = queueItems[queueIndex+1];
4735
+ args = queueItems[queueIndex+2];
4736
+ stack = queueItems[queueIndex+3]; // Debugging assistance
4737
+
4738
+ if (typeof method === 'string') { method = target[method]; }
4739
+
4740
+ // method could have been nullified / canceled during flush
4741
+ if (method) {
4742
+ // TODO: error handling
4743
+ if (args && args.length > 0) {
4744
+ method.apply(target, args);
4745
+ } else {
4746
+ method.call(target);
4747
+ }
4748
+ }
4749
+
4750
+ queueIndex += 4;
4751
+ }
4752
+ queue._queueBeingFlushed = null;
4753
+ if (numberOfQueueItems && after) { after(); }
4754
+
4755
+ if ((priorQueueNameIndex = indexOfPriorQueueWithActions(this, queueNameIndex)) !== -1) {
4756
+ queueNameIndex = priorQueueNameIndex;
4757
+ continue outerloop;
4758
+ }
4759
+
4760
+ queueNameIndex++;
4761
+ }
4762
+ }
4763
+ };
4764
+
4765
+ function indexOfPriorQueueWithActions(daq, currentQueueIndex) {
4766
+ var queueName, queue;
4767
+
4768
+ for (var i = 0, l = currentQueueIndex; i <= l; i++) {
4769
+ queueName = daq.queueNames[i];
4770
+ queue = daq.queues[queueName];
4771
+ if (queue._queue.length) { return i; }
4772
+ }
4773
+
4774
+ return -1;
4775
+ }
4776
+
4777
+
4778
+ __exports__.DeferredActionQueues = DeferredActionQueues;
4779
+ });
4780
+
4544
4781
  define("backburner",
4545
4782
  ["backburner/deferred_action_queues","exports"],
4546
4783
  function(__dependency1__, __exports__) {
@@ -4549,9 +4786,11 @@ define("backburner",
4549
4786
 
4550
4787
  var slice = [].slice,
4551
4788
  pop = [].pop,
4789
+ throttlers = [],
4552
4790
  debouncees = [],
4553
4791
  timers = [],
4554
- autorun, laterTimer, laterTimerExpiresAt;
4792
+ autorun, laterTimer, laterTimerExpiresAt,
4793
+ global = this;
4555
4794
 
4556
4795
  function Backburner(queueNames, options) {
4557
4796
  this.queueNames = queueNames;
@@ -4708,7 +4947,7 @@ define("backburner",
4708
4947
  clearTimeout(laterTimer);
4709
4948
  laterTimer = null;
4710
4949
  }
4711
- laterTimer = window.setTimeout(function() {
4950
+ laterTimer = global.setTimeout(function() {
4712
4951
  executeTimers(self);
4713
4952
  laterTimer = null;
4714
4953
  laterTimerExpiresAt = null;
@@ -4718,53 +4957,101 @@ define("backburner",
4718
4957
  return fn;
4719
4958
  },
4720
4959
 
4721
- debounce: function(target, method /* , args, wait */) {
4960
+ throttle: function(target, method /* , args, wait */) {
4722
4961
  var self = this,
4723
4962
  args = arguments,
4724
4963
  wait = pop.call(args),
4725
- debouncee;
4964
+ throttler;
4726
4965
 
4727
- for (var i = 0, l = debouncees.length; i < l; i++) {
4728
- debouncee = debouncees[i];
4729
- if (debouncee[0] === target && debouncee[1] === method) { return; } // do nothing
4966
+ for (var i = 0, l = throttlers.length; i < l; i++) {
4967
+ throttler = throttlers[i];
4968
+ if (throttler[0] === target && throttler[1] === method) { return; } // do nothing
4730
4969
  }
4731
4970
 
4732
- var timer = window.setTimeout(function() {
4971
+ var timer = global.setTimeout(function() {
4733
4972
  self.run.apply(self, args);
4734
4973
 
4735
- // remove debouncee
4974
+ // remove throttler
4736
4975
  var index = -1;
4737
- for (var i = 0, l = debouncees.length; i < l; i++) {
4738
- debouncee = debouncees[i];
4739
- if (debouncee[0] === target && debouncee[1] === method) {
4976
+ for (var i = 0, l = throttlers.length; i < l; i++) {
4977
+ throttler = throttlers[i];
4978
+ if (throttler[0] === target && throttler[1] === method) {
4740
4979
  index = i;
4741
4980
  break;
4742
4981
  }
4743
4982
  }
4744
4983
 
4745
- if (index > -1) { debouncees.splice(index, 1); }
4984
+ if (index > -1) { throttlers.splice(index, 1); }
4746
4985
  }, wait);
4747
4986
 
4748
- debouncees.push([target, method, timer]);
4987
+ throttlers.push([target, method, timer]);
4749
4988
  },
4750
4989
 
4751
- cancelTimers: function() {
4752
- for (var i = 0, l = debouncees.length; i < l; i++) {
4753
- clearTimeout(debouncees[i][2]);
4754
- }
4755
- debouncees = [];
4990
+ debounce: function(target, method /* , args, wait, [immediate] */) {
4991
+ var self = this,
4992
+ args = arguments,
4993
+ immediate = pop.call(args),
4994
+ wait,
4995
+ index,
4996
+ debouncee;
4756
4997
 
4757
- if (laterTimer) {
4758
- clearTimeout(laterTimer);
4759
- laterTimer = null;
4998
+ if (typeof immediate === "number") {
4999
+ wait = immediate;
5000
+ immediate = false;
5001
+ } else {
5002
+ wait = pop.call(args);
4760
5003
  }
4761
- timers = [];
4762
5004
 
4763
- if (autorun) {
4764
- clearTimeout(autorun);
4765
- autorun = null;
5005
+ // Remove debouncee
5006
+ index = findDebouncee(target, method);
5007
+
5008
+ if (index !== -1) {
5009
+ debouncee = debouncees[index];
5010
+ debouncees.splice(index, 1);
5011
+ clearTimeout(debouncee[2]);
4766
5012
  }
4767
- },
5013
+
5014
+ var timer = window.setTimeout(function() {
5015
+ if (!immediate) {
5016
+ self.run.apply(self, args);
5017
+ }
5018
+ index = findDebouncee(target, method);
5019
+ if (index) {
5020
+ debouncees.splice(index, 1);
5021
+ }
5022
+ }, wait);
5023
+
5024
+ if (immediate && index === -1) {
5025
+ self.run.apply(self, args);
5026
+ }
5027
+
5028
+ debouncees.push([target, method, timer]);
5029
+ },
5030
+
5031
+ cancelTimers: function() {
5032
+ var i, len;
5033
+
5034
+ for (i = 0, len = throttlers.length; i < len; i++) {
5035
+ clearTimeout(throttlers[i][2]);
5036
+ }
5037
+ throttlers = [];
5038
+
5039
+ for (i = 0, len = debouncees.length; i < len; i++) {
5040
+ clearTimeout(debouncees[i][2]);
5041
+ }
5042
+ debouncees = [];
5043
+
5044
+ if (laterTimer) {
5045
+ clearTimeout(laterTimer);
5046
+ laterTimer = null;
5047
+ }
5048
+ timers = [];
5049
+
5050
+ if (autorun) {
5051
+ clearTimeout(autorun);
5052
+ autorun = null;
5053
+ }
5054
+ },
4768
5055
 
4769
5056
  hasTimers: function() {
4770
5057
  return !!timers.length || autorun;
@@ -4792,7 +5079,7 @@ define("backburner",
4792
5079
 
4793
5080
  function createAutorun(backburner) {
4794
5081
  backburner.begin();
4795
- autorun = window.setTimeout(function() {
5082
+ autorun = global.setTimeout(function() {
4796
5083
  backburner.end();
4797
5084
  autorun = null;
4798
5085
  });
@@ -4817,7 +5104,7 @@ define("backburner",
4817
5104
  });
4818
5105
 
4819
5106
  if (timers.length) {
4820
- laterTimer = window.setTimeout(function() {
5107
+ laterTimer = global.setTimeout(function() {
4821
5108
  executeTimers(self);
4822
5109
  laterTimer = null;
4823
5110
  laterTimerExpiresAt = null;
@@ -4826,222 +5113,23 @@ define("backburner",
4826
5113
  }
4827
5114
  }
4828
5115
 
5116
+ function findDebouncee(target, method) {
5117
+ var debouncee,
5118
+ index = -1;
4829
5119
 
4830
- __exports__.Backburner = Backburner;
4831
- });
4832
-
4833
- define("backburner/deferred_action_queues",
4834
- ["backburner/queue","exports"],
4835
- function(__dependency1__, __exports__) {
4836
- "use strict";
4837
- var Queue = __dependency1__.Queue;
4838
-
4839
- function DeferredActionQueues(queueNames, options) {
4840
- var queues = this.queues = {};
4841
- this.queueNames = queueNames = queueNames || [];
4842
-
4843
- var queueName;
4844
- for (var i = 0, l = queueNames.length; i < l; i++) {
4845
- queueName = queueNames[i];
4846
- queues[queueName] = new Queue(this, queueName, options[queueName]);
4847
- }
4848
- }
4849
-
4850
- DeferredActionQueues.prototype = {
4851
- queueNames: null,
4852
- queues: null,
4853
-
4854
- schedule: function(queueName, target, method, args, onceFlag, stack) {
4855
- var queues = this.queues,
4856
- queue = queues[queueName];
4857
-
4858
- if (!queue) { throw new Error("You attempted to schedule an action in a queue (" + queueName + ") that doesn't exist"); }
4859
-
4860
- if (onceFlag) {
4861
- return queue.pushUnique(target, method, args, stack);
4862
- } else {
4863
- return queue.push(target, method, args, stack);
4864
- }
4865
- },
4866
-
4867
- flush: function() {
4868
- var queues = this.queues,
4869
- queueNames = this.queueNames,
4870
- queueName, queue, queueItems, priorQueueNameIndex,
4871
- queueNameIndex = 0, numberOfQueues = queueNames.length;
4872
-
4873
- outerloop:
4874
- while (queueNameIndex < numberOfQueues) {
4875
- queueName = queueNames[queueNameIndex];
4876
- queue = queues[queueName];
4877
- queueItems = queue._queueBeingFlushed = queue._queue.slice();
4878
- queue._queue = [];
4879
-
4880
- var options = queue.options,
4881
- before = options && options.before,
4882
- after = options && options.after,
4883
- target, method, args, stack,
4884
- queueIndex = 0, numberOfQueueItems = queueItems.length;
4885
-
4886
- if (numberOfQueueItems && before) { before(); }
4887
- while (queueIndex < numberOfQueueItems) {
4888
- target = queueItems[queueIndex];
4889
- method = queueItems[queueIndex+1];
4890
- args = queueItems[queueIndex+2];
4891
- stack = queueItems[queueIndex+3]; // Debugging assistance
4892
-
4893
- if (typeof method === 'string') { method = target[method]; }
4894
-
4895
- // method could have been nullified / canceled during flush
4896
- if (method) {
4897
- // TODO: error handling
4898
- if (args && args.length > 0) {
4899
- method.apply(target, args);
4900
- } else {
4901
- method.call(target);
4902
- }
4903
- }
4904
-
4905
- queueIndex += 4;
4906
- }
4907
- queue._queueBeingFlushed = null;
4908
- if (numberOfQueueItems && after) { after(); }
4909
-
4910
- if ((priorQueueNameIndex = indexOfPriorQueueWithActions(this, queueNameIndex)) !== -1) {
4911
- queueNameIndex = priorQueueNameIndex;
4912
- continue outerloop;
4913
- }
4914
-
4915
- queueNameIndex++;
5120
+ for (var i = 0, l = debouncees.length; i < l; i++) {
5121
+ debouncee = debouncees[i];
5122
+ if (debouncee[0] === target && debouncee[1] === method) {
5123
+ index = i;
5124
+ break;
4916
5125
  }
4917
5126
  }
4918
- };
4919
-
4920
- function indexOfPriorQueueWithActions(daq, currentQueueIndex) {
4921
- var queueName, queue;
4922
5127
 
4923
- for (var i = 0, l = currentQueueIndex; i <= l; i++) {
4924
- queueName = daq.queueNames[i];
4925
- queue = daq.queues[queueName];
4926
- if (queue._queue.length) { return i; }
4927
- }
4928
-
4929
- return -1;
5128
+ return index;
4930
5129
  }
4931
5130
 
4932
5131
 
4933
- __exports__.DeferredActionQueues = DeferredActionQueues;
4934
- });
4935
-
4936
- define("backburner/queue",
4937
- ["exports"],
4938
- function(__exports__) {
4939
- "use strict";
4940
- function Queue(daq, name, options) {
4941
- this.daq = daq;
4942
- this.name = name;
4943
- this.options = options;
4944
- this._queue = [];
4945
- }
4946
-
4947
- Queue.prototype = {
4948
- daq: null,
4949
- name: null,
4950
- options: null,
4951
- _queue: null,
4952
-
4953
- push: function(target, method, args, stack) {
4954
- var queue = this._queue;
4955
- queue.push(target, method, args, stack);
4956
- return {queue: this, target: target, method: method};
4957
- },
4958
-
4959
- pushUnique: function(target, method, args, stack) {
4960
- var queue = this._queue, currentTarget, currentMethod, i, l;
4961
-
4962
- for (i = 0, l = queue.length; i < l; i += 4) {
4963
- currentTarget = queue[i];
4964
- currentMethod = queue[i+1];
4965
-
4966
- if (currentTarget === target && currentMethod === method) {
4967
- queue[i+2] = args; // replace args
4968
- queue[i+3] = stack; // replace stack
4969
- return {queue: this, target: target, method: method}; // TODO: test this code path
4970
- }
4971
- }
4972
-
4973
- this._queue.push(target, method, args, stack);
4974
- return {queue: this, target: target, method: method};
4975
- },
4976
-
4977
- // TODO: remove me, only being used for Ember.run.sync
4978
- flush: function() {
4979
- var queue = this._queue,
4980
- options = this.options,
4981
- before = options && options.before,
4982
- after = options && options.after,
4983
- target, method, args, stack, i, l = queue.length;
4984
-
4985
- if (l && before) { before(); }
4986
- for (i = 0; i < l; i += 4) {
4987
- target = queue[i];
4988
- method = queue[i+1];
4989
- args = queue[i+2];
4990
- stack = queue[i+3]; // Debugging assistance
4991
-
4992
- // TODO: error handling
4993
- if (args && args.length > 0) {
4994
- method.apply(target, args);
4995
- } else {
4996
- method.call(target);
4997
- }
4998
- }
4999
- if (l && after) { after(); }
5000
-
5001
- // check if new items have been added
5002
- if (queue.length > l) {
5003
- this._queue = queue.slice(l);
5004
- this.flush();
5005
- } else {
5006
- this._queue.length = 0;
5007
- }
5008
- },
5009
-
5010
- cancel: function(actionToCancel) {
5011
- var queue = this._queue, currentTarget, currentMethod, i, l;
5012
-
5013
- for (i = 0, l = queue.length; i < l; i += 4) {
5014
- currentTarget = queue[i];
5015
- currentMethod = queue[i+1];
5016
-
5017
- if (currentTarget === actionToCancel.target && currentMethod === actionToCancel.method) {
5018
- queue.splice(i, 4);
5019
- return true;
5020
- }
5021
- }
5022
-
5023
- // if not found in current queue
5024
- // could be in the queue that is being flushed
5025
- queue = this._queueBeingFlushed;
5026
- if (!queue) {
5027
- return;
5028
- }
5029
- for (i = 0, l = queue.length; i < l; i += 4) {
5030
- currentTarget = queue[i];
5031
- currentMethod = queue[i+1];
5032
-
5033
- if (currentTarget === actionToCancel.target && currentMethod === actionToCancel.method) {
5034
- // don't mess with array during flush
5035
- // just nullify the method
5036
- queue[i+1] = null;
5037
- return true;
5038
- }
5039
- }
5040
- }
5041
- };
5042
-
5043
-
5044
- __exports__.Queue = Queue;
5132
+ __exports__.Backburner = Backburner;
5045
5133
  });
5046
5134
  })();
5047
5135
 
@@ -5083,7 +5171,7 @@ var Backburner = requireModule('backburner').Backburner,
5083
5171
  call.
5084
5172
 
5085
5173
  ```javascript
5086
- Ember.run(function(){
5174
+ Ember.run(function() {
5087
5175
  // code to be execute within a RunLoop
5088
5176
  });
5089
5177
  ```
@@ -5126,7 +5214,7 @@ Ember.run = function(target, method) {
5126
5214
  If invoked when not within a run loop:
5127
5215
 
5128
5216
  ```javascript
5129
- Ember.run.join(function(){
5217
+ Ember.run.join(function() {
5130
5218
  // creates a new run-loop
5131
5219
  });
5132
5220
  ```
@@ -5134,9 +5222,9 @@ Ember.run = function(target, method) {
5134
5222
  Alternatively, if called within an existing run loop:
5135
5223
 
5136
5224
  ```javascript
5137
- Ember.run(function(){
5225
+ Ember.run(function() {
5138
5226
  // creates a new run-loop
5139
- Ember.run.join(function(){
5227
+ Ember.run.join(function() {
5140
5228
  // joins with the existing run-loop, and queues for invocation on
5141
5229
  // the existing run-loops action queue.
5142
5230
  });
@@ -5229,12 +5317,12 @@ Ember.run.end = function() {
5229
5317
  the `Ember.run.queues` property.
5230
5318
 
5231
5319
  ```javascript
5232
- Ember.run.schedule('sync', this, function(){
5320
+ Ember.run.schedule('sync', this, function() {
5233
5321
  // this will be executed in the first RunLoop queue, when bindings are synced
5234
5322
  console.log("scheduled on sync queue");
5235
5323
  });
5236
5324
 
5237
- Ember.run.schedule('actions', this, function(){
5325
+ Ember.run.schedule('actions', this, function() {
5238
5326
  // this will be executed in the 'actions' queue, after bindings have synced.
5239
5327
  console.log("scheduled on actions queue");
5240
5328
  });
@@ -5302,7 +5390,7 @@ Ember.run.sync = function() {
5302
5390
  together, which is often more efficient than using a real setTimeout.
5303
5391
 
5304
5392
  ```javascript
5305
- Ember.run.later(myContext, function(){
5393
+ Ember.run.later(myContext, function() {
5306
5394
  // code here will execute within a RunLoop in about 500ms with this == myContext
5307
5395
  }, 500);
5308
5396
  ```
@@ -5350,11 +5438,11 @@ Ember.run.once = function(target, method) {
5350
5438
  calls.
5351
5439
 
5352
5440
  ```javascript
5353
- Ember.run(function(){
5441
+ Ember.run(function() {
5354
5442
  var sayHi = function() { console.log('hi'); }
5355
5443
  Ember.run.scheduleOnce('afterRender', myContext, sayHi);
5356
5444
  Ember.run.scheduleOnce('afterRender', myContext, sayHi);
5357
- // doFoo will only be executed once, in the afterRender queue of the RunLoop
5445
+ // sayHi will only be executed once, in the afterRender queue of the RunLoop
5358
5446
  });
5359
5447
  ```
5360
5448
 
@@ -5395,7 +5483,7 @@ Ember.run.scheduleOnce = function(queue, target, method) {
5395
5483
  `Ember.run.later` with a wait time of 1ms.
5396
5484
 
5397
5485
  ```javascript
5398
- Ember.run.next(myContext, function(){
5486
+ Ember.run.next(myContext, function() {
5399
5487
  // code to be executed in the next run loop, which will be scheduled after the current one
5400
5488
  });
5401
5489
  ```
@@ -5457,17 +5545,17 @@ Ember.run.next = function() {
5457
5545
  `Ember.run.once()`, or `Ember.run.next()`.
5458
5546
 
5459
5547
  ```javascript
5460
- var runNext = Ember.run.next(myContext, function(){
5548
+ var runNext = Ember.run.next(myContext, function() {
5461
5549
  // will not be executed
5462
5550
  });
5463
5551
  Ember.run.cancel(runNext);
5464
5552
 
5465
- var runLater = Ember.run.later(myContext, function(){
5553
+ var runLater = Ember.run.later(myContext, function() {
5466
5554
  // will not be executed
5467
5555
  }, 500);
5468
5556
  Ember.run.cancel(runLater);
5469
5557
 
5470
- var runOnce = Ember.run.once(myContext, function(){
5558
+ var runOnce = Ember.run.once(myContext, function() {
5471
5559
  // will not be executed
5472
5560
  });
5473
5561
  Ember.run.cancel(runOnce);
@@ -5482,8 +5570,15 @@ Ember.run.cancel = function(timer) {
5482
5570
  };
5483
5571
 
5484
5572
  /**
5485
- Execute the passed method in a specified amount of time, reset timer
5486
- upon additional calls.
5573
+ Delay calling the target method until the debounce period has elapsed
5574
+ with no additional debounce calls. If `debounce` is called again before
5575
+ the specified time has elapsed, the timer is reset and the entire period
5576
+ must pass again before the target method is called.
5577
+
5578
+ This method should be used when an event may be called multiple times
5579
+ but the action should only be called once when the event is done firing.
5580
+ A common example is for scroll events where you only want updates to
5581
+ happen once scrolling has ceased.
5487
5582
 
5488
5583
  ```javascript
5489
5584
  var myFunc = function() { console.log(this.name + ' ran.'); };
@@ -5507,12 +5602,50 @@ Ember.run.cancel = function(timer) {
5507
5602
  then it will be looked up on the passed target.
5508
5603
  @param {Object} [args*] Optional arguments to pass to the timeout.
5509
5604
  @param {Number} wait Number of milliseconds to wait.
5605
+ @param {Boolean} immediate Trigger the function on the leading instead of the trailing edge of the wait interval.
5510
5606
  @return {void}
5511
5607
  */
5512
5608
  Ember.run.debounce = function() {
5513
5609
  return backburner.debounce.apply(backburner, arguments);
5514
5610
  };
5515
5611
 
5612
+ /**
5613
+ Ensure that the target method is never called more frequently than
5614
+ the specified spacing period.
5615
+
5616
+ ```javascript
5617
+ var myFunc = function() { console.log(this.name + ' ran.'); };
5618
+ var myContext = {name: 'throttle'};
5619
+
5620
+ Ember.run.throttle(myContext, myFunc, 150);
5621
+
5622
+ // 50ms passes
5623
+ Ember.run.throttle(myContext, myFunc, 150);
5624
+
5625
+ // 50ms passes
5626
+ Ember.run.throttle(myContext, myFunc, 150);
5627
+
5628
+ // 50ms passes
5629
+ Ember.run.throttle(myContext, myFunc, 150);
5630
+
5631
+ // 150ms passes
5632
+ // myFunc is invoked with context myContext
5633
+ // console logs 'throttle ran.' twice, 150ms apart.
5634
+ ```
5635
+
5636
+ @method throttle
5637
+ @param {Object} [target] target of method to invoke
5638
+ @param {Function|String} method The method to invoke.
5639
+ May be a function or a string. If you pass a string
5640
+ then it will be looked up on the passed target.
5641
+ @param {Object} [args*] Optional arguments to pass to the timeout.
5642
+ @param {Number} spacing Number of milliseconds to space out requests.
5643
+ @return {void}
5644
+ */
5645
+ Ember.run.throttle = function() {
5646
+ return backburner.throttle.apply(backburner, arguments);
5647
+ };
5648
+
5516
5649
  // Make sure it's not an autorun during testing
5517
5650
  function checkAutoRun() {
5518
5651
  if (!Ember.run.currentRunLoop) {
@@ -6003,7 +6136,8 @@ Ember.oneWay = function(obj, to, from) {
6003
6136
 
6004
6137
  (function() {
6005
6138
  /**
6006
- @module ember-metal
6139
+ @module ember
6140
+ @submodule ember-metal
6007
6141
  */
6008
6142
 
6009
6143
  var Mixin, REQUIRED, Alias,
@@ -6379,38 +6513,6 @@ Mixin.finishPartial = finishPartial;
6379
6513
  Ember.anyUnprocessedMixins = false;
6380
6514
 
6381
6515
  /**
6382
- Creates an instance of a class. Accepts either no arguments, or an object
6383
- containing values to initialize the newly instantiated object with.
6384
-
6385
- ```javascript
6386
- App.Person = Ember.Object.extend({
6387
- helloWorld: function() {
6388
- alert("Hi, my name is " + this.get('name'));
6389
- }
6390
- });
6391
-
6392
- var tom = App.Person.create({
6393
- name: 'Tom Dale'
6394
- });
6395
-
6396
- tom.helloWorld(); // alerts "Hi, my name is Tom Dale".
6397
- ```
6398
-
6399
- `create` will call the `init` function if defined during
6400
- `Ember.AnyObject.extend`
6401
-
6402
- If no arguments are passed to `create`, it will not set values to the new
6403
- instance during initialization:
6404
-
6405
- ```javascript
6406
- var noName = App.Person.create();
6407
- noName.helloWorld(); // alerts undefined
6408
- ```
6409
-
6410
- NOTE: For performance reasons, you cannot declare methods or computed
6411
- properties during `create`. You should instead declare methods and computed
6412
- properties when using `extend`.
6413
-
6414
6516
  @method create
6415
6517
  @static
6416
6518
  @param arguments*
@@ -6570,7 +6672,7 @@ Alias.prototype = new Ember.Descriptor();
6570
6672
  App.PaintSample = Ember.Object.extend({
6571
6673
  color: 'red',
6572
6674
  colour: Ember.alias('color'),
6573
- name: function(){
6675
+ name: function() {
6574
6676
  return "Zed";
6575
6677
  },
6576
6678
  moniker: Ember.alias("name")
@@ -6598,7 +6700,7 @@ Ember.alias = Ember.deprecateFunc("Ember.alias is deprecated. Please use Ember.a
6598
6700
 
6599
6701
  ```javascript
6600
6702
  App.Person = Ember.Object.extend({
6601
- name: function(){
6703
+ name: function() {
6602
6704
  return 'Tomhuda Katzdale';
6603
6705
  },
6604
6706
  moniker: Ember.aliasMethod('name')
@@ -6667,7 +6769,7 @@ Ember.immediateObserver = function() {
6667
6769
  }.observesBefore('content.value'),
6668
6770
  valueDidChange: function(obj, keyName, value) {
6669
6771
  // only run if updating a value already in the DOM
6670
- if(this.get('state') === 'inDOM') {
6772
+ if (this.get('state') === 'inDOM') {
6671
6773
  var color = value > this.changingFrom ? 'green' : 'red';
6672
6774
  // logic
6673
6775
  }
@@ -6703,65 +6805,82 @@ Ember Metal
6703
6805
 
6704
6806
  (function() {
6705
6807
  define("rsvp/all",
6706
- ["rsvp/defer","exports"],
6808
+ ["rsvp/promise","exports"],
6707
6809
  function(__dependency1__, __exports__) {
6708
6810
  "use strict";
6709
- var defer = __dependency1__.defer;
6811
+ var Promise = __dependency1__.Promise;
6812
+ /* global toString */
6710
6813
 
6711
- function all(promises) {
6712
- var results = [], deferred = defer(), remaining = promises.length;
6713
6814
 
6714
- if (remaining === 0) {
6715
- deferred.resolve([]);
6815
+ function all(promises) {
6816
+ if (Object.prototype.toString.call(promises) !== "[object Array]") {
6817
+ throw new TypeError('You must pass an array to all.');
6716
6818
  }
6717
6819
 
6718
- var resolver = function(index) {
6719
- return function(value) {
6720
- resolveAll(index, value);
6721
- };
6722
- };
6820
+ return new Promise(function(resolve, reject) {
6821
+ var results = [], remaining = promises.length,
6822
+ promise;
6723
6823
 
6724
- var resolveAll = function(index, value) {
6725
- results[index] = value;
6726
- if (--remaining === 0) {
6727
- deferred.resolve(results);
6824
+ if (remaining === 0) {
6825
+ resolve([]);
6728
6826
  }
6729
- };
6730
6827
 
6731
- var rejectAll = function(error) {
6732
- deferred.reject(error);
6733
- };
6828
+ function resolver(index) {
6829
+ return function(value) {
6830
+ resolveAll(index, value);
6831
+ };
6832
+ }
6734
6833
 
6735
- for (var i = 0; i < promises.length; i++) {
6736
- if (promises[i] && typeof promises[i].then === 'function') {
6737
- promises[i].then(resolver(i), rejectAll);
6738
- } else {
6739
- resolveAll(i, promises[i]);
6834
+ function resolveAll(index, value) {
6835
+ results[index] = value;
6836
+ if (--remaining === 0) {
6837
+ resolve(results);
6838
+ }
6740
6839
  }
6741
- }
6742
- return deferred.promise;
6840
+
6841
+ for (var i = 0; i < promises.length; i++) {
6842
+ promise = promises[i];
6843
+
6844
+ if (promise && typeof promise.then === 'function') {
6845
+ promise.then(resolver(i), reject);
6846
+ } else {
6847
+ resolveAll(i, promise);
6848
+ }
6849
+ }
6850
+ });
6743
6851
  }
6744
6852
 
6853
+
6745
6854
  __exports__.all = all;
6746
6855
  });
6747
-
6748
6856
  define("rsvp/async",
6749
6857
  ["exports"],
6750
6858
  function(__exports__) {
6751
6859
  "use strict";
6752
6860
  var browserGlobal = (typeof window !== 'undefined') ? window : {};
6753
-
6754
6861
  var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
6755
6862
  var async;
6756
6863
 
6757
- if (typeof process !== 'undefined' &&
6758
- {}.toString.call(process) === '[object process]') {
6759
- async = function(callback, binding) {
6864
+ // old node
6865
+ function useNextTick() {
6866
+ return function(callback, arg) {
6760
6867
  process.nextTick(function() {
6761
- callback.call(binding);
6868
+ callback(arg);
6762
6869
  });
6763
6870
  };
6764
- } else if (BrowserMutationObserver) {
6871
+ }
6872
+
6873
+ // node >= 0.10.x
6874
+ function useSetImmediate() {
6875
+ return function(callback, arg) {
6876
+ /* global setImmediate */
6877
+ setImmediate(function(){
6878
+ callback(arg);
6879
+ });
6880
+ };
6881
+ }
6882
+
6883
+ function useMutationObserver() {
6765
6884
  var queue = [];
6766
6885
 
6767
6886
  var observer = new BrowserMutationObserver(function() {
@@ -6769,8 +6888,8 @@ define("rsvp/async",
6769
6888
  queue = [];
6770
6889
 
6771
6890
  toProcess.forEach(function(tuple) {
6772
- var callback = tuple[0], binding = tuple[1];
6773
- callback.call(binding);
6891
+ var callback = tuple[0], arg= tuple[1];
6892
+ callback(arg);
6774
6893
  });
6775
6894
  });
6776
6895
 
@@ -6781,24 +6900,35 @@ define("rsvp/async",
6781
6900
  window.addEventListener('unload', function(){
6782
6901
  observer.disconnect();
6783
6902
  observer = null;
6784
- });
6903
+ }, false);
6785
6904
 
6786
- async = function(callback, binding) {
6787
- queue.push([callback, binding]);
6905
+ return function(callback, arg) {
6906
+ queue.push([callback, arg]);
6788
6907
  element.setAttribute('drainQueue', 'drainQueue');
6789
6908
  };
6790
- } else {
6791
- async = function(callback, binding) {
6909
+ }
6910
+
6911
+ function useSetTimeout() {
6912
+ return function(callback, arg) {
6792
6913
  setTimeout(function() {
6793
- callback.call(binding);
6914
+ callback(arg);
6794
6915
  }, 1);
6795
6916
  };
6796
6917
  }
6797
6918
 
6919
+ if (typeof setImmediate === 'function') {
6920
+ async = useSetImmediate();
6921
+ } else if (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]') {
6922
+ async = useNextTick();
6923
+ } else if (BrowserMutationObserver) {
6924
+ async = useMutationObserver();
6925
+ } else {
6926
+ async = useSetTimeout();
6927
+ }
6928
+
6798
6929
 
6799
6930
  __exports__.async = async;
6800
6931
  });
6801
-
6802
6932
  define("rsvp/config",
6803
6933
  ["rsvp/async","exports"],
6804
6934
  function(__dependency1__, __exports__) {
@@ -6808,9 +6938,9 @@ define("rsvp/config",
6808
6938
  var config = {};
6809
6939
  config.async = async;
6810
6940
 
6941
+
6811
6942
  __exports__.config = config;
6812
6943
  });
6813
-
6814
6944
  define("rsvp/defer",
6815
6945
  ["rsvp/promise","exports"],
6816
6946
  function(__dependency1__, __exports__) {
@@ -6818,20 +6948,24 @@ define("rsvp/defer",
6818
6948
  var Promise = __dependency1__.Promise;
6819
6949
 
6820
6950
  function defer() {
6821
- var deferred = {};
6951
+ var deferred = {
6952
+ // pre-allocate shape
6953
+ resolve: undefined,
6954
+ reject: undefined,
6955
+ promise: undefined
6956
+ };
6822
6957
 
6823
- var promise = new Promise(function(resolve, reject) {
6958
+ deferred.promise = new Promise(function(resolve, reject) {
6824
6959
  deferred.resolve = resolve;
6825
6960
  deferred.reject = reject;
6826
6961
  });
6827
6962
 
6828
- deferred.promise = promise;
6829
6963
  return deferred;
6830
6964
  }
6831
6965
 
6966
+
6832
6967
  __exports__.defer = defer;
6833
6968
  });
6834
-
6835
6969
  define("rsvp/events",
6836
6970
  ["exports"],
6837
6971
  function(__exports__) {
@@ -6933,7 +7067,6 @@ define("rsvp/events",
6933
7067
 
6934
7068
  __exports__.EventTarget = EventTarget;
6935
7069
  });
6936
-
6937
7070
  define("rsvp/hash",
6938
7071
  ["rsvp/defer","exports"],
6939
7072
  function(__dependency1__, __exports__) {
@@ -6941,13 +7074,13 @@ define("rsvp/hash",
6941
7074
  var defer = __dependency1__.defer;
6942
7075
 
6943
7076
  function size(object) {
6944
- var size = 0;
7077
+ var s = 0;
6945
7078
 
6946
7079
  for (var prop in object) {
6947
- size++;
7080
+ s++;
6948
7081
  }
6949
7082
 
6950
- return size;
7083
+ return s;
6951
7084
  }
6952
7085
 
6953
7086
  function hash(promises) {
@@ -6985,9 +7118,9 @@ define("rsvp/hash",
6985
7118
  return deferred.promise;
6986
7119
  }
6987
7120
 
7121
+
6988
7122
  __exports__.hash = hash;
6989
7123
  });
6990
-
6991
7124
  define("rsvp/node",
6992
7125
  ["rsvp/promise","rsvp/all","exports"],
6993
7126
  function(__dependency1__, __dependency2__, __exports__) {
@@ -7010,6 +7143,7 @@ define("rsvp/node",
7010
7143
  function denodeify(nodeFunc) {
7011
7144
  return function() {
7012
7145
  var nodeArgs = Array.prototype.slice.call(arguments), resolve, reject;
7146
+ var thisArg = this;
7013
7147
 
7014
7148
  var promise = new Promise(function(nodeResolve, nodeReject) {
7015
7149
  resolve = nodeResolve;
@@ -7020,7 +7154,7 @@ define("rsvp/node",
7020
7154
  nodeArgs.push(makeNodeCallbackFor(resolve, reject));
7021
7155
 
7022
7156
  try {
7023
- nodeFunc.apply(this, nodeArgs);
7157
+ nodeFunc.apply(thisArg, nodeArgs);
7024
7158
  } catch(e) {
7025
7159
  reject(e);
7026
7160
  }
@@ -7030,9 +7164,9 @@ define("rsvp/node",
7030
7164
  };
7031
7165
  }
7032
7166
 
7167
+
7033
7168
  __exports__.denodeify = denodeify;
7034
7169
  });
7035
-
7036
7170
  define("rsvp/promise",
7037
7171
  ["rsvp/config","rsvp/events","exports"],
7038
7172
  function(__dependency1__, __dependency2__, __exports__) {
@@ -7080,6 +7214,8 @@ define("rsvp/promise",
7080
7214
  this.trigger('error', { detail: event.detail });
7081
7215
  }, this);
7082
7216
 
7217
+ this.on('error', onerror);
7218
+
7083
7219
  try {
7084
7220
  resolver(resolvePromise, rejectPromise);
7085
7221
  } catch(e) {
@@ -7087,6 +7223,12 @@ define("rsvp/promise",
7087
7223
  }
7088
7224
  };
7089
7225
 
7226
+ function onerror(event) {
7227
+ if (config.onerror) {
7228
+ config.onerror(event.detail);
7229
+ }
7230
+ }
7231
+
7090
7232
  var invokeCallback = function(type, promise, callback, event) {
7091
7233
  var hasCallback = isFunction(callback),
7092
7234
  value, error, succeeded, failed;
@@ -7120,18 +7262,25 @@ define("rsvp/promise",
7120
7262
  Promise.prototype = {
7121
7263
  constructor: Promise,
7122
7264
 
7265
+ isRejected: undefined,
7266
+ isFulfilled: undefined,
7267
+ rejectedReason: undefined,
7268
+ fulfillmentValue: undefined,
7269
+
7123
7270
  then: function(done, fail) {
7124
- var thenPromise = new Promise(function() {});
7271
+ this.off('error', onerror);
7272
+
7273
+ var thenPromise = new this.constructor(function() {});
7125
7274
 
7126
7275
  if (this.isFulfilled) {
7127
- config.async(function() {
7128
- invokeCallback('resolve', thenPromise, done, { detail: this.fulfillmentValue });
7276
+ config.async(function(promise) {
7277
+ invokeCallback('resolve', thenPromise, done, { detail: promise.fulfillmentValue });
7129
7278
  }, this);
7130
7279
  }
7131
7280
 
7132
7281
  if (this.isRejected) {
7133
- config.async(function() {
7134
- invokeCallback('reject', thenPromise, fail, { detail: this.rejectedReason });
7282
+ config.async(function(promise) {
7283
+ invokeCallback('reject', thenPromise, fail, { detail: promise.rejectedReason });
7135
7284
  }, this);
7136
7285
  }
7137
7286
 
@@ -7158,32 +7307,40 @@ define("rsvp/promise",
7158
7307
  }
7159
7308
 
7160
7309
  function handleThenable(promise, value) {
7161
- var then = null;
7310
+ var then = null,
7311
+ resolved;
7162
7312
 
7163
- if (objectOrFunction(value)) {
7164
- try {
7165
- then = value.then;
7166
- } catch(e) {
7167
- reject(promise, e);
7168
- return true;
7313
+ try {
7314
+ if (promise === value) {
7315
+ throw new TypeError("A promises callback cannot return that same promise.");
7169
7316
  }
7170
7317
 
7171
- if (isFunction(then)) {
7172
- try {
7318
+ if (objectOrFunction(value)) {
7319
+ then = value.then;
7320
+
7321
+ if (isFunction(then)) {
7173
7322
  then.call(value, function(val) {
7323
+ if (resolved) { return true; }
7324
+ resolved = true;
7325
+
7174
7326
  if (value !== val) {
7175
7327
  resolve(promise, val);
7176
7328
  } else {
7177
7329
  fulfill(promise, val);
7178
7330
  }
7179
7331
  }, function(val) {
7332
+ if (resolved) { return true; }
7333
+ resolved = true;
7334
+
7180
7335
  reject(promise, val);
7181
7336
  });
7182
- } catch (e) {
7183
- reject(promise, e);
7337
+
7338
+ return true;
7184
7339
  }
7185
- return true;
7186
7340
  }
7341
+ } catch (error) {
7342
+ reject(promise, error);
7343
+ return true;
7187
7344
  }
7188
7345
 
7189
7346
  return false;
@@ -7208,19 +7365,12 @@ define("rsvp/promise",
7208
7365
 
7209
7366
  __exports__.Promise = Promise;
7210
7367
  });
7211
-
7212
7368
  define("rsvp/reject",
7213
7369
  ["rsvp/promise","exports"],
7214
7370
  function(__dependency1__, __exports__) {
7215
7371
  "use strict";
7216
7372
  var Promise = __dependency1__.Promise;
7217
7373
 
7218
-
7219
- function objectOrFunction(x) {
7220
- return typeof x === "function" || (typeof x === "object" && x !== null);
7221
- }
7222
-
7223
-
7224
7374
  function reject(reason) {
7225
7375
  return new Promise(function (resolve, reject) {
7226
7376
  reject(reason);
@@ -7230,48 +7380,21 @@ define("rsvp/reject",
7230
7380
 
7231
7381
  __exports__.reject = reject;
7232
7382
  });
7233
-
7234
7383
  define("rsvp/resolve",
7235
7384
  ["rsvp/promise","exports"],
7236
7385
  function(__dependency1__, __exports__) {
7237
7386
  "use strict";
7238
7387
  var Promise = __dependency1__.Promise;
7239
7388
 
7240
-
7241
- function objectOrFunction(x) {
7242
- return typeof x === "function" || (typeof x === "object" && x !== null);
7243
- }
7244
-
7245
- function resolve(thenable){
7246
- var promise = new Promise(function(resolve, reject){
7247
- var then;
7248
-
7249
- try {
7250
- if ( objectOrFunction(thenable) ) {
7251
- then = thenable.then;
7252
-
7253
- if (typeof then === "function") {
7254
- then.call(thenable, resolve, reject);
7255
- } else {
7256
- resolve(thenable);
7257
- }
7258
-
7259
- } else {
7260
- resolve(thenable);
7261
- }
7262
-
7263
- } catch(error) {
7264
- reject(error);
7265
- }
7389
+ function resolve(thenable) {
7390
+ return new Promise(function(resolve, reject) {
7391
+ resolve(thenable);
7266
7392
  });
7267
-
7268
- return promise;
7269
7393
  }
7270
7394
 
7271
7395
 
7272
7396
  __exports__.resolve = resolve;
7273
7397
  });
7274
-
7275
7398
  define("rsvp",
7276
7399
  ["rsvp/events","rsvp/promise","rsvp/node","rsvp/all","rsvp/hash","rsvp/defer","rsvp/config","rsvp/resolve","rsvp/reject","exports"],
7277
7400
  function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __exports__) {
@@ -7302,8 +7425,6 @@ define("rsvp",
7302
7425
  __exports__.reject = reject;
7303
7426
  });
7304
7427
 
7305
-
7306
-
7307
7428
  })();
7308
7429
 
7309
7430
  (function() {
@@ -7371,6 +7492,16 @@ define("container",
7371
7492
  this.dict[key] = value;
7372
7493
  },
7373
7494
 
7495
+ /**
7496
+ Delete the given key
7497
+
7498
+ @method remove
7499
+ @param {String} key
7500
+ */
7501
+ remove: function(key) {
7502
+ delete this.dict[key];
7503
+ },
7504
+
7374
7505
  /**
7375
7506
  Check for the existence of given a key, if the key is present at the current
7376
7507
  level return true, otherwise walk up the parent hierarchy and try again. If
@@ -7543,7 +7674,7 @@ define("container",
7543
7674
  register: function(type, name, factory, options) {
7544
7675
  var fullName;
7545
7676
 
7546
- if (type.indexOf(':') !== -1){
7677
+ if (type.indexOf(':') !== -1) {
7547
7678
  options = factory;
7548
7679
  factory = name;
7549
7680
  fullName = type;
@@ -7558,11 +7689,34 @@ define("container",
7558
7689
  this._options.set(normalizedName, options || {});
7559
7690
  },
7560
7691
 
7692
+ /**
7693
+ Unregister a fullName
7694
+
7695
+ ```javascript
7696
+ var container = new Container();
7697
+ container.register('model:user', User);
7698
+
7699
+ container.lookup('model:user') instanceof User //=> true
7700
+
7701
+ container.unregister('model:user')
7702
+ container.lookup('model:user') === undefined //=> true
7703
+
7704
+ @method unregister
7705
+ @param {String} fullName
7706
+ */
7707
+ unregister: function(fullName) {
7708
+ var normalizedName = this.normalize(fullName);
7709
+
7710
+ this.registry.remove(normalizedName);
7711
+ this.cache.remove(normalizedName);
7712
+ this._options.remove(normalizedName);
7713
+ },
7714
+
7561
7715
  /**
7562
7716
  Given a fullName return the corresponding factory.
7563
7717
 
7564
- By default `resolve` will retreive the factory from
7565
- it's containers registry.
7718
+ By default `resolve` will retrieve the factory from
7719
+ its container's registry.
7566
7720
 
7567
7721
  ```javascript
7568
7722
  var container = new Container();
@@ -7594,6 +7748,20 @@ define("container",
7594
7748
  return this.resolver(fullName) || this.registry.get(fullName);
7595
7749
  },
7596
7750
 
7751
+ /**
7752
+ A hook that can be used to describe how the resolver will
7753
+ attempt to find the factory.
7754
+
7755
+ For example, the default Ember `.describe` returns the full
7756
+ class name (including namespace) where Ember's resolver expects
7757
+ to find the `fullName`.
7758
+
7759
+ @method describe
7760
+ */
7761
+ describe: function(fullName) {
7762
+ return fullName;
7763
+ },
7764
+
7597
7765
  /**
7598
7766
  A hook to enable custom fullName normalization behaviour
7599
7767
 
@@ -8168,7 +8336,11 @@ Ember.copy = function(obj, deep) {
8168
8336
  @return {String} A description of the object
8169
8337
  */
8170
8338
  Ember.inspect = function(obj) {
8171
- if (typeof obj !== 'object' || obj === null) {
8339
+ var type = Ember.typeOf(obj);
8340
+ if (type === 'array') {
8341
+ return '[' + obj + ']';
8342
+ }
8343
+ if (type !== 'object') {
8172
8344
  return obj + '';
8173
8345
  }
8174
8346
 
@@ -8351,9 +8523,9 @@ Ember.String = {
8351
8523
  // first, replace any ORDERED replacements.
8352
8524
  var idx = 0; // the current index for non-numerical replacements
8353
8525
  return str.replace(/%@([0-9]+)?/g, function(s, argIndex) {
8354
- argIndex = (argIndex) ? parseInt(argIndex,0) - 1 : idx++ ;
8526
+ argIndex = (argIndex) ? parseInt(argIndex, 10) - 1 : idx++;
8355
8527
  s = formats[argIndex];
8356
- return ((s === null) ? '(null)' : (s === undefined) ? '' : s).toString();
8528
+ return (s === null) ? '(null)' : (s === undefined) ? '' : Ember.inspect(s);
8357
8529
  }) ;
8358
8530
  },
8359
8531
 
@@ -8871,14 +9043,10 @@ function iter(key, value) {
8871
9043
 
8872
9044
  @class Enumerable
8873
9045
  @namespace Ember
8874
- @extends Ember.Mixin
8875
9046
  @since Ember 0.9
8876
9047
  */
8877
9048
  Ember.Enumerable = Ember.Mixin.create({
8878
9049
 
8879
- // compatibility
8880
- isEnumerable: true,
8881
-
8882
9050
  /**
8883
9051
  Implement this method to make your class enumerable.
8884
9052
 
@@ -9350,7 +9518,7 @@ Ember.Enumerable = Ember.Mixin.create({
9350
9518
  @method some
9351
9519
  @param {Function} callback The callback to execute
9352
9520
  @param {Object} [target] The target object to use
9353
- @return {Array} A filtered array.
9521
+ @return {Boolean} `true` if the passed function returns `true` for any item
9354
9522
  */
9355
9523
  some: function(callback, target) {
9356
9524
  return !!this.find(function(x, idx, i) {
@@ -9365,7 +9533,7 @@ Ember.Enumerable = Ember.Mixin.create({
9365
9533
  @method someProperty
9366
9534
  @param {String} key the property to test
9367
9535
  @param {String} [value] optional value to test against.
9368
- @return {Boolean} `true`
9536
+ @return {Boolean} `true` if the passed function returns `true` for any item
9369
9537
  */
9370
9538
  someProperty: function(key, value) {
9371
9539
  return this.some(iter.apply(this, arguments));
@@ -9505,7 +9673,7 @@ Ember.Enumerable = Ember.Mixin.create({
9505
9673
  */
9506
9674
  uniq: function() {
9507
9675
  var ret = Ember.A();
9508
- this.forEach(function(k){
9676
+ this.forEach(function(k) {
9509
9677
  if (a_indexOf(ret, k)<0) ret.push(k);
9510
9678
  });
9511
9679
  return ret;
@@ -9709,7 +9877,6 @@ var get = Ember.get, set = Ember.set, isNone = Ember.isNone, map = Ember.Enumera
9709
9877
 
9710
9878
  @class Array
9711
9879
  @namespace Ember
9712
- @extends Ember.Mixin
9713
9880
  @uses Ember.Enumerable
9714
9881
  @since Ember 0.9.0
9715
9882
  */
@@ -9765,7 +9932,7 @@ Ember.Array = Ember.Mixin.create(Ember.Enumerable, /** @scope Ember.Array.protot
9765
9932
  */
9766
9933
  objectsAt: function(indexes) {
9767
9934
  var self = this;
9768
- return map(indexes, function(idx){ return self.objectAt(idx); });
9935
+ return map(indexes, function(idx) { return self.objectAt(idx); });
9769
9936
  },
9770
9937
 
9771
9938
  // overrides Ember.Enumerable version
@@ -9797,7 +9964,7 @@ Ember.Array = Ember.Mixin.create(Ember.Enumerable, /** @scope Ember.Array.protot
9797
9964
  }),
9798
9965
 
9799
9966
  // optimized version from Enumerable
9800
- contains: function(obj){
9967
+ contains: function(obj) {
9801
9968
  return this.indexOf(obj) >= 0;
9802
9969
  },
9803
9970
 
@@ -9862,7 +10029,7 @@ Ember.Array = Ember.Mixin.create(Ember.Enumerable, /** @scope Ember.Array.protot
9862
10029
  if (startAt < 0) startAt += len;
9863
10030
 
9864
10031
  for(idx=startAt;idx<len;idx++) {
9865
- if (this.objectAt(idx, true) === object) return idx ;
10032
+ if (this.objectAt(idx) === object) return idx ;
9866
10033
  }
9867
10034
  return -1;
9868
10035
  },
@@ -10107,20 +10274,10 @@ Ember.Array = Ember.Mixin.create(Ember.Enumerable, /** @scope Ember.Array.protot
10107
10274
 
10108
10275
  @class Comparable
10109
10276
  @namespace Ember
10110
- @extends Ember.Mixin
10111
10277
  @since Ember 0.9
10112
10278
  */
10113
10279
  Ember.Comparable = Ember.Mixin.create( /** @scope Ember.Comparable.prototype */{
10114
10280
 
10115
- /**
10116
- walk like a duck. Indicates that the object can be compared.
10117
-
10118
- @property isComparable
10119
- @type Boolean
10120
- @default true
10121
- */
10122
- isComparable: true,
10123
-
10124
10281
  /**
10125
10282
  Override to return the result of the comparison of the two parameters. The
10126
10283
  compare method should return:
@@ -10168,7 +10325,6 @@ var get = Ember.get, set = Ember.set;
10168
10325
 
10169
10326
  @class Copyable
10170
10327
  @namespace Ember
10171
- @extends Ember.Mixin
10172
10328
  @since Ember 0.9
10173
10329
  */
10174
10330
  Ember.Copyable = Ember.Mixin.create(/** @scope Ember.Copyable.prototype */ {
@@ -10273,7 +10429,6 @@ var get = Ember.get, set = Ember.set;
10273
10429
 
10274
10430
  @class Freezable
10275
10431
  @namespace Ember
10276
- @extends Ember.Mixin
10277
10432
  @since Ember 0.9
10278
10433
  */
10279
10434
  Ember.Freezable = Ember.Mixin.create(/** @scope Ember.Freezable.prototype */ {
@@ -10353,7 +10508,6 @@ var forEach = Ember.EnumerableUtils.forEach;
10353
10508
 
10354
10509
  @class MutableEnumerable
10355
10510
  @namespace Ember
10356
- @extends Ember.Mixin
10357
10511
  @uses Ember.Enumerable
10358
10512
  */
10359
10513
  Ember.MutableEnumerable = Ember.Mixin.create(Ember.Enumerable, {
@@ -10453,7 +10607,6 @@ var get = Ember.get, set = Ember.set;
10453
10607
 
10454
10608
  @class MutableArray
10455
10609
  @namespace Ember
10456
- @extends Ember.Mixin
10457
10610
  @uses Ember.Array
10458
10611
  @uses Ember.MutableEnumerable
10459
10612
  */
@@ -10523,7 +10676,7 @@ Ember.MutableArray = Ember.Mixin.create(Ember.Array, Ember.MutableEnumerable,/**
10523
10676
  method. You can pass either a single index, or a start and a length.
10524
10677
 
10525
10678
  If you pass a start and length that is beyond the
10526
- length this method will throw an `Ember.OUT_OF_RANGE_EXCEPTION`
10679
+ length this method will throw an `OUT_OF_RANGE_EXCEPTION`
10527
10680
 
10528
10681
  ```javascript
10529
10682
  var colors = ["red", "green", "blue", "yellow", "orange"];
@@ -10577,7 +10730,7 @@ Ember.MutableArray = Ember.Mixin.create(Ember.Array, Ember.MutableEnumerable,/**
10577
10730
 
10578
10731
  ```javascript
10579
10732
  var colors = ["red", "green", "blue"];
10580
- colors.pushObjects("black"); // ["red", "green", "blue", "black"]
10733
+ colors.pushObjects(["black"]); // ["red", "green", "blue", "black"]
10581
10734
  colors.pushObjects(["yellow", "orange"]); // ["red", "green", "blue", "black", "yellow", "orange"]
10582
10735
  ```
10583
10736
 
@@ -10586,6 +10739,9 @@ Ember.MutableArray = Ember.Mixin.create(Ember.Array, Ember.MutableEnumerable,/**
10586
10739
  @return {Ember.Array} receiver
10587
10740
  */
10588
10741
  pushObjects: function(objects) {
10742
+ if (!(Ember.Enumerable.detect(objects) || Ember.isArray(objects))) {
10743
+ throw new TypeError("Must pass Ember.Enumerable to Ember.MutableArray#pushObjects");
10744
+ }
10589
10745
  this.replace(get(this, 'length'), 0, objects);
10590
10746
  return this;
10591
10747
  },
@@ -10804,9 +10960,8 @@ var get = Ember.get, set = Ember.set;
10804
10960
 
10805
10961
  @class Observable
10806
10962
  @namespace Ember
10807
- @extends Ember.Mixin
10808
10963
  */
10809
- Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ {
10964
+ Ember.Observable = Ember.Mixin.create({
10810
10965
 
10811
10966
  /**
10812
10967
  Retrieves the value of a property from the object.
@@ -11004,7 +11159,7 @@ Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ {
11004
11159
  @param {String} keyName The property key that is about to change.
11005
11160
  @return {Ember.Observable}
11006
11161
  */
11007
- propertyWillChange: function(keyName){
11162
+ propertyWillChange: function(keyName) {
11008
11163
  Ember.propertyWillChange(this, keyName);
11009
11164
  return this;
11010
11165
  },
@@ -11310,7 +11465,7 @@ Ember.TargetActionSupport = Ember.Mixin.create({
11310
11465
  target: Ember.computed.alias('controller'),
11311
11466
  action: 'save',
11312
11467
  actionContext: Ember.computed.alias('context'),
11313
- click: function(){
11468
+ click: function() {
11314
11469
  this.triggerAction(); // Sends the `save` action, along with the current context
11315
11470
  // to the current controller
11316
11471
  }
@@ -11322,7 +11477,7 @@ Ember.TargetActionSupport = Ember.Mixin.create({
11322
11477
 
11323
11478
  ```javascript
11324
11479
  App.SaveButtonView = Ember.View.extend(Ember.TargetActionSupport, {
11325
- click: function(){
11480
+ click: function() {
11326
11481
  this.triggerAction({
11327
11482
  action: 'save',
11328
11483
  target: this.get('controller'),
@@ -11340,7 +11495,7 @@ Ember.TargetActionSupport = Ember.Mixin.create({
11340
11495
  ```javascript
11341
11496
  App.SaveButtonView = Ember.View.extend(Ember.TargetActionSupport, {
11342
11497
  target: Ember.computed.alias('controller'),
11343
- click: function(){
11498
+ click: function() {
11344
11499
  this.triggerAction({
11345
11500
  action: 'save'
11346
11501
  }); // Sends the `save` action, along with a reference to `this`,
@@ -11422,7 +11577,6 @@ Ember.TargetActionSupport = Ember.Mixin.create({
11422
11577
 
11423
11578
  @class Evented
11424
11579
  @namespace Ember
11425
- @extends Ember.Mixin
11426
11580
  */
11427
11581
  Ember.Evented = Ember.Mixin.create({
11428
11582
 
@@ -11540,8 +11694,8 @@ Ember.Evented = Ember.Mixin.create({
11540
11694
  (function() {
11541
11695
  var RSVP = requireModule("rsvp");
11542
11696
 
11543
- RSVP.configure('async', function(callback, binding) {
11544
- Ember.run.schedule('actions', binding, callback);
11697
+ RSVP.configure('async', function(callback, promise) {
11698
+ Ember.run.schedule('actions', promise, callback, promise);
11545
11699
  });
11546
11700
 
11547
11701
  /**
@@ -11554,7 +11708,6 @@ var get = Ember.get;
11554
11708
  /**
11555
11709
  @class Deferred
11556
11710
  @namespace Ember
11557
- @extends Ember.Mixin
11558
11711
  */
11559
11712
  Ember.DeferredMixin = Ember.Mixin.create({
11560
11713
  /**
@@ -11593,7 +11746,7 @@ Ember.DeferredMixin = Ember.Mixin.create({
11593
11746
  deferred = get(this, '_deferred');
11594
11747
  promise = deferred.promise;
11595
11748
 
11596
- if (value === this){
11749
+ if (value === this) {
11597
11750
  deferred.resolve(promise);
11598
11751
  } else {
11599
11752
  deferred.resolve(value);
@@ -11640,8 +11793,8 @@ Ember.Container.set = Ember.set;
11640
11793
  */
11641
11794
 
11642
11795
 
11643
- // NOTE: this object should never be included directly. Instead use Ember.
11644
- // Ember.Object. We only define this separately so that Ember.Set can depend on it
11796
+ // NOTE: this object should never be included directly. Instead use `Ember.Object`.
11797
+ // We only define this separately so that `Ember.Set` can depend on it.
11645
11798
 
11646
11799
 
11647
11800
  var set = Ember.set, get = Ember.get,
@@ -11786,6 +11939,10 @@ function makeCtor() {
11786
11939
 
11787
11940
  }
11788
11941
 
11942
+ /**
11943
+ @class CoreObject
11944
+ @namespace Ember
11945
+ */
11789
11946
  var CoreObject = makeCtor();
11790
11947
  CoreObject.toString = function() { return "Ember.CoreObject"; };
11791
11948
 
@@ -11982,7 +12139,7 @@ CoreObject.PrototypeMixin = Mixin.create({
11982
12139
  included in the output.
11983
12140
 
11984
12141
  App.Teacher = App.Person.extend({
11985
- toStringExtension: function(){
12142
+ toStringExtension: function() {
11986
12143
  return this.get('fullName');
11987
12144
  }
11988
12145
  });
@@ -12045,12 +12202,57 @@ var ClassMixin = Mixin.create({
12045
12202
  return Class;
12046
12203
  },
12047
12204
 
12205
+ /**
12206
+ Equivalent to doing `extend(arguments).create()`.
12207
+ If possible use the normal `create` method instead.
12208
+
12209
+ @method createWithMixins
12210
+ @static
12211
+ @param [arguments]*
12212
+ */
12048
12213
  createWithMixins: function() {
12049
12214
  var C = this;
12050
12215
  if (arguments.length>0) { this._initMixins(arguments); }
12051
12216
  return new C();
12052
12217
  },
12053
12218
 
12219
+ /**
12220
+ Creates an instance of a class. Accepts either no arguments, or an object
12221
+ containing values to initialize the newly instantiated object with.
12222
+
12223
+ ```javascript
12224
+ App.Person = Ember.Object.extend({
12225
+ helloWorld: function() {
12226
+ alert("Hi, my name is " + this.get('name'));
12227
+ }
12228
+ });
12229
+
12230
+ var tom = App.Person.create({
12231
+ name: 'Tom Dale'
12232
+ });
12233
+
12234
+ tom.helloWorld(); // alerts "Hi, my name is Tom Dale".
12235
+ ```
12236
+
12237
+ `create` will call the `init` function if defined during
12238
+ `Ember.AnyObject.extend`
12239
+
12240
+ If no arguments are passed to `create`, it will not set values to the new
12241
+ instance during initialization:
12242
+
12243
+ ```javascript
12244
+ var noName = App.Person.create();
12245
+ noName.helloWorld(); // alerts undefined
12246
+ ```
12247
+
12248
+ NOTE: For performance reasons, you cannot declare methods or computed
12249
+ properties during `create`. You should instead declare methods and computed
12250
+ properties when using `extend` or use the `createWithMixins` shorthand.
12251
+
12252
+ @method create
12253
+ @static
12254
+ @param [arguments]*
12255
+ */
12054
12256
  create: function() {
12055
12257
  var C = this;
12056
12258
  if (arguments.length>0) { this._initProperties(arguments); }
@@ -12150,10 +12352,6 @@ if (Ember.config.overrideClassMixin) {
12150
12352
  CoreObject.ClassMixin = ClassMixin;
12151
12353
  ClassMixin.apply(CoreObject);
12152
12354
 
12153
- /**
12154
- @class CoreObject
12155
- @namespace Ember
12156
- */
12157
12355
  Ember.CoreObject = CoreObject;
12158
12356
 
12159
12357
  })();
@@ -12673,6 +12871,9 @@ Ember.ArrayProxy = Ember.Object.extend(Ember.MutableArray,/** @scope Ember.Array
12673
12871
  },
12674
12872
 
12675
12873
  pushObjects: function(objects) {
12874
+ if (!(Ember.Enumerable.detect(objects) || Ember.isArray(objects))) {
12875
+ throw new TypeError("Must pass Ember.Enumerable to Ember.MutableArray#pushObjects");
12876
+ }
12676
12877
  this._replace(get(this, 'length'), 0, objects);
12677
12878
  return this;
12678
12879
  },
@@ -12925,6 +13126,7 @@ function addObserverForContentKey(content, keyName, proxy, idx, loc) {
12925
13126
  while(--loc>=idx) {
12926
13127
  var item = content.objectAt(loc);
12927
13128
  if (item) {
13129
+ Ember.assert('When using @each to observe the array ' + content + ', the array must return an object', Ember.typeOf(item) === 'instance' || Ember.typeOf(item) === 'object');
12928
13130
  Ember.addBeforeObserver(item, keyName, proxy, 'contentKeyWillChange');
12929
13131
  Ember.addObserver(item, keyName, proxy, 'contentKeyDidChange');
12930
13132
 
@@ -13008,7 +13210,7 @@ Ember.EachProxy = Ember.Object.extend({
13008
13210
  for(key in keys) {
13009
13211
  if (!keys.hasOwnProperty(key)) { continue; }
13010
13212
 
13011
- if (lim>0) removeObserverForContentKey(content, key, this, idx, lim);
13213
+ if (lim>0) { removeObserverForContentKey(content, key, this, idx, lim); }
13012
13214
 
13013
13215
  Ember.propertyWillChange(this, key);
13014
13216
  }
@@ -13018,21 +13220,20 @@ Ember.EachProxy = Ember.Object.extend({
13018
13220
  },
13019
13221
 
13020
13222
  arrayDidChange: function(content, idx, removedCnt, addedCnt) {
13021
- var keys = this._keys, key, lim;
13223
+ var keys = this._keys, lim;
13022
13224
 
13023
13225
  lim = addedCnt>0 ? idx+addedCnt : -1;
13024
- Ember.beginPropertyChanges(this);
13025
-
13026
- for(key in keys) {
13027
- if (!keys.hasOwnProperty(key)) { continue; }
13226
+ Ember.changeProperties(function() {
13227
+ for(var key in keys) {
13228
+ if (!keys.hasOwnProperty(key)) { continue; }
13028
13229
 
13029
- if (lim>0) addObserverForContentKey(content, key, this, idx, lim);
13230
+ if (lim>0) { addObserverForContentKey(content, key, this, idx, lim); }
13030
13231
 
13031
- Ember.propertyDidChange(this, key);
13032
- }
13232
+ Ember.propertyDidChange(this, key);
13233
+ }
13033
13234
 
13034
- Ember.propertyDidChange(this._content, '@each');
13035
- Ember.endPropertyChanges(this);
13235
+ Ember.propertyDidChange(this._content, '@each');
13236
+ }, this);
13036
13237
  },
13037
13238
 
13038
13239
  // ..........................................................
@@ -13181,7 +13382,7 @@ var NativeArray = Ember.Mixin.create(Ember.MutableArray, Ember.Observable, Ember
13181
13382
 
13182
13383
  copy: function(deep) {
13183
13384
  if (deep) {
13184
- return this.map(function(item){ return Ember.copy(item, true); });
13385
+ return this.map(function(item) { return Ember.copy(item, true); });
13185
13386
  }
13186
13387
 
13187
13388
  return this.slice();
@@ -13207,7 +13408,6 @@ if (ignore.length>0) {
13207
13408
 
13208
13409
  @class NativeArray
13209
13410
  @namespace Ember
13210
- @extends Ember.Mixin
13211
13411
  @uses Ember.MutableArray
13212
13412
  @uses Ember.Observable
13213
13413
  @uses Ember.Copyable
@@ -13222,7 +13422,7 @@ Ember.NativeArray = NativeArray;
13222
13422
  @for Ember
13223
13423
  @return {Ember.NativeArray}
13224
13424
  */
13225
- Ember.A = function(arr){
13425
+ Ember.A = function(arr) {
13226
13426
  if (arr === undefined) { arr = []; }
13227
13427
  return Ember.Array.detect(arr) ? arr : Ember.NativeArray.apply(arr);
13228
13428
  };
@@ -13398,7 +13598,7 @@ Ember.Set = Ember.CoreObject.extend(Ember.MutableEnumerable, Ember.Copyable, Emb
13398
13598
  Ember.propertyWillChange(this, 'firstObject');
13399
13599
  Ember.propertyWillChange(this, 'lastObject');
13400
13600
 
13401
- for (var i=0; i < len; i++){
13601
+ for (var i=0; i < len; i++) {
13402
13602
  guid = guidFor(this[i]);
13403
13603
  delete this[guid];
13404
13604
  delete this[i];
@@ -13818,7 +14018,6 @@ var get = Ember.get;
13818
14018
 
13819
14019
  @class ControllerMixin
13820
14020
  @namespace Ember
13821
- @extends Ember.Mixin
13822
14021
  */
13823
14022
  Ember.ControllerMixin = Ember.Mixin.create({
13824
14023
  /* ducktype as a controller */
@@ -13852,7 +14051,7 @@ Ember.ControllerMixin = Ember.Mixin.create({
13852
14051
  if (this[actionName]) {
13853
14052
  Ember.assert("The controller " + this + " does not have the action " + actionName, typeof this[actionName] === 'function');
13854
14053
  this[actionName].apply(this, args);
13855
- } else if(target = get(this, 'target')) {
14054
+ } else if (target = get(this, 'target')) {
13856
14055
  Ember.assert("The target for controller " + this + " (" + target + ") did not define a `send` method", typeof target.send === 'function');
13857
14056
  target.send.apply(target, arguments);
13858
14057
  }
@@ -13906,7 +14105,6 @@ var get = Ember.get, set = Ember.set, forEach = Ember.EnumerableUtils.forEach;
13906
14105
 
13907
14106
  @class SortableMixin
13908
14107
  @namespace Ember
13909
- @extends Ember.Mixin
13910
14108
  @uses Ember.MutableEnumerable
13911
14109
  */
13912
14110
  Ember.SortableMixin = Ember.Mixin.create(Ember.MutableEnumerable, {
@@ -13924,7 +14122,7 @@ Ember.SortableMixin = Ember.Mixin.create(Ember.MutableEnumerable, {
13924
14122
  @property {Boolean} sortAscending
13925
14123
  */
13926
14124
  sortAscending: true,
13927
-
14125
+
13928
14126
  /**
13929
14127
  The function used to compare two values. You can override this if you
13930
14128
  want to do custom comparisons.Functions must be of the type expected by
@@ -13934,8 +14132,8 @@ Ember.SortableMixin = Ember.Mixin.create(Ember.MutableEnumerable, {
13934
14132
  return a positive value otherwise:
13935
14133
 
13936
14134
  ```javascript
13937
- function(x,y){ // These are assumed to be integers
13938
- if(x === y)
14135
+ function(x,y) { // These are assumed to be integers
14136
+ if (x === y)
13939
14137
  return 0;
13940
14138
  return x < y ? -1 : 1;
13941
14139
  }
@@ -13946,7 +14144,7 @@ Ember.SortableMixin = Ember.Mixin.create(Ember.MutableEnumerable, {
13946
14144
  @default Ember.compare
13947
14145
  */
13948
14146
  sortFunction: Ember.compare,
13949
-
14147
+
13950
14148
  orderBy: function(item1, item2) {
13951
14149
  var result = 0,
13952
14150
  sortProperties = get(this, 'sortProperties'),
@@ -14441,7 +14639,7 @@ if (Ember.$) {
14441
14639
  // is a "zero-scope" element. This problem can be worked around by making
14442
14640
  // the first node an invisible text node. We, like Modernizr, use &shy;
14443
14641
 
14444
- var needsShy = this.document && (function(){
14642
+ var needsShy = this.document && (function() {
14445
14643
  var testEl = document.createElement('div');
14446
14644
  testEl.innerHTML = "<div></div>";
14447
14645
  testEl.firstChild.innerHTML = "<script></script>";
@@ -14597,6 +14795,45 @@ ClassSet.prototype = {
14597
14795
  }
14598
14796
  };
14599
14797
 
14798
+ var BAD_TAG_NAME_TEST_REGEXP = /[^a-zA-Z0-9\-]/;
14799
+ var BAD_TAG_NAME_REPLACE_REGEXP = /[^a-zA-Z0-9\-]/g;
14800
+
14801
+ function stripTagName(tagName) {
14802
+ if (!tagName) {
14803
+ return tagName;
14804
+ }
14805
+
14806
+ if (!BAD_TAG_NAME_TEST_REGEXP.test(tagName)) {
14807
+ return tagName;
14808
+ }
14809
+
14810
+ return tagName.replace(BAD_TAG_NAME_REPLACE_REGEXP, '');
14811
+ }
14812
+
14813
+ var BAD_CHARS_REGEXP = /&(?!\w+;)|[<>"'`]/g;
14814
+ var POSSIBLE_CHARS_REGEXP = /[&<>"'`]/;
14815
+
14816
+ function escapeAttribute(value) {
14817
+ // Stolen shamelessly from Handlebars
14818
+
14819
+ var escape = {
14820
+ "<": "&lt;",
14821
+ ">": "&gt;",
14822
+ '"': "&quot;",
14823
+ "'": "&#x27;",
14824
+ "`": "&#x60;"
14825
+ };
14826
+
14827
+ var escapeChar = function(chr) {
14828
+ return escape[chr] || "&amp;";
14829
+ };
14830
+
14831
+ var string = value.toString();
14832
+
14833
+ if(!POSSIBLE_CHARS_REGEXP.test(string)) { return string; }
14834
+ return string.replace(BAD_CHARS_REGEXP, escapeChar);
14835
+ }
14836
+
14600
14837
  /**
14601
14838
  `Ember.RenderBuffer` gathers information regarding the a view and generates the
14602
14839
  final representation. `Ember.RenderBuffer` will generate HTML which can be pushed
@@ -14884,14 +15121,14 @@ Ember._RenderBuffer.prototype =
14884
15121
  style = this.elementStyle,
14885
15122
  attr, prop;
14886
15123
 
14887
- buffer += '<' + tagName;
15124
+ buffer += '<' + stripTagName(tagName);
14888
15125
 
14889
15126
  if (id) {
14890
- buffer += ' id="' + this._escapeAttribute(id) + '"';
15127
+ buffer += ' id="' + escapeAttribute(id) + '"';
14891
15128
  this.elementId = null;
14892
15129
  }
14893
15130
  if (classes) {
14894
- buffer += ' class="' + this._escapeAttribute(classes.join(' ')) + '"';
15131
+ buffer += ' class="' + escapeAttribute(classes.join(' ')) + '"';
14895
15132
  this.classes = null;
14896
15133
  }
14897
15134
 
@@ -14900,7 +15137,7 @@ Ember._RenderBuffer.prototype =
14900
15137
 
14901
15138
  for (prop in style) {
14902
15139
  if (style.hasOwnProperty(prop)) {
14903
- buffer += prop + ':' + this._escapeAttribute(style[prop]) + ';';
15140
+ buffer += prop + ':' + escapeAttribute(style[prop]) + ';';
14904
15141
  }
14905
15142
  }
14906
15143
 
@@ -14912,7 +15149,7 @@ Ember._RenderBuffer.prototype =
14912
15149
  if (attrs) {
14913
15150
  for (attr in attrs) {
14914
15151
  if (attrs.hasOwnProperty(attr)) {
14915
- buffer += ' ' + attr + '="' + this._escapeAttribute(attrs[attr]) + '"';
15152
+ buffer += ' ' + attr + '="' + escapeAttribute(attrs[attr]) + '"';
14916
15153
  }
14917
15154
  }
14918
15155
 
@@ -14927,7 +15164,7 @@ Ember._RenderBuffer.prototype =
14927
15164
  if (value === true) {
14928
15165
  buffer += ' ' + prop + '="' + prop + '"';
14929
15166
  } else {
14930
- buffer += ' ' + prop + '="' + this._escapeAttribute(props[prop]) + '"';
15167
+ buffer += ' ' + prop + '="' + escapeAttribute(props[prop]) + '"';
14931
15168
  }
14932
15169
  }
14933
15170
  }
@@ -14942,7 +15179,7 @@ Ember._RenderBuffer.prototype =
14942
15179
 
14943
15180
  pushClosingTag: function() {
14944
15181
  var tagName = this.tagNames.pop();
14945
- if (tagName) { this.buffer += '</' + tagName + '>'; }
15182
+ if (tagName) { this.buffer += '</' + stripTagName(tagName) + '>'; }
14946
15183
  },
14947
15184
 
14948
15185
  currentTagName: function() {
@@ -15029,7 +15266,7 @@ Ember._RenderBuffer.prototype =
15029
15266
  if (this._hasElement && this._element) {
15030
15267
  // Firefox versions < 11 do not have support for element.outerHTML.
15031
15268
  var thisElement = this.element(), outerHTML = thisElement.outerHTML;
15032
- if (typeof outerHTML === 'undefined'){
15269
+ if (typeof outerHTML === 'undefined') {
15033
15270
  return Ember.$('<div/>').append(thisElement).html();
15034
15271
  }
15035
15272
  return outerHTML;
@@ -15040,32 +15277,7 @@ Ember._RenderBuffer.prototype =
15040
15277
 
15041
15278
  innerString: function() {
15042
15279
  return this.buffer;
15043
- },
15044
-
15045
- _escapeAttribute: function(value) {
15046
- // Stolen shamelessly from Handlebars
15047
-
15048
- var escape = {
15049
- "<": "&lt;",
15050
- ">": "&gt;",
15051
- '"': "&quot;",
15052
- "'": "&#x27;",
15053
- "`": "&#x60;"
15054
- };
15055
-
15056
- var badChars = /&(?!\w+;)|[<>"'`]/g;
15057
- var possible = /[&<>"'`]/;
15058
-
15059
- var escapeChar = function(chr) {
15060
- return escape[chr] || "&amp;";
15061
- };
15062
-
15063
- var string = value.toString();
15064
-
15065
- if(!possible.test(string)) { return string; }
15066
- return string.replace(badChars, escapeChar);
15067
15280
  }
15068
-
15069
15281
  };
15070
15282
 
15071
15283
  })();
@@ -15381,8 +15593,11 @@ var childViewsProperty = Ember.computed(function() {
15381
15593
  var childViews = this._childViews, ret = Ember.A(), view = this;
15382
15594
 
15383
15595
  a_forEach(childViews, function(view) {
15596
+ var currentChildViews;
15384
15597
  if (view.isVirtual) {
15385
- ret.pushObjects(get(view, 'childViews'));
15598
+ if (currentChildViews = get(view, 'childViews')) {
15599
+ ret.pushObjects(currentChildViews);
15600
+ }
15386
15601
  } else {
15387
15602
  ret.push(view);
15388
15603
  }
@@ -15677,8 +15892,8 @@ class:
15677
15892
  MyView = Ember.View.extend({
15678
15893
  classNameBindings: ['propertyA', 'propertyB'],
15679
15894
  propertyA: 'from-a',
15680
- propertyB: function(){
15681
- if(someLogic){ return 'from-b'; }
15895
+ propertyB: function() {
15896
+ if (someLogic) { return 'from-b'; }
15682
15897
  }.property()
15683
15898
  });
15684
15899
  ```
@@ -15859,7 +16074,7 @@ class:
15859
16074
  MyTextInput = Ember.View.extend({
15860
16075
  tagName: 'input',
15861
16076
  attributeBindings: ['disabled'],
15862
- disabled: function(){
16077
+ disabled: function() {
15863
16078
  if (someLogic) {
15864
16079
  return true;
15865
16080
  } else {
@@ -15968,7 +16183,7 @@ class:
15968
16183
 
15969
16184
  aController = Ember.Object.create({
15970
16185
  firstName: 'Barry',
15971
- excitedGreeting: function(){
16186
+ excitedGreeting: function() {
15972
16187
  return this.get("content.firstName") + "!!!"
15973
16188
  }.property()
15974
16189
  });
@@ -16039,7 +16254,7 @@ class:
16039
16254
 
16040
16255
  ```javascript
16041
16256
  AView = Ember.View.extend({
16042
- click: function(event){
16257
+ click: function(event) {
16043
16258
  // will be called when when an instance's
16044
16259
  // rendered element is clicked
16045
16260
  }
@@ -16060,7 +16275,7 @@ class:
16060
16275
  ```javascript
16061
16276
  AView = Ember.View.extend({
16062
16277
  eventManager: Ember.Object.create({
16063
- doubleClick: function(event, view){
16278
+ doubleClick: function(event, view) {
16064
16279
  // will be called when when an instance's
16065
16280
  // rendered element or any rendering
16066
16281
  // of this views's descendent
@@ -16075,11 +16290,11 @@ class:
16075
16290
 
16076
16291
  ```javascript
16077
16292
  AView = Ember.View.extend({
16078
- mouseEnter: function(event){
16293
+ mouseEnter: function(event) {
16079
16294
  // will never trigger.
16080
16295
  },
16081
16296
  eventManager: Ember.Object.create({
16082
- mouseEnter: function(event, view){
16297
+ mouseEnter: function(event, view) {
16083
16298
  // takes presedence over AView#mouseEnter
16084
16299
  }
16085
16300
  })
@@ -16097,7 +16312,7 @@ class:
16097
16312
  OuterView = Ember.View.extend({
16098
16313
  template: Ember.Handlebars.compile("outer {{#view InnerView}}inner{{/view}} outer"),
16099
16314
  eventManager: Ember.Object.create({
16100
- mouseEnter: function(event, view){
16315
+ mouseEnter: function(event, view) {
16101
16316
  // view might be instance of either
16102
16317
  // OuterView or InnerView depending on
16103
16318
  // where on the page the user interaction occured
@@ -16106,12 +16321,12 @@ class:
16106
16321
  });
16107
16322
 
16108
16323
  InnerView = Ember.View.extend({
16109
- click: function(event){
16324
+ click: function(event) {
16110
16325
  // will be called if rendered inside
16111
16326
  // an OuterView because OuterView's
16112
16327
  // eventManager doesn't handle click events
16113
16328
  },
16114
- mouseEnter: function(event){
16329
+ mouseEnter: function(event) {
16115
16330
  // will never be called if rendered inside
16116
16331
  // an OuterView.
16117
16332
  }
@@ -16321,6 +16536,14 @@ Ember.View = Ember.CoreView.extend(
16321
16536
  }
16322
16537
  }).volatile(),
16323
16538
 
16539
+ /**
16540
+ The parent context for this template.
16541
+ */
16542
+ parentContext: function() {
16543
+ var parentView = get(this, '_parentView');
16544
+ return parentView && get(parentView, '_context');
16545
+ },
16546
+
16324
16547
  /**
16325
16548
  @private
16326
16549
 
@@ -16422,7 +16645,7 @@ Ember.View = Ember.CoreView.extend(
16422
16645
  var view = get(this, 'parentView');
16423
16646
 
16424
16647
  while (view) {
16425
- if(view instanceof klass) { return view; }
16648
+ if (view instanceof klass) { return view; }
16426
16649
  view = get(view, 'parentView');
16427
16650
  }
16428
16651
  },
@@ -16443,7 +16666,7 @@ Ember.View = Ember.CoreView.extend(
16443
16666
  function(view) { return klass.detect(view.constructor); };
16444
16667
 
16445
16668
  while (view) {
16446
- if( isOfType(view) ) { return view; }
16669
+ if (isOfType(view)) { return view; }
16447
16670
  view = get(view, 'parentView');
16448
16671
  }
16449
16672
  },
@@ -16476,7 +16699,7 @@ Ember.View = Ember.CoreView.extend(
16476
16699
  var view = get(this, 'parentView');
16477
16700
 
16478
16701
  while (view) {
16479
- if(get(view, 'parentView') instanceof klass) { return view; }
16702
+ if (get(view, 'parentView') instanceof klass) { return view; }
16480
16703
  view = get(view, 'parentView');
16481
16704
  }
16482
16705
  },
@@ -16999,7 +17222,7 @@ Ember.View = Ember.CoreView.extend(
16999
17222
  */
17000
17223
  invokeRecursively: function(fn, includeSelf) {
17001
17224
  var childViews = (includeSelf === false) ? this._childViews : [this];
17002
- var currentViews, view;
17225
+ var currentViews, view, currentChildViews;
17003
17226
 
17004
17227
  while (childViews.length) {
17005
17228
  currentViews = childViews.slice();
@@ -17007,16 +17230,17 @@ Ember.View = Ember.CoreView.extend(
17007
17230
 
17008
17231
  for (var i=0, l=currentViews.length; i<l; i++) {
17009
17232
  view = currentViews[i];
17233
+ currentChildViews = view._childViews ? view._childViews.slice(0) : null;
17010
17234
  fn(view);
17011
- if (view._childViews) {
17012
- childViews.push.apply(childViews, view._childViews);
17235
+ if (currentChildViews) {
17236
+ childViews.push.apply(childViews, currentChildViews);
17013
17237
  }
17014
17238
  }
17015
17239
  }
17016
17240
  },
17017
17241
 
17018
17242
  triggerRecursively: function(eventName) {
17019
- var childViews = [this], currentViews, view;
17243
+ var childViews = [this], currentViews, view, currentChildViews;
17020
17244
 
17021
17245
  while (childViews.length) {
17022
17246
  currentViews = childViews.slice();
@@ -17024,10 +17248,12 @@ Ember.View = Ember.CoreView.extend(
17024
17248
 
17025
17249
  for (var i=0, l=currentViews.length; i<l; i++) {
17026
17250
  view = currentViews[i];
17251
+ currentChildViews = view._childViews ? view._childViews.slice(0) : null;
17027
17252
  if (view.trigger) { view.trigger(eventName); }
17028
- if (view._childViews) {
17029
- childViews.push.apply(childViews, view._childViews);
17253
+ if (currentChildViews) {
17254
+ childViews.push.apply(childViews, currentChildViews);
17030
17255
  }
17256
+
17031
17257
  }
17032
17258
  }
17033
17259
  },
@@ -17074,7 +17300,7 @@ Ember.View = Ember.CoreView.extend(
17074
17300
 
17075
17301
  @event willDestroyElement
17076
17302
  */
17077
- willDestroyElement: function() {},
17303
+ willDestroyElement: Ember.K,
17078
17304
 
17079
17305
  /**
17080
17306
  @private
@@ -17586,7 +17812,7 @@ Ember.View = Ember.CoreView.extend(
17586
17812
  }
17587
17813
 
17588
17814
  var view = this,
17589
- stateCheckedObserver = function(){
17815
+ stateCheckedObserver = function() {
17590
17816
  view.currentState.invokeObserver(this, observer);
17591
17817
  },
17592
17818
  scheduledObserver = function() {
@@ -18847,7 +19073,7 @@ Ember.CollectionView = Ember.ContainerView.extend(/** @scope Ember.CollectionVie
18847
19073
  var content = get(this, 'content');
18848
19074
 
18849
19075
  if (content) {
18850
- Ember.assert(fmt("an Ember.CollectionView's content must implement Ember.Array. You passed %@", [content]), Ember.Array.detect(content));
19076
+ this._assertArrayLike(content);
18851
19077
  content.addArrayObserver(this);
18852
19078
  }
18853
19079
 
@@ -18855,6 +19081,10 @@ Ember.CollectionView = Ember.ContainerView.extend(/** @scope Ember.CollectionVie
18855
19081
  this.arrayDidChange(content, 0, null, len);
18856
19082
  }, 'content'),
18857
19083
 
19084
+ _assertArrayLike: function(content) {
19085
+ Ember.assert(fmt("an Ember.CollectionView's content must implement Ember.Array. You passed %@", [content]), Ember.Array.detect(content));
19086
+ },
19087
+
18858
19088
  destroy: function() {
18859
19089
  if (!this._super()) { return; }
18860
19090
 
@@ -18987,6 +19217,8 @@ Ember.CollectionView.CONTAINER_MAP = {
18987
19217
 
18988
19218
 
18989
19219
  (function() {
19220
+ var get = Ember.get, set = Ember.set, isNone = Ember.isNone;
19221
+
18990
19222
  /**
18991
19223
  @module ember
18992
19224
  @submodule ember-views
@@ -19070,11 +19302,66 @@ Ember.CollectionView.CONTAINER_MAP = {
19070
19302
  @namespace Ember
19071
19303
  @extends Ember.View
19072
19304
  */
19073
- Ember.Component = Ember.View.extend({
19305
+ Ember.Component = Ember.View.extend(Ember.TargetActionSupport, {
19074
19306
  init: function() {
19075
19307
  this._super();
19076
- this.set('context', this);
19077
- this.set('controller', this);
19308
+ set(this, 'context', this);
19309
+ set(this, 'controller', this);
19310
+ set(this, 'templateData', {keywords: {}});
19311
+ },
19312
+
19313
+ targetObject: Ember.computed(function(key) {
19314
+ var parentView = get(this, '_parentView');
19315
+ return parentView ? get(parentView, 'controller') : null;
19316
+ }).property('_parentView'),
19317
+
19318
+ /**
19319
+ Sends an action to component's controller. A component inherits its
19320
+ controller from the context in which it is used.
19321
+
19322
+ By default, calling `sendAction()` will send an action with the name
19323
+ of the component's `action` property.
19324
+
19325
+ For example, if the component had a property `action` with the value
19326
+ `"addItem"`, calling `sendAction()` would send the `addItem` action
19327
+ to the component's controller.
19328
+
19329
+ If you provide an argument to `sendAction()`, that key will be used to look
19330
+ up the action name.
19331
+
19332
+ For example, if the component had a property `playing` with the value
19333
+ `didStartPlaying`, calling `sendAction('playing')` would send the
19334
+ `didStartPlaying` action to the component's controller.
19335
+
19336
+ Whether or not you are using the default action or a named action, if
19337
+ the action name is not defined on the component, calling `sendAction()`
19338
+ does not have any effect.
19339
+
19340
+ For example, if you call `sendAction()` on a component that does not have
19341
+ an `action` property defined, no action will be sent to the controller,
19342
+ nor will an exception be raised.
19343
+
19344
+ @param [action] {String} the action to trigger
19345
+ */
19346
+ sendAction: function(action) {
19347
+ var actionName;
19348
+
19349
+ // Send the default action
19350
+ if (action === undefined) {
19351
+ actionName = get(this, 'action');
19352
+ Ember.assert("The default action was triggered on the component " + this.toString() + ", but the action name (" + actionName + ") was not a string.", isNone(actionName) || typeof actionName === 'string');
19353
+ } else {
19354
+ actionName = get(this, action);
19355
+ Ember.assert("The " + action + " action was triggered on the component " + this.toString() + ", but the action name (" + actionName + ") was not a string.", isNone(actionName) || typeof actionName === 'string');
19356
+ }
19357
+
19358
+
19359
+ // If no action name for that action could be found, just abort.
19360
+ if (actionName === undefined) { return; }
19361
+
19362
+ this.triggerAction({
19363
+ action: actionName
19364
+ });
19078
19365
  }
19079
19366
  });
19080
19367
 
@@ -19105,7 +19392,7 @@ For example:
19105
19392
  ```javascript
19106
19393
  App.SaveButtonView = Ember.View.extend(Ember.ViewTargetActionSupport, {
19107
19394
  action: 'save',
19108
- click: function(){
19395
+ click: function() {
19109
19396
  this.triggerAction(); // Sends the `save` action, along with the current context
19110
19397
  // to the current controller
19111
19398
  }
@@ -19117,7 +19404,7 @@ to `triggerAction` as well.
19117
19404
 
19118
19405
  ```javascript
19119
19406
  App.SaveButtonView = Ember.View.extend(Ember.ViewTargetActionSupport, {
19120
- click: function(){
19407
+ click: function() {
19121
19408
  this.triggerAction({
19122
19409
  action: 'save'
19123
19410
  }); // Sends the `save` action, along with the current context
@@ -19386,7 +19673,7 @@ Ember.State.reopenClass({
19386
19673
 
19387
19674
  bManager = Ember.StateManager.create({
19388
19675
  stateOne: Ember.State.create({
19389
- changeToStateTwo: function(manager, context){
19676
+ changeToStateTwo: function(manager, context) {
19390
19677
  manager.transitionTo('stateTwo', context)
19391
19678
  }
19392
19679
  }),
@@ -19714,7 +20001,7 @@ var sendEvent = function(eventName, sendRecursiveArguments, isUnhandledPass) {
19714
20001
 
19715
20002
  ```javascript
19716
20003
  managerC = Ember.StateManager.create({
19717
- initialState: function(){
20004
+ initialState: function() {
19718
20005
  if (someLogic) {
19719
20006
  return 'active';
19720
20007
  } else {
@@ -19757,12 +20044,12 @@ var sendEvent = function(eventName, sendRecursiveArguments, isUnhandledPass) {
19757
20044
  robotManager = Ember.StateManager.create({
19758
20045
  initialState: 'poweredDown',
19759
20046
  poweredDown: Ember.State.create({
19760
- exit: function(stateManager){
20047
+ exit: function(stateManager) {
19761
20048
  console.log("exiting the poweredDown state")
19762
20049
  }
19763
20050
  }),
19764
20051
  poweredUp: Ember.State.create({
19765
- enter: function(stateManager){
20052
+ enter: function(stateManager) {
19766
20053
  console.log("entering the poweredUp state. Destroy all humans.")
19767
20054
  }
19768
20055
  })
@@ -19785,12 +20072,12 @@ var sendEvent = function(eventName, sendRecursiveArguments, isUnhandledPass) {
19785
20072
  robotManager = Ember.StateManager.create({
19786
20073
  initialState: 'poweredDown',
19787
20074
  poweredDown: Ember.State.create({
19788
- exit: function(stateManager){
20075
+ exit: function(stateManager) {
19789
20076
  console.log("exiting the poweredDown state")
19790
20077
  }
19791
20078
  }),
19792
20079
  poweredUp: Ember.State.create({
19793
- enter: function(stateManager){
20080
+ enter: function(stateManager) {
19794
20081
  console.log("entering the poweredUp state. Destroy all humans.")
19795
20082
  }
19796
20083
  })
@@ -19853,37 +20140,37 @@ var sendEvent = function(eventName, sendRecursiveArguments, isUnhandledPass) {
19853
20140
  robotManager = Ember.StateManager.create({
19854
20141
  initialState: 'poweredDown',
19855
20142
  poweredDown: Ember.State.create({
19856
- enter: function(){},
19857
- exit: function(){
20143
+ enter: function() {},
20144
+ exit: function() {
19858
20145
  console.log("exited poweredDown state")
19859
20146
  },
19860
20147
  charging: Ember.State.create({
19861
- enter: function(){},
19862
- exit: function(){}
20148
+ enter: function() {},
20149
+ exit: function() {}
19863
20150
  }),
19864
20151
  charged: Ember.State.create({
19865
- enter: function(){
20152
+ enter: function() {
19866
20153
  console.log("entered charged state")
19867
20154
  },
19868
- exit: function(){
20155
+ exit: function() {
19869
20156
  console.log("exited charged state")
19870
20157
  }
19871
20158
  })
19872
20159
  }),
19873
20160
  poweredUp: Ember.State.create({
19874
- enter: function(){
20161
+ enter: function() {
19875
20162
  console.log("entered poweredUp state")
19876
20163
  },
19877
- exit: function(){},
20164
+ exit: function() {},
19878
20165
  mobile: Ember.State.create({
19879
- enter: function(){
20166
+ enter: function() {
19880
20167
  console.log("entered mobile state")
19881
20168
  },
19882
- exit: function(){}
20169
+ exit: function() {}
19883
20170
  }),
19884
20171
  stationary: Ember.State.create({
19885
- enter: function(){},
19886
- exit: function(){}
20172
+ enter: function() {},
20173
+ exit: function() {}
19887
20174
  })
19888
20175
  })
19889
20176
  })
@@ -19931,7 +20218,7 @@ var sendEvent = function(eventName, sendRecursiveArguments, isUnhandledPass) {
19931
20218
  initialState: 'stateOne.substateOne.subsubstateOne',
19932
20219
  stateOne: Ember.State.create({
19933
20220
  substateOne: Ember.State.create({
19934
- anAction: function(manager, context){
20221
+ anAction: function(manager, context) {
19935
20222
  console.log("an action was called")
19936
20223
  },
19937
20224
  subsubstateOne: Ember.State.create({})
@@ -19994,7 +20281,7 @@ var sendEvent = function(eventName, sendRecursiveArguments, isUnhandledPass) {
19994
20281
  })
19995
20282
  }),
19996
20283
  stateTwo: Ember.State.create({
19997
- anAction: function(manager, context){
20284
+ anAction: function(manager, context) {
19998
20285
  // will not be called below because it is
19999
20286
  // not a parent of the current state
20000
20287
  }
@@ -20015,18 +20302,18 @@ var sendEvent = function(eventName, sendRecursiveArguments, isUnhandledPass) {
20015
20302
  initialState: 'poweredDown.charging',
20016
20303
  poweredDown: Ember.State.create({
20017
20304
  charging: Ember.State.create({
20018
- chargeComplete: function(manager, context){
20305
+ chargeComplete: function(manager, context) {
20019
20306
  manager.transitionTo('charged')
20020
20307
  }
20021
20308
  }),
20022
20309
  charged: Ember.State.create({
20023
- boot: function(manager, context){
20310
+ boot: function(manager, context) {
20024
20311
  manager.transitionTo('poweredUp')
20025
20312
  }
20026
20313
  })
20027
20314
  }),
20028
20315
  poweredUp: Ember.State.create({
20029
- beginExtermination: function(manager, context){
20316
+ beginExtermination: function(manager, context) {
20030
20317
  manager.transitionTo('rampaging')
20031
20318
  },
20032
20319
  rampaging: Ember.State.create()
@@ -20065,7 +20352,7 @@ var sendEvent = function(eventName, sendRecursiveArguments, isUnhandledPass) {
20065
20352
 
20066
20353
  bManager = Ember.StateManager.create({
20067
20354
  stateOne: Ember.State.create({
20068
- changeToStateTwo: function(manager, context){
20355
+ changeToStateTwo: function(manager, context) {
20069
20356
  manager.transitionTo('stateTwo', context)
20070
20357
  }
20071
20358
  }),
@@ -20438,7 +20725,7 @@ define("metamorph",
20438
20725
  // Copyright: ©2011 My Company Inc. All rights reserved.
20439
20726
  // ==========================================================================
20440
20727
 
20441
- var K = function(){},
20728
+ var K = function() {},
20442
20729
  guid = 0,
20443
20730
  document = this.document,
20444
20731
 
@@ -20448,7 +20735,7 @@ define("metamorph",
20448
20735
  // Internet Explorer prior to 9 does not allow setting innerHTML if the first element
20449
20736
  // is a "zero-scope" element. This problem can be worked around by making
20450
20737
  // the first node an invisible text node. We, like Modernizr, use &shy;
20451
- needsShy = document && (function(){
20738
+ needsShy = document && (function() {
20452
20739
  var testEl = document.createElement('div');
20453
20740
  testEl.innerHTML = "<div></div>";
20454
20741
  testEl.firstChild.innerHTML = "<script></script>";
@@ -20904,12 +21191,12 @@ var objectCreate = Object.create || function(parent) {
20904
21191
  };
20905
21192
 
20906
21193
  var Handlebars = this.Handlebars || (Ember.imports && Ember.imports.Handlebars);
20907
- if(!Handlebars && typeof require === 'function') {
21194
+ if (!Handlebars && typeof require === 'function') {
20908
21195
  Handlebars = require('handlebars');
20909
21196
  }
20910
21197
 
20911
- Ember.assert("Ember Handlebars requires Handlebars version 1.0.0. Include a SCRIPT tag in the HTML HEAD linking to the Handlebars file before you link to Ember.", Handlebars)
20912
- Ember.assert("Ember Handlebars requires Handlebars version 1.0.0, COMPILER_REVISION expected: 4, got: " + Handlebars.COMPILER_REVISION + " Please note: Builds of master may have other COMPILER_REVISION values.", Handlebars.COMPILER_REVISION === 4);
21198
+ Ember.assert("Ember Handlebars requires Handlebars version 1.0.0. Include a SCRIPT tag in the HTML HEAD linking to the Handlebars file before you link to Ember.", Handlebars);
21199
+ Ember.assert("Ember Handlebars requires Handlebars version 1.0.0, COMPILER_REVISION expected: 4, got: " + Handlebars.COMPILER_REVISION + " - Please note: Builds of master may have other COMPILER_REVISION values.", Handlebars.COMPILER_REVISION === 4);
20913
21200
 
20914
21201
  /**
20915
21202
  Prepares the Handlebars templating library for use inside Ember's view
@@ -21008,14 +21295,14 @@ Ember.Handlebars.helper = function(name, value) {
21008
21295
 
21009
21296
  if (Ember.View.detect(value)) {
21010
21297
  Ember.Handlebars.registerHelper(name, function(options) {
21011
- Ember.assert("You can only pass attributes as parameters (not values) to a application-defined helper", arguments.length < 2);
21298
+ Ember.assert("You can only pass attributes (such as name=value) not bare values to a helper for a View", arguments.length < 2);
21012
21299
  makeBindings(options);
21013
21300
  return Ember.Handlebars.helpers.view.call(this, value, options);
21014
21301
  });
21015
21302
  } else {
21016
21303
  Ember.Handlebars.registerBoundHelper.apply(null, arguments);
21017
21304
  }
21018
- }
21305
+ };
21019
21306
 
21020
21307
  /**
21021
21308
  @class helpers
@@ -21101,7 +21388,7 @@ Ember.Handlebars.Compiler.prototype.mustache = function(mustache) {
21101
21388
  // Update the mustache node to include a hash value indicating whether the original node
21102
21389
  // was escaped. This will allow us to properly escape values when the underlying value
21103
21390
  // changes and we need to re-render the value.
21104
- if(!mustache.escaped) {
21391
+ if (!mustache.escaped) {
21105
21392
  mustache.hash = mustache.hash || new Handlebars.AST.HashNode([]);
21106
21393
  mustache.hash.pairs.push(["unescaped", new Handlebars.AST.StringNode("true")]);
21107
21394
  }
@@ -21299,7 +21586,7 @@ Ember.Handlebars.registerHelper('helperMissing', function(path, options) {
21299
21586
  var error, view = "";
21300
21587
 
21301
21588
  error = "%@ Handlebars error: Could not find property '%@' on object %@.";
21302
- if (options.data){
21589
+ if (options.data) {
21303
21590
  view = options.data.view;
21304
21591
  }
21305
21592
  throw new Ember.Error(Ember.String.fmt(error, [view, path, this]));
@@ -21336,7 +21623,7 @@ Ember.Handlebars.registerHelper('helperMissing', function(path, options) {
21336
21623
  Ember.Handlebars.registerBoundHelper('repeat', function(value, options) {
21337
21624
  var count = options.hash.count;
21338
21625
  var a = [];
21339
- while(a.length < count){
21626
+ while(a.length < count) {
21340
21627
  a.push(value);
21341
21628
  }
21342
21629
  return a.join('');
@@ -21380,7 +21667,7 @@ Ember.Handlebars.registerHelper('helperMissing', function(path, options) {
21380
21667
 
21381
21668
  ```javascript
21382
21669
  Ember.Handlebars.registerBoundHelper('concatenate', function() {
21383
- var values = arguments[arguments.length - 1];
21670
+ var values = Array.prototype.slice.call(arguments, 0, -1);
21384
21671
  return values.join('||');
21385
21672
  });
21386
21673
  ```
@@ -21427,7 +21714,7 @@ Ember.Handlebars.registerBoundHelper = function(name, fn) {
21427
21714
  view = data.view,
21428
21715
  currentContext = (options.contexts && options.contexts[0]) || this,
21429
21716
  normalized,
21430
- pathRoot, path,
21717
+ pathRoot, path, prefixPathForDependentKeys = '',
21431
21718
  loc, hashOption;
21432
21719
 
21433
21720
  Ember.assert("registerBoundHelper-generated helpers do not support use with Handlebars blocks.", !options.fn);
@@ -21478,8 +21765,11 @@ Ember.Handlebars.registerBoundHelper = function(name, fn) {
21478
21765
 
21479
21766
  view.registerObserver(pathRoot, path, bindView, bindView.rerender);
21480
21767
 
21768
+ if(!Ember.isEmpty(path)) {
21769
+ prefixPathForDependentKeys = path + '.';
21770
+ }
21481
21771
  for (var i=0, l=dependentKeys.length; i<l; i++) {
21482
- view.registerObserver(pathRoot, path + '.' + dependentKeys[i], bindView, bindView.rerender);
21772
+ view.registerObserver(pathRoot, prefixPathForDependentKeys + dependentKeys[i], bindView, bindView.rerender);
21483
21773
  }
21484
21774
  }
21485
21775
 
@@ -21586,7 +21876,7 @@ function evaluateUnboundHelper(context, fn, normalizedProperties, options) {
21586
21876
  @for Ember.Handlebars
21587
21877
  @param {String} template spec
21588
21878
  */
21589
- Ember.Handlebars.template = function(spec){
21879
+ Ember.Handlebars.template = function(spec) {
21590
21880
  var t = Handlebars.template(spec);
21591
21881
  t.isTop = true;
21592
21882
  return t;
@@ -21598,10 +21888,19 @@ Ember.Handlebars.template = function(spec){
21598
21888
 
21599
21889
  (function() {
21600
21890
  /**
21601
- @method htmlSafe
21602
- @for Ember.String
21603
- @static
21604
- */
21891
+ * Mark a string as safe for unescaped output with Handlebars. If you
21892
+ * return HTML from a Handlebars helper, use this function to
21893
+ * ensure Handlebars does not escape the HTML.
21894
+ *
21895
+ * ```javascript
21896
+ * Ember.String.htmlSafe('<div>someString</div>')
21897
+ * ```
21898
+ *
21899
+ * @method htmlSafe
21900
+ * @for Ember.String
21901
+ * @static
21902
+ * @return {Handlebars.SafeString} a string that will not be html escaped by Handlebars
21903
+ */
21605
21904
  Ember.String.htmlSafe = function(str) {
21606
21905
  return new Handlebars.SafeString(str);
21607
21906
  };
@@ -21611,11 +21910,18 @@ var htmlSafe = Ember.String.htmlSafe;
21611
21910
  if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {
21612
21911
 
21613
21912
  /**
21614
- See `Ember.String.htmlSafe`.
21615
-
21616
- @method htmlSafe
21617
- @for String
21618
- */
21913
+ * Mark a string as being safe for unescaped output with Handlebars.
21914
+ *
21915
+ * ```javascript
21916
+ * '<div>someString</div>'.htmlSafe()
21917
+ * ```
21918
+ *
21919
+ * See `Ember.String.htmlSafe`.
21920
+ *
21921
+ * @method htmlSafe
21922
+ * @for String
21923
+ * @return {Handlebars.SafeString} a string that will not be html escaped by Handlebars
21924
+ */
21619
21925
  String.prototype.htmlSafe = function() {
21620
21926
  return htmlSafe(this);
21621
21927
  };
@@ -21720,7 +22026,6 @@ var DOMManager = {
21720
22026
  /**
21721
22027
  @class _Metamorph
21722
22028
  @namespace Ember
21723
- @extends Ember.Mixin
21724
22029
  @private
21725
22030
  */
21726
22031
  Ember._Metamorph = Ember.Mixin.create({
@@ -22115,7 +22420,7 @@ var forEach = Ember.ArrayPolyfills.forEach;
22115
22420
 
22116
22421
  var EmberHandlebars = Ember.Handlebars, helpers = EmberHandlebars.helpers;
22117
22422
 
22118
- function exists(value){
22423
+ function exists(value) {
22119
22424
  return !Ember.isNone(value);
22120
22425
  }
22121
22426
 
@@ -22140,7 +22445,7 @@ function bind(property, options, preserveContext, shouldDisplay, valueNormalizer
22140
22445
 
22141
22446
  var template, context, result = handlebarsGet(currentContext, property, options);
22142
22447
 
22143
- result = valueNormalizer(result);
22448
+ result = valueNormalizer ? valueNormalizer(result) : result;
22144
22449
 
22145
22450
  context = preserveContext ? currentContext : result;
22146
22451
  if (shouldDisplay(result)) {
@@ -22465,7 +22770,7 @@ EmberHandlebars.registerHelper('unless', function(context, options) {
22465
22770
 
22466
22771
  ```javascript
22467
22772
  AView = Ember.View.extend({
22468
- someProperty: function(){
22773
+ someProperty: function() {
22469
22774
  return "aValue";
22470
22775
  }.property()
22471
22776
  })
@@ -22568,7 +22873,7 @@ EmberHandlebars.registerHelper('bindAttr', function(options) {
22568
22873
  var path = attrs[attr],
22569
22874
  normalized;
22570
22875
 
22571
- Ember.assert(fmt("You must provide a String for a bound attribute, not %@", [path]), typeof path === 'string');
22876
+ Ember.assert(fmt("You must provide an expression as the value of bound attribute. You specified: %@=%@", [attr, path]), typeof path === 'string');
22572
22877
 
22573
22878
  normalized = normalizePath(ctx, path, options.data);
22574
22879
 
@@ -22754,6 +23059,8 @@ EmberHandlebars.bindClasses = function(context, classBindings, view, bindAttrId,
22754
23059
 
22755
23060
  var get = Ember.get, set = Ember.set;
22756
23061
  var EmberHandlebars = Ember.Handlebars;
23062
+ var LOWERCASE_A_Z = /^[a-z]/;
23063
+ var VIEW_PREFIX = /^view\./;
22757
23064
 
22758
23065
  EmberHandlebars.ViewHelper = Ember.Object.create({
22759
23066
 
@@ -22865,7 +23172,18 @@ EmberHandlebars.ViewHelper = Ember.Object.create({
22865
23172
  newView;
22866
23173
 
22867
23174
  if ('string' === typeof path) {
22868
- newView = EmberHandlebars.get(thisContext, path, options);
23175
+
23176
+ // TODO: this is a lame conditional, this should likely change
23177
+ // but something along these lines will likely need to be added
23178
+ // as deprecation warnings
23179
+ //
23180
+ if (options.types[0] === 'STRING' && LOWERCASE_A_Z.test(path) && !VIEW_PREFIX.test(path)) {
23181
+ Ember.assert("View requires a container", !!data.view.container);
23182
+ newView = data.view.container.lookupFactory('view:' + path);
23183
+ } else {
23184
+ newView = EmberHandlebars.get(thisContext, path, options);
23185
+ }
23186
+
22869
23187
  Ember.assert("Unable to find view at path '" + path + "'", !!newView);
22870
23188
  } else {
22871
23189
  newView = path;
@@ -23234,11 +23552,25 @@ Ember.Handlebars.registerHelper('collection', function(path, options) {
23234
23552
  var hash = options.hash, itemHash = {}, match;
23235
23553
 
23236
23554
  // Extract item view class if provided else default to the standard class
23237
- var itemViewClass, itemViewPath = hash.itemViewClass;
23238
- var collectionPrototype = collectionClass.proto();
23555
+ var collectionPrototype = collectionClass.proto(),
23556
+ itemViewClass;
23557
+
23558
+ if (hash.itemView) {
23559
+ var controller = data.keywords.controller;
23560
+ Ember.assert('You specified an itemView, but the current context has no container to look the itemView up in. This probably means that you created a view manually, instead of through the container. Instead, use container.lookup("view:viewName"), which will properly instantiate your view.', controller && controller.container);
23561
+ var container = controller.container;
23562
+ itemViewClass = container.resolve('view:' + Ember.String.camelize(hash.itemView));
23563
+ Ember.assert('You specified the itemView ' + hash.itemView + ", but it was not found at " + container.describe("view:" + hash.itemView) + " (and it was not registered in the container)", !!itemViewClass);
23564
+ } else if (hash.itemViewClass) {
23565
+ itemViewClass = handlebarsGet(collectionPrototype, hash.itemViewClass, options);
23566
+ } else {
23567
+ itemViewClass = collectionPrototype.itemViewClass;
23568
+ }
23569
+
23570
+ Ember.assert(fmt("%@ #collection: Could not find itemViewClass %@", [data.view, itemViewClass]), !!itemViewClass);
23571
+
23239
23572
  delete hash.itemViewClass;
23240
- itemViewClass = itemViewPath ? handlebarsGet(collectionPrototype, itemViewPath, options) : collectionPrototype.itemViewClass;
23241
- Ember.assert(fmt("%@ #collection: Could not find itemViewClass %@", [data.view, itemViewPath]), !!itemViewClass);
23573
+ delete hash.itemView;
23242
23574
 
23243
23575
  // Go through options passed to the {{collection}} helper and extract options
23244
23576
  // that configure item views instead of the collection itself.
@@ -23246,7 +23578,7 @@ Ember.Handlebars.registerHelper('collection', function(path, options) {
23246
23578
  if (hash.hasOwnProperty(prop)) {
23247
23579
  match = prop.match(/^item(.)(.*)$/);
23248
23580
 
23249
- if(match && prop !== 'itemController') {
23581
+ if (match && prop !== 'itemController') {
23250
23582
  // Convert itemShouldFoo -> shouldFoo
23251
23583
  itemHash[match[1].toLowerCase() + match[2]] = hash[prop];
23252
23584
  // Delete from hash as this will end up getting passed to the
@@ -23273,7 +23605,7 @@ Ember.Handlebars.registerHelper('collection', function(path, options) {
23273
23605
  }
23274
23606
  if (emptyViewClass) { hash.emptyView = emptyViewClass; }
23275
23607
 
23276
- if(!hash.keyword){
23608
+ if (!hash.keyword) {
23277
23609
  itemHash._context = Ember.computed.alias('content');
23278
23610
  }
23279
23611
 
@@ -23320,7 +23652,7 @@ var handlebarsGet = Ember.Handlebars.get;
23320
23652
  Ember.Handlebars.registerHelper('unbound', function(property, fn) {
23321
23653
  var options = arguments[arguments.length - 1], helper, context, out;
23322
23654
 
23323
- if(arguments.length > 2) {
23655
+ if (arguments.length > 2) {
23324
23656
  // Unbound helper call.
23325
23657
  options.data.isUnbound = true;
23326
23658
  helper = Ember.Handlebars.helpers[arguments[0]] || Ember.Handlebars.helperMissing;
@@ -23378,7 +23710,7 @@ Ember.Handlebars.registerHelper('log', function(property, options) {
23378
23710
  @for Ember.Handlebars.helpers
23379
23711
  @param {String} property
23380
23712
  */
23381
- Ember.Handlebars.registerHelper('debugger', function() {
23713
+ Ember.Handlebars.registerHelper('debugger', function(options) {
23382
23714
  debugger;
23383
23715
  });
23384
23716
 
@@ -23424,6 +23756,11 @@ Ember.Handlebars.EachView = Ember.CollectionView.extend(Ember._Metamorph, {
23424
23756
  return this._super();
23425
23757
  },
23426
23758
 
23759
+ _assertArrayLike: function(content) {
23760
+ Ember.assert("The value that #each loops over must be an Array. You passed " + content.constructor + ", but it should have been an ArrayController", !Ember.ControllerMixin.detect(content) || (content && content.isGenerated) || content instanceof Ember.ArrayController);
23761
+ Ember.assert("The value that #each loops over must be an Array. You passed " + ((Ember.ControllerMixin.detect(content) && content.get('model') !== undefined) ? ("" + content.get('model') + " (wrapped in " + content + ")") : ("" + content)), Ember.Array.detect(content));
23762
+ },
23763
+
23427
23764
  disableContentObservers: function(callback) {
23428
23765
  Ember.removeBeforeObserver(this, 'content', null, '_contentWillChange');
23429
23766
  Ember.removeObserver(this, 'content', null, '_contentDidChange');
@@ -23654,6 +23991,12 @@ GroupedEach.prototype = {
23654
23991
  </div>
23655
23992
  ```
23656
23993
 
23994
+ If an `itemViewClass` is defined on the helper, and therefore the helper is not
23995
+ being used as a block, an `emptyViewClass` can also be provided optionally.
23996
+ The `emptyViewClass` will match the behavior of the `{{else}}` condition
23997
+ described above. That is, the `emptyViewClass` will render if the collection
23998
+ is empty.
23999
+
23657
24000
  ### Representing each item with a Controller.
23658
24001
  By default the controller lookup within an `{{#each}}` block will be
23659
24002
  the controller of the template where the `{{#each}}` was used. If each
@@ -23667,7 +24010,7 @@ GroupedEach.prototype = {
23667
24010
 
23668
24011
  ```javascript
23669
24012
  App.DeveloperController = Ember.ObjectController.extend({
23670
- isAvailableForHire: function(){
24013
+ isAvailableForHire: function() {
23671
24014
  return !this.get('content.isEmployed') && this.get('content.isSeekingWork');
23672
24015
  }.property('isEmployed', 'isSeekingWork')
23673
24016
  })
@@ -23767,18 +24110,15 @@ Ember.Handlebars.registerHelper('each', function(path, options) {
23767
24110
  Ember.TEMPLATES["my_cool_template"] = Ember.Handlebars.compile('<b>{{user}}</b>');
23768
24111
  ```
23769
24112
 
24113
+ @deprecated
23770
24114
  @method template
23771
24115
  @for Ember.Handlebars.helpers
23772
24116
  @param {String} templateName the template to render
23773
24117
  */
23774
24118
 
23775
24119
  Ember.Handlebars.registerHelper('template', function(name, options) {
23776
- var view = options.data.view,
23777
- template = view.templateForName(name);
23778
-
23779
- Ember.assert("Unable to find template with name '"+name+"'.", !!template);
23780
-
23781
- template(this, { data: options.data });
24120
+ Ember.deprecate("The `template` helper has been deprecated in favor of the `partial` helper. Please use `partial` instead, which will work the same way.");
24121
+ return Ember.Handlebars.helpers.partial.apply(this, arguments);
23782
24122
  });
23783
24123
 
23784
24124
  })();
@@ -23828,7 +24168,6 @@ Ember.Handlebars.registerHelper('partial', function(name, options) {
23828
24168
  template = view.templateForName(underscoredName),
23829
24169
  deprecatedTemplate = !template && view.templateForName(name);
23830
24170
 
23831
- Ember.deprecate("You tried to render the partial " + name + ", which should be at '" + underscoredName + "', but Ember found '" + name + "'. Please use a leading underscore in your partials", template);
23832
24171
  Ember.assert("Unable to find partial with name '"+name+"'.", template || deprecatedTemplate);
23833
24172
 
23834
24173
  template = template || deprecatedTemplate;
@@ -23900,7 +24239,7 @@ var get = Ember.get, set = Ember.set;
23900
24239
  @return {String} HTML string
23901
24240
  */
23902
24241
  Ember.Handlebars.registerHelper('yield', function(options) {
23903
- var view = options.data.view, template;
24242
+ var currentView = options.data.view, view = currentView, template;
23904
24243
 
23905
24244
  while (view && !get(view, 'layout')) {
23906
24245
  view = get(view, 'parentView');
@@ -23910,7 +24249,48 @@ Ember.Handlebars.registerHelper('yield', function(options) {
23910
24249
 
23911
24250
  template = get(view, 'template');
23912
24251
 
23913
- if (template) { template(this, options); }
24252
+ var keywords = view._parentView.cloneKeywords();
24253
+
24254
+ currentView.appendChild(Ember.View, {
24255
+ isVirtual: true,
24256
+ tagName: '',
24257
+ template: template,
24258
+ context: get(view._parentView, 'context'),
24259
+ controller: get(view._parentView, 'controller'),
24260
+ templateData: {keywords: keywords}
24261
+ });
24262
+ });
24263
+
24264
+ })();
24265
+
24266
+
24267
+
24268
+ (function() {
24269
+ /**
24270
+ @module ember
24271
+ @submodule ember-handlebars
24272
+ */
24273
+
24274
+ /**
24275
+ `loc` looks up the string in the localized strings hash.
24276
+ This is a convenient way to localize text. For example:
24277
+
24278
+ ```html
24279
+ <script type="text/x-handlebars" data-template-name="home">
24280
+ {{loc welcome}}
24281
+ </script>
24282
+ ```
24283
+
24284
+ Take note that `welcome` is a string and not an object
24285
+ reference.
24286
+
24287
+ @method loc
24288
+ @for Ember.Handlebars.helpers
24289
+ @param {String} str The string to format
24290
+ */
24291
+
24292
+ Ember.Handlebars.registerHelper('loc', function(str) {
24293
+ return Ember.String.loc(str);
23914
24294
  });
23915
24295
 
23916
24296
  })();
@@ -23980,17 +24360,23 @@ Ember.Checkbox = Ember.View.extend({
23980
24360
 
23981
24361
  tagName: 'input',
23982
24362
 
23983
- attributeBindings: ['type', 'checked', 'disabled', 'tabindex', 'name'],
24363
+ attributeBindings: ['type', 'checked', 'indeterminate', 'disabled', 'tabindex', 'name'],
23984
24364
 
23985
24365
  type: "checkbox",
23986
24366
  checked: false,
23987
24367
  disabled: false,
24368
+ indeterminate: false,
23988
24369
 
23989
24370
  init: function() {
23990
24371
  this._super();
23991
24372
  this.on("change", this, this._updateElementValue);
23992
24373
  },
23993
24374
 
24375
+ didInsertElement: function() {
24376
+ this._super();
24377
+ this.get('element').indeterminate = !!this.get('indeterminate');
24378
+ },
24379
+
23994
24380
  _updateElementValue: function() {
23995
24381
  set(this, 'checked', this.$().prop('checked'));
23996
24382
  }
@@ -24013,7 +24399,6 @@ var get = Ember.get, set = Ember.set;
24013
24399
 
24014
24400
  @class TextSupport
24015
24401
  @namespace Ember
24016
- @extends Ember.Mixin
24017
24402
  @private
24018
24403
  */
24019
24404
  Ember.TextSupport = Ember.Mixin.create({
@@ -25025,9 +25410,9 @@ function program7(depth0,data) {
25025
25410
  content = get(this, 'content'),
25026
25411
  selection = get(this, 'selection');
25027
25412
 
25028
- if (!content){ return; }
25413
+ if (!content) { return; }
25029
25414
  if (options) {
25030
- var selectedIndexes = options.map(function(){
25415
+ var selectedIndexes = options.map(function() {
25031
25416
  return this.index - offset;
25032
25417
  }).toArray();
25033
25418
  var newSelection = content.objectsAt(selectedIndexes);
@@ -25116,7 +25501,7 @@ Ember.Handlebars.registerHelper('input', function(options) {
25116
25501
  if (inputType === 'checkbox') {
25117
25502
  return Ember.Handlebars.helpers.view.call(this, Ember.Checkbox, options);
25118
25503
  } else {
25119
- hash.type = inputType;
25504
+ if (inputType) { hash.type = inputType; }
25120
25505
  hash.onEvent = onEvent || 'enter';
25121
25506
  return Ember.Handlebars.helpers.view.call(this, Ember.TextField, options);
25122
25507
  }
@@ -25962,7 +26347,7 @@ Ember.Application.registerInjection({
25962
26347
  var name = property.charAt(0).toLowerCase() + property.substr(1),
25963
26348
  controllerClass = app[property], controller;
25964
26349
 
25965
- if(!Ember.Object.detect(controllerClass)){ return; }
26350
+ if (!Ember.Object.detect(controllerClass)) { return; }
25966
26351
  controller = app[property].create();
25967
26352
 
25968
26353
  router.set(name, controller);
@@ -26083,7 +26468,6 @@ var merge = function(original, hash) {
26083
26468
  /**
26084
26469
  @class Routable
26085
26470
  @namespace Ember
26086
- @extends Ember.Mixin
26087
26471
  */
26088
26472
  Ember.Routable = Ember.Mixin.create({
26089
26473
  init: function() {
@@ -27015,7 +27399,7 @@ Ember.HistoryLocation = Ember.Object.extend({
27015
27399
  var guid = Ember.guidFor(this);
27016
27400
 
27017
27401
  Ember.$(window).on('popstate.ember-location-'+guid, function(e) {
27018
- if(!popstateReady) {
27402
+ if (!popstateReady) {
27019
27403
  return;
27020
27404
  }
27021
27405
  callback(location.pathname);
@@ -27847,7 +28231,7 @@ ActionHelper.registerAction = function(actionName, options) {
27847
28231
  ```javascript
27848
28232
  AView = Ember.View.extend({
27849
28233
  templateName: 'a-template',
27850
- anActionName: function(event){}
28234
+ anActionName: function(event) {}
27851
28235
  });
27852
28236
 
27853
28237
  aView = AView.create();
@@ -27973,7 +28357,7 @@ ActionHelper.registerAction = function(actionName, options) {
27973
28357
  AView = Ember.View.extend({
27974
28358
  templateName; 'a-template',
27975
28359
  // note: no method 'aMethodNameThatIsMissing'
27976
- anActionName: function(event){}
28360
+ anActionName: function(event) {}
27977
28361
  });
27978
28362
 
27979
28363
  aView = AView.create();