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

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,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