ember-source 1.0.0.rc5.1 → 1.0.0.rc6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

@@ -1,5 +1,5 @@
1
- // Version: v1.0.0-rc.5-2-g9dc4ad8
2
- // Last commit: 9dc4ad8 (2013-07-25 20:19:21 -0400)
1
+ // Version: v1.0.0-rc.6-1-g42f0c68
2
+ // Last commit: 42f0c68 (2013-06-23 15:43:35 -0400)
3
3
 
4
4
 
5
5
  (function() {
@@ -49,7 +49,12 @@ if (!('MANDATORY_SETTER' in Ember.ENV)) {
49
49
  falsy, an exception will be thrown.
50
50
  */
51
51
  Ember.assert = function(desc, test) {
52
- if (!test) throw new Error("assertion failed: "+desc);
52
+ Ember.Logger.assert(test, desc);
53
+
54
+ if (Ember.testing && !test) {
55
+ // when testing, ensure test failures when assertions fail
56
+ throw new Error("Assertion Failed: " + desc);
57
+ }
53
58
  };
54
59
 
55
60
 
@@ -95,12 +100,12 @@ Ember.debug = function(message) {
95
100
  will be displayed.
96
101
  */
97
102
  Ember.deprecate = function(message, test) {
98
- if (Ember && Ember.TESTING_DEPRECATION) { return; }
103
+ if (Ember.TESTING_DEPRECATION) { return; }
99
104
 
100
105
  if (arguments.length === 1) { test = false; }
101
106
  if (test) { return; }
102
107
 
103
- if (Ember && Ember.ENV.RAISE_ON_DEPRECATION) { throw new Error(message); }
108
+ if (Ember.ENV.RAISE_ON_DEPRECATION) { throw new Error(message); }
104
109
 
105
110
  var error;
106
111
 
@@ -151,8 +156,8 @@ Ember.deprecateFunc = function(message, func) {
151
156
 
152
157
  })();
153
158
 
154
- // Version: v1.0.0-rc.5-2-g9dc4ad8
155
- // Last commit: 9dc4ad8 (2013-07-25 20:19:21 -0400)
159
+ // Version: v1.0.0-rc.6-1-g42f0c68
160
+ // Last commit: 42f0c68 (2013-06-23 15:43:35 -0400)
156
161
 
157
162
 
158
163
  (function() {
@@ -219,7 +224,7 @@ var define, requireModule;
219
224
 
220
225
  @class Ember
221
226
  @static
222
- @version 1.0.0-rc.5
227
+ @version 1.0.0-rc.6
223
228
  */
224
229
 
225
230
  if ('undefined' === typeof Ember) {
@@ -246,10 +251,10 @@ Ember.toString = function() { return "Ember"; };
246
251
  /**
247
252
  @property VERSION
248
253
  @type String
249
- @default '1.0.0-rc.5'
254
+ @default '1.0.0-rc.6'
250
255
  @final
251
256
  */
252
- Ember.VERSION = '1.0.0-rc.5';
257
+ Ember.VERSION = '1.0.0-rc.6';
253
258
 
254
259
  /**
255
260
  Standard environmental variables. You can define these in a global `ENV`
@@ -364,6 +369,19 @@ function consoleMethod(name) {
364
369
  }
365
370
  }
366
371
 
372
+ function assertPolyfill(test, message) {
373
+ if (!test) {
374
+ try {
375
+ // attempt to preserve the stack
376
+ throw new Error("assertion failed: " + message);
377
+ } catch(error) {
378
+ setTimeout(function(){
379
+ throw error;
380
+ }, 0);
381
+ }
382
+ }
383
+ }
384
+
367
385
  /**
368
386
  Inside Ember-Metal, simply uses the methods from `imports.console`.
369
387
  Override this to provide more robust logging functionality.
@@ -376,7 +394,8 @@ Ember.Logger = {
376
394
  warn: consoleMethod('warn') || Ember.K,
377
395
  error: consoleMethod('error') || Ember.K,
378
396
  info: consoleMethod('info') || Ember.K,
379
- debug: consoleMethod('debug') || consoleMethod('info') || Ember.K
397
+ debug: consoleMethod('debug') || consoleMethod('info') || Ember.K,
398
+ assert: consoleMethod('assert') || assertPolyfill
380
399
  };
381
400
 
382
401
 
@@ -1644,6 +1663,7 @@ get = function get(obj, keyName) {
1644
1663
  obj = null;
1645
1664
  }
1646
1665
 
1666
+ Ember.assert("Cannot call get with "+ keyName +" key.", !!keyName);
1647
1667
  Ember.assert("Cannot call get with '"+ keyName +"' on an undefined object.", obj !== undefined);
1648
1668
 
1649
1669
  if (obj === null || keyName.indexOf('.') !== -1) {
@@ -1676,12 +1696,21 @@ if (Ember.config.overrideAccessors) {
1676
1696
  get = Ember.get;
1677
1697
  }
1678
1698
 
1679
- function firstKey(path) {
1680
- return path.match(FIRST_KEY)[0];
1681
- }
1699
+ /**
1700
+ @private
1701
+
1702
+ Normalizes a target/path pair to reflect that actual target/path that should
1703
+ be observed, etc. This takes into account passing in global property
1704
+ paths (i.e. a path beginning with a captial letter not defined on the
1705
+ target) and * separators.
1682
1706
 
1683
- // assumes path is already normalized
1684
- function normalizeTuple(target, path) {
1707
+ @method normalizeTuple
1708
+ @for Ember
1709
+ @param {Object} target The current target. May be `null`.
1710
+ @param {String} path A path on the target or a global property path.
1711
+ @return {Array} a temporary array with the normalized target/path pair.
1712
+ */
1713
+ var normalizeTuple = Ember.normalizeTuple = function(target, path) {
1685
1714
  var hasThis = HAS_THIS.test(path),
1686
1715
  isGlobal = !hasThis && IS_GLOBAL_PATH.test(path),
1687
1716
  key;
@@ -1690,7 +1719,7 @@ function normalizeTuple(target, path) {
1690
1719
  if (hasThis) path = path.slice(5);
1691
1720
 
1692
1721
  if (target === Ember.lookup) {
1693
- key = firstKey(path);
1722
+ key = path.match(FIRST_KEY)[0];
1694
1723
  target = get(target, key);
1695
1724
  path = path.slice(key.length+1);
1696
1725
  }
@@ -1699,7 +1728,7 @@ function normalizeTuple(target, path) {
1699
1728
  if (!path || path.length===0) throw new Error('Invalid Path');
1700
1729
 
1701
1730
  return [ target, path ];
1702
- }
1731
+ };
1703
1732
 
1704
1733
  var getPath = Ember._getPath = function(root, path) {
1705
1734
  var hasThis, parts, tuple, idx, len;
@@ -1728,24 +1757,6 @@ var getPath = Ember._getPath = function(root, path) {
1728
1757
  return root;
1729
1758
  };
1730
1759
 
1731
- /**
1732
- @private
1733
-
1734
- Normalizes a target/path pair to reflect that actual target/path that should
1735
- be observed, etc. This takes into account passing in global property
1736
- paths (i.e. a path beginning with a captial letter not defined on the
1737
- target) and * separators.
1738
-
1739
- @method normalizeTuple
1740
- @for Ember
1741
- @param {Object} target The current target. May be `null`.
1742
- @param {String} path A path on the target or a global property path.
1743
- @return {Array} a temporary array with the normalized target/path pair.
1744
- */
1745
- Ember.normalizeTuple = function(target, path) {
1746
- return normalizeTuple(target, path);
1747
- };
1748
-
1749
1760
  Ember.getWithDefault = function(root, key, defaultValue) {
1750
1761
  var value = get(root, key);
1751
1762
 
@@ -2465,6 +2476,8 @@ var set = function set(obj, keyName, value, tolerant) {
2465
2476
  obj = null;
2466
2477
  }
2467
2478
 
2479
+ Ember.assert("Cannot call set with "+ keyName +" key.", !!keyName);
2480
+
2468
2481
  if (!obj || keyName.indexOf('.') !== -1) {
2469
2482
  return setPath(obj, keyName, value, tolerant);
2470
2483
  }
@@ -3116,9 +3129,9 @@ var changeProperties = Ember.changeProperties,
3116
3129
  observers will be buffered.
3117
3130
 
3118
3131
  @method setProperties
3119
- @param target
3120
- @param {Hash} properties
3121
- @return target
3132
+ @param self
3133
+ @param {Object} hash
3134
+ @return self
3122
3135
  */
3123
3136
  Ember.setProperties = function(self, hash) {
3124
3137
  changeProperties(function(){
@@ -4758,7 +4771,7 @@ define("backburner",
4758
4771
  },
4759
4772
 
4760
4773
  cancel: function(timer) {
4761
- if (typeof timer === 'object' && timer.queue && timer.method) { // we're cancelling a deferOnce
4774
+ if (timer && typeof timer === 'object' && timer.queue && timer.method) { // we're cancelling a deferOnce
4762
4775
  return timer.queue.cancel(timer);
4763
4776
  } else if (typeof timer === 'function') { // we're cancelling a setTimeout
4764
4777
  for (var i = 0, l = timers.length; i < l; i += 2) {
@@ -4767,6 +4780,8 @@ define("backburner",
4767
4780
  return true;
4768
4781
  }
4769
4782
  }
4783
+ } else {
4784
+ return; // timer was null or not a timer
4770
4785
  }
4771
4786
  }
4772
4787
  };
@@ -4859,7 +4874,7 @@ define("backburner/deferred_action_queues",
4859
4874
  while (queueNameIndex < numberOfQueues) {
4860
4875
  queueName = queueNames[queueNameIndex];
4861
4876
  queue = queues[queueName];
4862
- queueItems = queue._queue.slice();
4877
+ queueItems = queue._queueBeingFlushed = queue._queue.slice();
4863
4878
  queue._queue = [];
4864
4879
 
4865
4880
  var options = queue.options,
@@ -4877,15 +4892,19 @@ define("backburner/deferred_action_queues",
4877
4892
 
4878
4893
  if (typeof method === 'string') { method = target[method]; }
4879
4894
 
4880
- // TODO: error handling
4881
- if (args && args.length > 0) {
4882
- method.apply(target, args);
4883
- } else {
4884
- method.call(target);
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
+ }
4885
4903
  }
4886
4904
 
4887
4905
  queueIndex += 4;
4888
4906
  }
4907
+ queue._queueBeingFlushed = null;
4889
4908
  if (numberOfQueueItems && after) { after(); }
4890
4909
 
4891
4910
  if ((priorQueueNameIndex = indexOfPriorQueueWithActions(this, queueNameIndex)) !== -1) {
@@ -4910,6 +4929,7 @@ define("backburner/deferred_action_queues",
4910
4929
  return -1;
4911
4930
  }
4912
4931
 
4932
+
4913
4933
  __exports__.DeferredActionQueues = DeferredActionQueues;
4914
4934
  });
4915
4935
 
@@ -4999,12 +5019,30 @@ define("backburner/queue",
4999
5019
  return true;
5000
5020
  }
5001
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
+ }
5002
5040
  }
5003
5041
  };
5004
5042
 
5043
+
5005
5044
  __exports__.Queue = Queue;
5006
5045
  });
5007
-
5008
5046
  })();
5009
5047
 
5010
5048
 
@@ -5112,7 +5150,7 @@ Ember.run = function(target, method) {
5112
5150
  May be a function or a string. If you pass a string
5113
5151
  then it will be looked up on the passed target.
5114
5152
  @param {Object} [args*] Any additional arguments you wish to pass to the method.
5115
- @return {Object} return value from invoking the passed function. Please note,
5153
+ @return {Object} return value from invoking the passed function. Please note,
5116
5154
  when called within an existing loop, no return value is possible.
5117
5155
  */
5118
5156
  Ember.run.join = function(target, method) {
@@ -5248,7 +5286,9 @@ Ember.run.cancelTimers = function () {
5248
5286
  @return {void}
5249
5287
  */
5250
5288
  Ember.run.sync = function() {
5251
- backburner.currentInstance.queues.sync.flush();
5289
+ if (backburner.currentInstance) {
5290
+ backburner.currentInstance.queues.sync.flush();
5291
+ }
5252
5292
  };
5253
5293
 
5254
5294
  /**
@@ -5441,6 +5481,38 @@ Ember.run.cancel = function(timer) {
5441
5481
  return backburner.cancel(timer);
5442
5482
  };
5443
5483
 
5484
+ /**
5485
+ Execute the passed method in a specified amount of time, reset timer
5486
+ upon additional calls.
5487
+
5488
+ ```javascript
5489
+ var myFunc = function() { console.log(this.name + ' ran.'); };
5490
+ var myContext = {name: 'debounce'};
5491
+
5492
+ Ember.run.debounce(myContext, myFunc, 150);
5493
+
5494
+ // less than 150ms passes
5495
+
5496
+ Ember.run.debounce(myContext, myFunc, 150);
5497
+
5498
+ // 150ms passes
5499
+ // myFunc is invoked with context myContext
5500
+ // console logs 'debounce ran.' one time.
5501
+ ```
5502
+
5503
+ @method debounce
5504
+ @param {Object} [target] target of method to invoke
5505
+ @param {Function|String} method The method to invoke.
5506
+ May be a function or a string. If you pass a string
5507
+ then it will be looked up on the passed target.
5508
+ @param {Object} [args*] Optional arguments to pass to the timeout.
5509
+ @param {Number} wait Number of milliseconds to wait.
5510
+ @return {void}
5511
+ */
5512
+ Ember.run.debounce = function() {
5513
+ return backburner.debounce.apply(backburner, arguments);
5514
+ };
5515
+
5444
5516
  // Make sure it's not an autorun during testing
5445
5517
  function checkAutoRun() {
5446
5518
  if (!Ember.run.currentRunLoop) {
@@ -7230,6 +7302,8 @@ define("rsvp",
7230
7302
  __exports__.reject = reject;
7231
7303
  });
7232
7304
 
7305
+
7306
+
7233
7307
  })();
7234
7308
 
7235
7309
  (function() {
@@ -7354,6 +7428,10 @@ define("container",
7354
7428
  return value;
7355
7429
  },
7356
7430
 
7431
+ lookupFactory: function(fullName) {
7432
+ return factoryFor(this, fullName);
7433
+ },
7434
+
7357
7435
  has: function(fullName) {
7358
7436
  if (this.cache.has(fullName)) {
7359
7437
  return true;
@@ -8074,8 +8152,8 @@ Ember.String = {
8074
8152
  ```
8075
8153
 
8076
8154
  @method capitalize
8077
- @param {String} str
8078
- @return {String}
8155
+ @param {String} str The string to capitalize.
8156
+ @return {String} The capitalized string.
8079
8157
  */
8080
8158
  capitalize: function(str) {
8081
8159
  return str.charAt(0).toUpperCase() + str.substr(1);
@@ -9448,15 +9526,15 @@ Ember.Array = Ember.Mixin.create(Ember.Enumerable, /** @scope Ember.Array.protot
9448
9526
  Adds an array observer to the receiving array. The array observer object
9449
9527
  normally must implement two methods:
9450
9528
 
9451
- * `arrayWillChange(start, removeCount, addCount)` - This method will be
9529
+ * `arrayWillChange(observedObj, start, removeCount, addCount)` - This method will be
9452
9530
  called just before the array is modified.
9453
- * `arrayDidChange(start, removeCount, addCount)` - This method will be
9531
+ * `arrayDidChange(observedObj, start, removeCount, addCount)` - This method will be
9454
9532
  called just after the array is modified.
9455
9533
 
9456
- Both callbacks will be passed the starting index of the change as well a
9457
- a count of the items to be removed and added. You can use these callbacks
9458
- to optionally inspect the array during the change, clear caches, or do
9459
- any other bookkeeping necessary.
9534
+ Both callbacks will be passed the observed object, starting index of the
9535
+ change as well a a count of the items to be removed and added. You can use
9536
+ these callbacks to optionally inspect the array during the change, clear
9537
+ caches, or do any other bookkeeping necessary.
9460
9538
 
9461
9539
  In addition to passing a target, you can also include an options hash
9462
9540
  which you can use to override the method names that will be invoked on the
@@ -13464,17 +13542,40 @@ Ember.SortableMixin = Ember.Mixin.create(Ember.MutableEnumerable, {
13464
13542
  @property {Boolean} sortAscending
13465
13543
  */
13466
13544
  sortAscending: true,
13545
+
13546
+ /**
13547
+ The function used to compare two values. You can override this if you
13548
+ want to do custom comparisons.Functions must be of the type expected by
13549
+ Array#sort, i.e.
13550
+ return 0 if the two parameters are equal,
13551
+ return a negative value if the first parameter is smaller than the second or
13552
+ return a positive value otherwise:
13553
+
13554
+ ```javascript
13555
+ function(x,y){ // These are assumed to be integers
13556
+ if(x === y)
13557
+ return 0;
13558
+ return x < y ? -1 : 1;
13559
+ }
13560
+ ```
13467
13561
 
13562
+ @property sortFunction
13563
+ @type {Function}
13564
+ @default Ember.compare
13565
+ */
13566
+ sortFunction: Ember.compare,
13567
+
13468
13568
  orderBy: function(item1, item2) {
13469
13569
  var result = 0,
13470
13570
  sortProperties = get(this, 'sortProperties'),
13471
- sortAscending = get(this, 'sortAscending');
13571
+ sortAscending = get(this, 'sortAscending'),
13572
+ sortFunction = get(this, 'sortFunction');
13472
13573
 
13473
13574
  Ember.assert("you need to define `sortProperties`", !!sortProperties);
13474
13575
 
13475
13576
  forEach(sortProperties, function(propertyName) {
13476
13577
  if (result === 0) {
13477
- result = Ember.compare(get(item1, propertyName), get(item2, propertyName));
13578
+ result = sortFunction(get(item1, propertyName), get(item2, propertyName));
13478
13579
  if ((result !== 0) && !sortAscending) {
13479
13580
  result = (-1) * result;
13480
13581
  }
@@ -13912,7 +14013,7 @@ Ember Runtime
13912
14013
  */
13913
14014
 
13914
14015
  var jQuery = Ember.imports.jQuery;
13915
- Ember.assert("Ember Views require jQuery 1.8, 1.9, 1.10, or 2.0", jQuery && (jQuery().jquery.match(/^((1\.(8|9|10))|2.0)(\.\d+)?(pre|rc\d?)?/) || Ember.ENV.FORCE_JQUERY));
14016
+ Ember.assert("Ember Views require jQuery 1.7, 1.8, 1.9, 1.10, or 2.0", jQuery && (jQuery().jquery.match(/^((1\.(7|8|9|10))|2.0)(\.\d+)?(pre|rc\d?)?/) || Ember.ENV.FORCE_JQUERY));
13916
14017
 
13917
14018
  /**
13918
14019
  Alias for jQuery
@@ -14114,45 +14215,6 @@ ClassSet.prototype = {
14114
14215
  }
14115
14216
  };
14116
14217
 
14117
- var BAD_TAG_NAME_TEST_REGEXP = /[^a-zA-Z\-]/;
14118
- var BAD_TAG_NAME_REPLACE_REGEXP = /[^a-zA-Z\-]/g;
14119
-
14120
- function stripTagName(tagName) {
14121
- if (!tagName) {
14122
- return tagName;
14123
- }
14124
-
14125
- if (!BAD_TAG_NAME_TEST_REGEXP.test(tagName)) {
14126
- return tagName;
14127
- }
14128
-
14129
- return tagName.replace(BAD_TAG_NAME_REPLACE_REGEXP, '');
14130
- }
14131
-
14132
- var BAD_CHARS_REGEXP = /&(?!\w+;)|[<>"'`]/g;
14133
- var POSSIBLE_CHARS_REGEXP = /[&<>"'`]/;
14134
-
14135
- function escapeAttribute(value) {
14136
- // Stolen shamelessly from Handlebars
14137
-
14138
- var escape = {
14139
- "<": "&lt;",
14140
- ">": "&gt;",
14141
- '"': "&quot;",
14142
- "'": "&#x27;",
14143
- "`": "&#x60;"
14144
- };
14145
-
14146
- var escapeChar = function(chr) {
14147
- return escape[chr] || "&amp;";
14148
- };
14149
-
14150
- var string = value.toString();
14151
-
14152
- if(!POSSIBLE_CHARS_REGEXP.test(string)) { return string; }
14153
- return string.replace(BAD_CHARS_REGEXP, escapeChar);
14154
- }
14155
-
14156
14218
  /**
14157
14219
  `Ember.RenderBuffer` gathers information regarding the a view and generates the
14158
14220
  final representation. `Ember.RenderBuffer` will generate HTML which can be pushed
@@ -14440,14 +14502,14 @@ Ember._RenderBuffer.prototype =
14440
14502
  style = this.elementStyle,
14441
14503
  attr, prop;
14442
14504
 
14443
- buffer += '<' + stripTagName(tagName);
14505
+ buffer += '<' + tagName;
14444
14506
 
14445
14507
  if (id) {
14446
- buffer += ' id="' + escapeAttribute(id) + '"';
14508
+ buffer += ' id="' + this._escapeAttribute(id) + '"';
14447
14509
  this.elementId = null;
14448
14510
  }
14449
14511
  if (classes) {
14450
- buffer += ' class="' + escapeAttribute(classes.join(' ')) + '"';
14512
+ buffer += ' class="' + this._escapeAttribute(classes.join(' ')) + '"';
14451
14513
  this.classes = null;
14452
14514
  }
14453
14515
 
@@ -14456,7 +14518,7 @@ Ember._RenderBuffer.prototype =
14456
14518
 
14457
14519
  for (prop in style) {
14458
14520
  if (style.hasOwnProperty(prop)) {
14459
- buffer += prop + ':' + escapeAttribute(style[prop]) + ';';
14521
+ buffer += prop + ':' + this._escapeAttribute(style[prop]) + ';';
14460
14522
  }
14461
14523
  }
14462
14524
 
@@ -14468,7 +14530,7 @@ Ember._RenderBuffer.prototype =
14468
14530
  if (attrs) {
14469
14531
  for (attr in attrs) {
14470
14532
  if (attrs.hasOwnProperty(attr)) {
14471
- buffer += ' ' + attr + '="' + escapeAttribute(attrs[attr]) + '"';
14533
+ buffer += ' ' + attr + '="' + this._escapeAttribute(attrs[attr]) + '"';
14472
14534
  }
14473
14535
  }
14474
14536
 
@@ -14483,7 +14545,7 @@ Ember._RenderBuffer.prototype =
14483
14545
  if (value === true) {
14484
14546
  buffer += ' ' + prop + '="' + prop + '"';
14485
14547
  } else {
14486
- buffer += ' ' + prop + '="' + escapeAttribute(props[prop]) + '"';
14548
+ buffer += ' ' + prop + '="' + this._escapeAttribute(props[prop]) + '"';
14487
14549
  }
14488
14550
  }
14489
14551
  }
@@ -14498,7 +14560,7 @@ Ember._RenderBuffer.prototype =
14498
14560
 
14499
14561
  pushClosingTag: function() {
14500
14562
  var tagName = this.tagNames.pop();
14501
- if (tagName) { this.buffer += '</' + stripTagName(tagName) + '>'; }
14563
+ if (tagName) { this.buffer += '</' + tagName + '>'; }
14502
14564
  },
14503
14565
 
14504
14566
  currentTagName: function() {
@@ -14596,7 +14658,32 @@ Ember._RenderBuffer.prototype =
14596
14658
 
14597
14659
  innerString: function() {
14598
14660
  return this.buffer;
14661
+ },
14662
+
14663
+ _escapeAttribute: function(value) {
14664
+ // Stolen shamelessly from Handlebars
14665
+
14666
+ var escape = {
14667
+ "<": "&lt;",
14668
+ ">": "&gt;",
14669
+ '"': "&quot;",
14670
+ "'": "&#x27;",
14671
+ "`": "&#x60;"
14672
+ };
14673
+
14674
+ var badChars = /&(?!\w+;)|[<>"'`]/g;
14675
+ var possible = /[&<>"'`]/;
14676
+
14677
+ var escapeChar = function(chr) {
14678
+ return escape[chr] || "&amp;";
14679
+ };
14680
+
14681
+ var string = value.toString();
14682
+
14683
+ if(!possible.test(string)) { return string; }
14684
+ return string.replace(badChars, escapeChar);
14599
14685
  }
14686
+
14600
14687
  };
14601
14688
 
14602
14689
  })();
@@ -14624,6 +14711,47 @@ var get = Ember.get, set = Ember.set, fmt = Ember.String.fmt;
14624
14711
  */
14625
14712
  Ember.EventDispatcher = Ember.Object.extend(/** @scope Ember.EventDispatcher.prototype */{
14626
14713
 
14714
+ /**
14715
+ The set of events names (and associated handler function names) to be setup
14716
+ and dispatched by the `EventDispatcher`. Custom events can added to this list at setup
14717
+ time, generally via the `Ember.Application.customEvents` hash. Only override this
14718
+ default set to prevent the EventDispatcher from listening on some events all together.
14719
+
14720
+ This set will be modified by `setup` to also include any events added at that time.
14721
+
14722
+ @property events
14723
+ @type Object
14724
+ */
14725
+ events: {
14726
+ touchstart : 'touchStart',
14727
+ touchmove : 'touchMove',
14728
+ touchend : 'touchEnd',
14729
+ touchcancel : 'touchCancel',
14730
+ keydown : 'keyDown',
14731
+ keyup : 'keyUp',
14732
+ keypress : 'keyPress',
14733
+ mousedown : 'mouseDown',
14734
+ mouseup : 'mouseUp',
14735
+ contextmenu : 'contextMenu',
14736
+ click : 'click',
14737
+ dblclick : 'doubleClick',
14738
+ mousemove : 'mouseMove',
14739
+ focusin : 'focusIn',
14740
+ focusout : 'focusOut',
14741
+ mouseenter : 'mouseEnter',
14742
+ mouseleave : 'mouseLeave',
14743
+ submit : 'submit',
14744
+ input : 'input',
14745
+ change : 'change',
14746
+ dragstart : 'dragStart',
14747
+ drag : 'drag',
14748
+ dragenter : 'dragEnter',
14749
+ dragleave : 'dragLeave',
14750
+ dragover : 'dragOver',
14751
+ drop : 'drop',
14752
+ dragend : 'dragEnd'
14753
+ },
14754
+
14627
14755
  /**
14628
14756
  @private
14629
14757
 
@@ -14655,35 +14783,7 @@ Ember.EventDispatcher = Ember.Object.extend(/** @scope Ember.EventDispatcher.pro
14655
14783
  @param addedEvents {Hash}
14656
14784
  */
14657
14785
  setup: function(addedEvents, rootElement) {
14658
- var event, events = {
14659
- touchstart : 'touchStart',
14660
- touchmove : 'touchMove',
14661
- touchend : 'touchEnd',
14662
- touchcancel : 'touchCancel',
14663
- keydown : 'keyDown',
14664
- keyup : 'keyUp',
14665
- keypress : 'keyPress',
14666
- mousedown : 'mouseDown',
14667
- mouseup : 'mouseUp',
14668
- contextmenu : 'contextMenu',
14669
- click : 'click',
14670
- dblclick : 'doubleClick',
14671
- mousemove : 'mouseMove',
14672
- focusin : 'focusIn',
14673
- focusout : 'focusOut',
14674
- mouseenter : 'mouseEnter',
14675
- mouseleave : 'mouseLeave',
14676
- submit : 'submit',
14677
- input : 'input',
14678
- change : 'change',
14679
- dragstart : 'dragStart',
14680
- drag : 'drag',
14681
- dragenter : 'dragEnter',
14682
- dragleave : 'dragLeave',
14683
- dragover : 'dragOver',
14684
- drop : 'drop',
14685
- dragend : 'dragEnd'
14686
- };
14786
+ var event, events = get(this, 'events');
14687
14787
 
14688
14788
  Ember.$.extend(events, addedEvents || {});
14689
14789
 
@@ -14930,6 +15030,15 @@ Ember.warn("The VIEW_PRESERVES_CONTEXT flag has been removed and the functionali
14930
15030
  */
14931
15031
  Ember.TEMPLATES = {};
14932
15032
 
15033
+ /**
15034
+ `Ember.CoreView` is
15035
+
15036
+ @class CoreView
15037
+ @namespace Ember
15038
+ @extends Ember.Object
15039
+ @uses Ember.Evented
15040
+ */
15041
+
14933
15042
  Ember.CoreView = Ember.Object.extend(Ember.Evented, {
14934
15043
  isView: true,
14935
15044
 
@@ -15633,8 +15742,10 @@ class:
15633
15742
 
15634
15743
  ### Event Names
15635
15744
 
15636
- Possible events names for any of the responding approaches described above
15637
- are:
15745
+ All of the event handling approaches described above respond to the same set
15746
+ of events. The names of the built-in events are listed below. (The hash of
15747
+ built-in events exists in `Ember.EventDispatcher`.) Additional, custom events
15748
+ can be registered by using `Ember.Application.customEvents`.
15638
15749
 
15639
15750
  Touch events:
15640
15751
 
@@ -15687,8 +15798,7 @@ class:
15687
15798
 
15688
15799
  @class View
15689
15800
  @namespace Ember
15690
- @extends Ember.Object
15691
- @uses Ember.Evented
15801
+ @extends Ember.CoreView
15692
15802
  */
15693
15803
  Ember.View = Ember.CoreView.extend(
15694
15804
  /** @scope Ember.View.prototype */ {
@@ -15869,7 +15979,7 @@ Ember.View = Ember.CoreView.extend(
15869
15979
  If a value that affects template rendering changes, the view should be
15870
15980
  re-rendered to reflect the new value.
15871
15981
 
15872
- @method _displayPropertyDidChange
15982
+ @method _contextDidChange
15873
15983
  */
15874
15984
  _contextDidChange: Ember.observer(function() {
15875
15985
  this.rerender();
@@ -15999,6 +16109,8 @@ Ember.View = Ember.CoreView.extend(
15999
16109
  _parentViewDidChange: Ember.observer(function() {
16000
16110
  if (this.isDestroying) { return; }
16001
16111
 
16112
+ this.trigger('parentViewDidChange');
16113
+
16002
16114
  if (get(this, 'parentView.controller') && !get(this, 'controller')) {
16003
16115
  this.notifyPropertyChange('controller');
16004
16116
  }
@@ -16270,9 +16382,9 @@ Ember.View = Ember.CoreView.extend(
16270
16382
  For example, calling `view.$('li')` will return a jQuery object containing
16271
16383
  all of the `li` elements inside the DOM element of this view.
16272
16384
 
16273
- @property $
16385
+ @method $
16274
16386
  @param {String} [selector] a jQuery-compatible selector string
16275
- @return {jQuery} the CoreQuery object for the DOM node
16387
+ @return {jQuery} the jQuery object for the DOM node
16276
16388
  */
16277
16389
  $: function(sel) {
16278
16390
  return this.currentState.$(this, sel);
@@ -16953,31 +17065,32 @@ Ember.View = Ember.CoreView.extend(
16953
17065
  @return {Ember.View} new instance
16954
17066
  */
16955
17067
  createChildView: function(view, attrs) {
16956
- if (view.isView && view._parentView === this) { return view; }
17068
+ if (view.isView && view._parentView === this && view.container === this.container) {
17069
+ return view;
17070
+ }
17071
+
17072
+ attrs = attrs || {};
17073
+ attrs._parentView = this;
17074
+ attrs.container = this.container;
16957
17075
 
16958
17076
  if (Ember.CoreView.detect(view)) {
16959
- attrs = attrs || {};
16960
- attrs._parentView = this;
16961
- attrs.container = this.container;
16962
17077
  attrs.templateData = attrs.templateData || get(this, 'templateData');
16963
17078
 
16964
17079
  view = view.create(attrs);
16965
17080
 
16966
17081
  // don't set the property on a virtual view, as they are invisible to
16967
17082
  // consumers of the view API
16968
- if (view.viewName) { set(get(this, 'concreteView'), view.viewName, view); }
17083
+ if (view.viewName) {
17084
+ set(get(this, 'concreteView'), view.viewName, view);
17085
+ }
16969
17086
  } else {
16970
17087
  Ember.assert('You must pass instance or subclass of View', view.isView);
16971
17088
 
16972
- if (attrs) {
16973
- view.setProperties(attrs);
16974
- }
17089
+ Ember.setProperties(view, attrs);
16975
17090
 
16976
17091
  if (!get(view, 'templateData')) {
16977
17092
  set(view, 'templateData', get(this, 'templateData'));
16978
17093
  }
16979
-
16980
- set(view, '_parentView', this);
16981
17094
  }
16982
17095
 
16983
17096
  return view;
@@ -17324,8 +17437,8 @@ Ember.View.applyAttributeBindings = function(elem, name, value) {
17324
17437
  elem.attr(name, value);
17325
17438
  }
17326
17439
  } else if (name === 'value' || type === 'boolean') {
17327
- // We can't set properties to undefined
17328
- if (value === undefined) { value = null; }
17440
+ // We can't set properties to undefined or null
17441
+ if (!value) { value = ''; }
17329
17442
 
17330
17443
  if (value !== elem.prop(name)) {
17331
17444
  // value and booleans should always be properties
@@ -18025,6 +18138,7 @@ Ember.ContainerView = Ember.View.extend(Ember.MutableArray, {
18025
18138
  initializeViews: function(views, parentView, templateData) {
18026
18139
  forEach(views, function(view) {
18027
18140
  set(view, '_parentView', parentView);
18141
+ set(view, 'container', parentView && parentView.container);
18028
18142
 
18029
18143
  if (!get(view, 'templateData')) {
18030
18144
  set(view, 'templateData', templateData);
@@ -18490,6 +18604,103 @@ Ember.CollectionView.CONTAINER_MAP = {
18490
18604
 
18491
18605
 
18492
18606
 
18607
+ (function() {
18608
+ /**
18609
+ @module ember
18610
+ @submodule ember-views
18611
+ */
18612
+
18613
+ /**
18614
+ An `Ember.Component` is a view that is completely
18615
+ isolated. Property access in its templates go
18616
+ to the view object and actions are targeted at
18617
+ the view object. There is no access to the
18618
+ surrounding context or outer controller; all
18619
+ contextual information is passed in.
18620
+
18621
+ The easiest way to create an `Ember.Component` is via
18622
+ a template. If you name a template
18623
+ `controls/my-foo`, you will be able to use
18624
+ `{{my-foo}}` in other templates, which will make
18625
+ an instance of the isolated control.
18626
+
18627
+ ```html
18628
+ {{app-profile person=currentUser}}
18629
+ ```
18630
+
18631
+ ```html
18632
+ <!-- app-profile template -->
18633
+ <h1>{{person.title}}</h1>
18634
+ <img {{bindAttr src=person.avatar}}>
18635
+ <p class='signature'>{{person.signature}}</p>
18636
+ ```
18637
+
18638
+ You can also use `yield` inside a template to
18639
+ include the **contents** of the custom tag:
18640
+
18641
+ ```html
18642
+ {{#my-profile person=currentUser}}
18643
+ <p>Admin mode</p>
18644
+ {{/my-profile}}
18645
+ ```
18646
+
18647
+ ```html
18648
+ <!-- app-profile template -->
18649
+
18650
+ <h1>{{person.title}}</h1>
18651
+ {{yield}} <!-- block contents -->
18652
+ ```
18653
+
18654
+ If you want to customize the control, in order to
18655
+ handle events or actions, you implement a subclass
18656
+ of `Ember.Component` named after the name of the
18657
+ control.
18658
+
18659
+ For example, you could implement the action
18660
+ `hello` for the `app-profile` control:
18661
+
18662
+ ```js
18663
+ App.AppProfileComponent = Ember.Component.extend({
18664
+ hello: function(name) {
18665
+ console.log("Hello", name)
18666
+ }
18667
+ });
18668
+ ```
18669
+
18670
+ And then use it in the control's template:
18671
+
18672
+ ```html
18673
+ <!-- app-profile template -->
18674
+
18675
+ <h1>{{person.title}}</h1>
18676
+ {{yield}} <!-- block contents -->
18677
+
18678
+ <button {{action 'hello' person.name}}>
18679
+ Say Hello to {{person.name}}
18680
+ </button>
18681
+ ```
18682
+
18683
+ Components must have a `-` in their name to avoid
18684
+ conflicts with built-in controls that wrap HTML
18685
+ elements. This is consistent with the same
18686
+ requirement in web components.
18687
+
18688
+ @class Component
18689
+ @namespace Ember
18690
+ @extends Ember.View
18691
+ */
18692
+ Ember.Component = Ember.View.extend({
18693
+ init: function() {
18694
+ this._super();
18695
+ this.set('context', this);
18696
+ this.set('controller', this);
18697
+ }
18698
+ });
18699
+
18700
+ })();
18701
+
18702
+
18703
+
18493
18704
  (function() {
18494
18705
 
18495
18706
  })();
@@ -18560,7 +18771,6 @@ Ember.ViewTargetActionSupport = Ember.Mixin.create(Ember.TargetActionSupport, {
18560
18771
 
18561
18772
 
18562
18773
  (function() {
18563
- /*globals jQuery*/
18564
18774
  /**
18565
18775
  Ember Views
18566
18776
 
@@ -18588,8 +18798,6 @@ var get = Ember.get, set = Ember.set;
18588
18798
  */
18589
18799
  Ember.State = Ember.Object.extend(Ember.Evented,
18590
18800
  /** @scope Ember.State.prototype */{
18591
- isState: true,
18592
-
18593
18801
  /**
18594
18802
  A reference to the parent state.
18595
18803
 
@@ -18699,20 +18907,24 @@ Ember.State = Ember.Object.extend(Ember.Evented,
18699
18907
 
18700
18908
  setupChild: function(states, name, value) {
18701
18909
  if (!value) { return false; }
18910
+ var instance;
18702
18911
 
18703
- if (value.isState) {
18912
+ if (value instanceof Ember.State) {
18704
18913
  set(value, 'name', name);
18914
+ instance = value;
18915
+ instance.container = this.container;
18705
18916
  } else if (Ember.State.detect(value)) {
18706
- value = value.create({
18707
- name: name
18917
+ instance = value.create({
18918
+ name: name,
18919
+ container: this.container
18708
18920
  });
18709
18921
  }
18710
18922
 
18711
- if (value.isState) {
18712
- set(value, 'parentState', this);
18713
- get(this, 'childStates').pushObject(value);
18714
- states[name] = value;
18715
- return value;
18923
+ if (instance instanceof Ember.State) {
18924
+ set(instance, 'parentState', this);
18925
+ get(this, 'childStates').pushObject(instance);
18926
+ states[name] = instance;
18927
+ return instance;
18716
18928
  }
18717
18929
  },
18718
18930
 
@@ -20348,7 +20560,71 @@ function makeBindings(options) {
20348
20560
  }
20349
20561
  }
20350
20562
 
20563
+ /**
20564
+ Register a bound helper or custom view helper.
20565
+
20566
+ ## Simple bound helper example
20567
+
20568
+ ```javascript
20569
+ Ember.Handlebars.helper('capitalize', function(value) {
20570
+ return value.toUpperCase();
20571
+ });
20572
+ ```
20573
+
20574
+ The above bound helper can be used inside of templates as follows:
20575
+
20576
+ ```handlebars
20577
+ {{capitalize name}}
20578
+ ```
20579
+
20580
+ In this case, when the `name` property of the template's context changes,
20581
+ the rendered value of the helper will update to reflect this change.
20582
+
20583
+ For more examples of bound helpers, see documentation for
20584
+ `Ember.Handlebars.registerBoundHelper`.
20585
+
20586
+ ## Custom view helper example
20587
+
20588
+ Assuming a view subclass named `App.CalenderView` were defined, a helper
20589
+ for rendering instances of this view could be registered as follows:
20590
+
20591
+ ```javascript
20592
+ Ember.Handlebars.helper('calendar', App.CalendarView):
20593
+ ```
20594
+
20595
+ The above bound helper can be used inside of templates as follows:
20596
+
20597
+ ```handlebars
20598
+ {{calendar}}
20599
+ ```
20600
+
20601
+ Which is functionally equivalent to:
20602
+
20603
+ ```handlebars
20604
+ {{view App.CalendarView}}
20605
+ ```
20606
+
20607
+ Options in the helper will be passed to the view in exactly the same
20608
+ manner as with the `view` helper.
20609
+
20610
+ @method helper
20611
+ @for Ember.Handlebars
20612
+ @param {String} name
20613
+ @param {Function|Ember.View} function or view class constructor
20614
+ @param {String} dependentKeys*
20615
+ */
20351
20616
  Ember.Handlebars.helper = function(name, value) {
20617
+ if (Ember.Component.detect(value)) {
20618
+ Ember.assert("You tried to register a component named '" + name + "', but component names must include a '-'", name.match(/-/));
20619
+
20620
+ var proto = value.proto();
20621
+ if (!proto.layoutName && !proto.templateName) {
20622
+ value.reopen({
20623
+ layoutName: 'components/' + name
20624
+ });
20625
+ }
20626
+ }
20627
+
20352
20628
  if (Ember.View.detect(value)) {
20353
20629
  Ember.Handlebars.registerHelper(name, function(options) {
20354
20630
  Ember.assert("You can only pass attributes as parameters (not values) to a application-defined helper", arguments.length < 2);
@@ -21109,7 +21385,7 @@ Ember._MetamorphView = Ember.View.extend(Ember._Metamorph);
21109
21385
  /**
21110
21386
  @class _SimpleMetamorphView
21111
21387
  @namespace Ember
21112
- @extends Ember.View
21388
+ @extends Ember.CoreView
21113
21389
  @uses Ember._Metamorph
21114
21390
  @private
21115
21391
  */
@@ -23925,7 +24201,6 @@ Ember.SelectOption = Ember.View.extend({
23925
24201
 
23926
24202
  ```html
23927
24203
  <select class="ember-select">
23928
- <option value>Please Select</option>
23929
24204
  <option value="1">Yehuda</option>
23930
24205
  <option value="2">Tom</option>
23931
24206
  </select>
@@ -23958,7 +24233,6 @@ Ember.SelectOption = Ember.View.extend({
23958
24233
 
23959
24234
  ```html
23960
24235
  <select class="ember-select">
23961
- <option value>Please Select</option>
23962
24236
  <option value="1">Yehuda</option>
23963
24237
  <option value="2" selected="selected">Tom</option>
23964
24238
  </select>
@@ -23996,7 +24270,6 @@ Ember.SelectOption = Ember.View.extend({
23996
24270
 
23997
24271
  ```html
23998
24272
  <select class="ember-select">
23999
- <option value>Please Select</option>
24000
24273
  <option value="1">Yehuda</option>
24001
24274
  <option value="2" selected="selected">Tom</option>
24002
24275
  </select>
@@ -24264,8 +24537,8 @@ function program3(depth0,data) {
24264
24537
  var selection = get(this, 'selection');
24265
24538
  var value = get(this, 'value');
24266
24539
 
24267
- if (selection) { this.selectionDidChange(); }
24268
- if (value) { this.valueDidChange(); }
24540
+ if (!Ember.isNone(selection)) { this.selectionDidChange(); }
24541
+ if (!Ember.isNone(value)) { this.valueDidChange(); }
24269
24542
 
24270
24543
  this._change();
24271
24544
  },
@@ -24462,6 +24735,31 @@ function bootstrap() {
24462
24735
  Ember.Handlebars.bootstrap( Ember.$(document) );
24463
24736
  }
24464
24737
 
24738
+ function registerComponents(container) {
24739
+ var templates = Ember.TEMPLATES, match;
24740
+ if (!templates) { return; }
24741
+
24742
+ for (var prop in templates) {
24743
+ if (match = prop.match(/^components\/(.*)$/)) {
24744
+ registerComponent(container, match[1]);
24745
+ }
24746
+ }
24747
+ }
24748
+
24749
+ function registerComponent(container, name) {
24750
+ Ember.assert("You provided a template named 'components/" + name + "', but custom components must include a '-'", name.match(/-/));
24751
+
24752
+ var className = name.replace(/-/g, '_');
24753
+ var Component = container.lookupFactory('component:' + className) || container.lookupFactory('component:' + name);
24754
+ var View = Component || Ember.Component.extend();
24755
+
24756
+ View.reopen({
24757
+ layoutName: 'components/' + name
24758
+ });
24759
+
24760
+ Ember.Handlebars.helper(name, View);
24761
+ }
24762
+
24465
24763
  /*
24466
24764
  We tie this to application.load to ensure that we've at least
24467
24765
  attempted to bootstrap at the point that the application is loaded.
@@ -24473,7 +24771,23 @@ function bootstrap() {
24473
24771
  from the DOM after processing.
24474
24772
  */
24475
24773
 
24476
- Ember.onLoad('application', bootstrap);
24774
+ Ember.onLoad('Ember.Application', function(Application) {
24775
+ if (Application.initializer) {
24776
+ Application.initializer({
24777
+ name: 'domTemplates',
24778
+ initialize: bootstrap
24779
+ });
24780
+
24781
+ Application.initializer({
24782
+ name: 'registerComponents',
24783
+ after: 'domTemplates',
24784
+ initialize: registerComponents
24785
+ });
24786
+ } else {
24787
+ // for ember-old-router
24788
+ Ember.onLoad('application', bootstrap);
24789
+ }
24790
+ });
24477
24791
 
24478
24792
  })();
24479
24793