rasputin 0.13.2 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -15,17 +15,10 @@ console.log = console.info = console.warn = console.error = function(){};
15
15
  var jQuery = function() { return jQuery; };
16
16
  jQuery.ready = function() { return jQuery; };
17
17
  jQuery.inArray = function() { return jQuery; };
18
+ jQuery.jquery = "1.7.1";
18
19
  var $ = jQuery;
19
20
 
20
- // Precompiler
21
- var EmberHandlebars = {
22
- precompile: function(string) {
23
- // Copied from the Ember codebase. This will need to be updated as Ember updates...
24
- var ast = Handlebars.parse(string);
25
- var options = { data: true, stringParams: true };
26
- var environment = new Ember.Handlebars.Compiler().compile(ast, options);
27
- var templateSpec = new Ember.Handlebars.JavaScriptCompiler().compile(environment, options, undefined, true);
28
-
29
- return templateSpec.toString();
30
- }
31
- };
21
+ // Ember
22
+ function precompileEmberHandlebars(string) {
23
+ return Ember.Handlebars.precompile(string).toString();
24
+ }
@@ -1608,7 +1608,7 @@ if ('undefined' === typeof Ember) {
1608
1608
  /**
1609
1609
  @namespace
1610
1610
  @name Ember
1611
- @version 0.9.3
1611
+ @version 0.9.4
1612
1612
 
1613
1613
  All Ember methods and functions are defined inside of this namespace.
1614
1614
  You generally should not add new properties to this namespace as it may be
@@ -1640,10 +1640,10 @@ if ('undefined' !== typeof window) {
1640
1640
  /**
1641
1641
  @static
1642
1642
  @type String
1643
- @default '0.9.3'
1643
+ @default '0.9.4'
1644
1644
  @constant
1645
1645
  */
1646
- Ember.VERSION = '0.9.3';
1646
+ Ember.VERSION = '0.9.4';
1647
1647
 
1648
1648
  /**
1649
1649
  @static
@@ -1664,6 +1664,12 @@ Ember.ENV = 'undefined' === typeof ENV ? {} : ENV;
1664
1664
  */
1665
1665
  Ember.K = function() { return this; };
1666
1666
 
1667
+ /**
1668
+ @namespace
1669
+ @name window
1670
+ @description The global window object
1671
+ */
1672
+
1667
1673
  /**
1668
1674
  Define an assertion that will throw an exception if the condition is not
1669
1675
  met. Ember build tools will remove any calls to ember_assert() when
@@ -1729,11 +1735,15 @@ Ember.Logger = window.console || { log: Ember.K, warn: Ember.K, error: Ember.K }
1729
1735
  @class
1730
1736
 
1731
1737
  Platform specific methods and feature detectors needed by the framework.
1738
+
1739
+ @name Ember.platform
1732
1740
  */
1733
1741
  var platform = Ember.platform = {} ;
1734
1742
 
1735
1743
  /**
1736
1744
  Identical to Object.create(). Implements if not available natively.
1745
+ @memberOf Ember.platform
1746
+ @name create
1737
1747
  */
1738
1748
  platform.create = Object.create;
1739
1749
 
@@ -1831,6 +1841,8 @@ if (defineProperty) {
1831
1841
  Identical to Object.defineProperty(). Implements as much functionality
1832
1842
  as possible if not available natively.
1833
1843
 
1844
+ @memberOf Ember.platform
1845
+ @name defineProperty
1834
1846
  @param {Object} obj The object to modify
1835
1847
  @param {String} keyName property name to modify
1836
1848
  @param {Object} desc descriptor hash
@@ -1840,6 +1852,9 @@ platform.defineProperty = defineProperty;
1840
1852
 
1841
1853
  /**
1842
1854
  Set to true if the platform supports native getters and setters.
1855
+
1856
+ @memberOf Ember.platform
1857
+ @name hasPropertyAccessors
1843
1858
  */
1844
1859
  platform.hasPropertyAccessors = true;
1845
1860
 
@@ -2028,8 +2043,6 @@ if (Object.freeze) Object.freeze(EMPTY_META);
2028
2043
  @returns {Hash}
2029
2044
  */
2030
2045
  Ember.meta = function meta(obj, writable) {
2031
-
2032
- ember_assert("You must pass an object to Ember.meta. This was probably called from Ember internals, so you probably called a Ember method with undefined that was expecting an object", obj != undefined);
2033
2046
 
2034
2047
  var ret = obj[META_KEY];
2035
2048
  if (writable===false) return ret || EMPTY_META;
@@ -2218,6 +2231,7 @@ var meta = Ember.meta;
2218
2231
 
2219
2232
  var get, set;
2220
2233
 
2234
+ /** @private */
2221
2235
  get = function get(obj, keyName) {
2222
2236
  if (keyName === undefined && 'string' === typeof obj) {
2223
2237
  keyName = obj;
@@ -2232,6 +2246,7 @@ get = function get(obj, keyName) {
2232
2246
  return ret;
2233
2247
  };
2234
2248
 
2249
+ /** @private */
2235
2250
  set = function set(obj, keyName, value) {
2236
2251
  if (('object'===typeof obj) && !(keyName in obj)) {
2237
2252
  if ('function' === typeof obj.setUnknownProperty) {
@@ -2372,8 +2387,8 @@ function getPath(target, path) {
2372
2387
  }
2373
2388
 
2374
2389
  var TUPLE_RET = [];
2375
- var IS_GLOBAL = /^([A-Z$]|([0-9][A-Z$])).*[\.\*]/;
2376
- var IS_GLOBAL_SET = /^([A-Z$]|([0-9][A-Z$])).*[\.\*]?/;
2390
+ var IS_GLOBAL = /^([A-Z$]|([0-9][A-Z$]))/;
2391
+ var IS_GLOBAL_PATH = /^([A-Z$]|([0-9][A-Z$])).*[\.\*]/;
2377
2392
  var HAS_THIS = /^this[\.\*]/;
2378
2393
  var FIRST_KEY = /^([^\.\*]+)/;
2379
2394
 
@@ -2384,7 +2399,7 @@ function firstKey(path) {
2384
2399
  // assumes path is already normalized
2385
2400
  function normalizeTuple(target, path) {
2386
2401
  var hasThis = HAS_THIS.test(path),
2387
- isGlobal = !hasThis && IS_GLOBAL.test(path),
2402
+ isGlobal = !hasThis && IS_GLOBAL_PATH.test(path),
2388
2403
  key;
2389
2404
 
2390
2405
  if (!target || isGlobal) target = window;
@@ -2449,9 +2464,14 @@ Ember.normalizeTuple = function(target, path) {
2449
2464
 
2450
2465
  Ember.normalizeTuple.primitive = normalizeTuple;
2451
2466
 
2452
- Ember.getPath = function(root, path) {
2453
- var hasThis, hasStar, isGlobal;
2467
+ Ember.getPath = function(root, path, _checkGlobal) {
2468
+ var hasThis, hasStar, isGlobal, ret;
2454
2469
 
2470
+ // Helpers that operate with 'this' within an #each
2471
+ if (path === '') {
2472
+ return root;
2473
+ }
2474
+
2455
2475
  if (!path && 'string'===typeof root) {
2456
2476
  path = root;
2457
2477
  root = null;
@@ -2467,14 +2487,26 @@ Ember.getPath = function(root, path) {
2467
2487
  // detect complicated paths and normalize them
2468
2488
  path = normalizePath(path);
2469
2489
  hasThis = HAS_THIS.test(path);
2470
- isGlobal = !hasThis && IS_GLOBAL.test(path);
2471
- if (!root || hasThis || isGlobal || hasStar) {
2490
+
2491
+ if (!root || hasThis || hasStar) {
2492
+ if (root && root !== window && IS_GLOBAL.test(path)) {
2493
+ console.warn("Fetching globals with Ember.getPath is deprecated", root, path);
2494
+ }
2495
+
2472
2496
  var tuple = normalizeTuple(root, path);
2473
2497
  root = tuple[0];
2474
2498
  path = tuple[1];
2475
- }
2476
-
2477
- return getPath(root, path);
2499
+ tuple.length = 0;
2500
+ }
2501
+
2502
+ ret = getPath(root, path);
2503
+
2504
+ if (ret === undefined && root !== window && !hasThis && IS_GLOBAL.test(path) && _checkGlobal !== false) {
2505
+ console.warn("Fetching globals with Ember.getPath is deprecated", root, path);
2506
+ return Ember.getPath(window, path);
2507
+ } else {
2508
+ return ret;
2509
+ }
2478
2510
  };
2479
2511
 
2480
2512
  Ember.setPath = function(root, path, value, tolerant) {
@@ -2488,22 +2520,30 @@ Ember.setPath = function(root, path, value, tolerant) {
2488
2520
 
2489
2521
  path = normalizePath(path);
2490
2522
  if (path.indexOf('*')>0) {
2523
+ if (root && root !== window && IS_GLOBAL.test(path)) {
2524
+ console.warn("Setting globals with Ember.setPath is deprecated", path);
2525
+ };
2526
+
2491
2527
  var tuple = normalizeTuple(root, path);
2492
2528
  root = tuple[0];
2493
2529
  path = tuple[1];
2530
+ tuple.length = 0;
2494
2531
  }
2495
2532
 
2496
2533
  if (path.indexOf('.') > 0) {
2497
2534
  keyName = path.slice(path.lastIndexOf('.')+1);
2498
2535
  path = path.slice(0, path.length-(keyName.length+1));
2499
- if (!HAS_THIS.test(path) && IS_GLOBAL_SET.test(path) && path.indexOf('.')<0) {
2500
- root = window[path]; // special case only works during set...
2501
- } else if (path !== 'this') {
2502
- root = Ember.getPath(root, path);
2536
+ if (path !== 'this') {
2537
+ // Remove the `false` when we're done with this deprecation
2538
+ root = Ember.getPath(root, path, false);
2539
+ if (!root && IS_GLOBAL.test(path)) {
2540
+ console.warn("Setting globals with Ember.setPath is deprecated", path);
2541
+ root = Ember.getPath(window, path);
2542
+ }
2503
2543
  }
2504
2544
 
2505
2545
  } else {
2506
- if (IS_GLOBAL_SET.test(path)) throw new Error('Invalid Path');
2546
+ if (IS_GLOBAL.test(path)) throw new Error('Invalid Path');
2507
2547
  keyName = path;
2508
2548
  }
2509
2549
 
@@ -2735,7 +2775,9 @@ function xformForArgs(args) {
2735
2775
  return function (target, method, params) {
2736
2776
  var obj = params[0], keyName = changeKey(params[1]), val;
2737
2777
  var copy_args = args.slice();
2738
- if (method.length>2) val = Ember.getPath(obj, keyName);
2778
+ if (method.length>2) {
2779
+ val = Ember.getPath(Ember.isGlobalPath(keyName) ? window : obj, keyName);
2780
+ }
2739
2781
  copy_args.unshift(obj, keyName, val);
2740
2782
  method.apply(target, copy_args);
2741
2783
  };
@@ -3138,9 +3180,10 @@ function hasDesc(descs, keyName) {
3138
3180
  }).property('firstName', 'lastName').cacheable());
3139
3181
  */
3140
3182
  Ember.defineProperty = function(obj, keyName, desc, val) {
3141
- var m = meta(obj, false), descs = m.descs, watching = m.watching[keyName]>0;
3183
+ var m = meta(obj, false), descs = m.descs, watching = m.watching[keyName]>0, override = true;
3142
3184
 
3143
3185
  if (val === undefined) {
3186
+ override = false;
3144
3187
  val = hasDesc(descs, keyName) ? descs[keyName].teardown(obj, keyName) : obj[keyName];
3145
3188
  } else if (hasDesc(descs, keyName)) {
3146
3189
  descs[keyName].teardown(obj, keyName);
@@ -3161,7 +3204,11 @@ Ember.defineProperty = function(obj, keyName, desc, val) {
3161
3204
  if (descs[keyName]) meta(obj).descs[keyName] = null;
3162
3205
  o_defineProperty(obj, keyName, desc);
3163
3206
  }
3164
-
3207
+
3208
+ // if key is being watched, override chains that
3209
+ // were initialized with the prototype
3210
+ if (override && watching) Ember.overrideChains(obj, keyName, m);
3211
+
3165
3212
  return this;
3166
3213
  };
3167
3214
 
@@ -3218,19 +3265,6 @@ Ember.createPrototype = function(obj, props) {
3218
3265
  if (META_KEY in ret) Ember.rewatch(ret); // setup watch chains if needed.
3219
3266
  return ret;
3220
3267
  };
3221
-
3222
-
3223
- /**
3224
- Tears down the meta on an object so that it can be garbage collected.
3225
- Multiple calls will have no effect.
3226
-
3227
- @param {Object} obj the object to destroy
3228
- @returns {void}
3229
- */
3230
- Ember.destroy = function(obj) {
3231
- if (obj[META_KEY]) obj[META_KEY] = null;
3232
- };
3233
-
3234
3268
 
3235
3269
  })({});
3236
3270
 
@@ -3249,6 +3283,7 @@ var normalizeTuple = Ember.normalizeTuple.primitive;
3249
3283
  var normalizePath = Ember.normalizePath;
3250
3284
  var SIMPLE_PROPERTY = Ember.SIMPLE_PROPERTY;
3251
3285
  var GUID_KEY = Ember.GUID_KEY;
3286
+ var META_KEY = Ember.META_KEY;
3252
3287
  var notifyObservers = Ember.notifyObservers;
3253
3288
 
3254
3289
  var FIRST_KEY = /^([^\.\*]+)/;
@@ -3265,17 +3300,17 @@ function isKeyName(path) {
3265
3300
 
3266
3301
  // ..........................................................
3267
3302
  // DEPENDENT KEYS
3268
- //
3303
+ //
3269
3304
 
3270
3305
  var DEP_SKIP = { __emberproto__: true }; // skip some keys and toString
3271
- function iterDeps(methodName, obj, depKey, seen) {
3272
-
3306
+ function iterDeps(method, obj, depKey, seen, meta) {
3307
+
3273
3308
  var guid = guidFor(obj);
3274
3309
  if (!seen[guid]) seen[guid] = {};
3275
3310
  if (seen[guid][depKey]) return ;
3276
3311
  seen[guid][depKey] = true;
3277
-
3278
- var deps = meta(obj, false).deps, method = Ember[methodName];
3312
+
3313
+ var deps = meta.deps;
3279
3314
  deps = deps && deps[depKey];
3280
3315
  if (deps) {
3281
3316
  for(var key in deps) {
@@ -3289,18 +3324,18 @@ function iterDeps(methodName, obj, depKey, seen) {
3289
3324
  var WILL_SEEN, DID_SEEN;
3290
3325
 
3291
3326
  // called whenever a property is about to change to clear the cache of any dependent keys (and notify those properties of changes, etc...)
3292
- function dependentKeysWillChange(obj, depKey) {
3327
+ function dependentKeysWillChange(obj, depKey, meta) {
3293
3328
  var seen = WILL_SEEN, top = !seen;
3294
3329
  if (top) seen = WILL_SEEN = {};
3295
- iterDeps('propertyWillChange', obj, depKey, seen);
3330
+ iterDeps(propertyWillChange, obj, depKey, seen, meta);
3296
3331
  if (top) WILL_SEEN = null;
3297
3332
  }
3298
3333
 
3299
3334
  // called whenever a property has just changed to update dependent keys
3300
- function dependentKeysDidChange(obj, depKey) {
3335
+ function dependentKeysDidChange(obj, depKey, meta) {
3301
3336
  var seen = DID_SEEN, top = !seen;
3302
3337
  if (top) seen = DID_SEEN = {};
3303
- iterDeps('propertyDidChange', obj, depKey, seen);
3338
+ iterDeps(propertyDidChange, obj, depKey, seen, meta);
3304
3339
  if (top) DID_SEEN = null;
3305
3340
  }
3306
3341
 
@@ -3436,6 +3471,7 @@ Wp.add = function(path) {
3436
3471
  // put into a queue and try to connect later.
3437
3472
  } else if (!tuple[0]) {
3438
3473
  pendingQueue.push([this, path]);
3474
+ tuple.length = 0;
3439
3475
  return;
3440
3476
 
3441
3477
  // global path, and object already exists
@@ -3446,6 +3482,7 @@ Wp.add = function(path) {
3446
3482
  path = tuple[1];
3447
3483
  }
3448
3484
 
3485
+ tuple.length = 0;
3449
3486
  this.chain(key, path, src, separator);
3450
3487
  };
3451
3488
 
@@ -3470,6 +3507,7 @@ Wp.remove = function(path) {
3470
3507
  path = tuple[1];
3471
3508
  }
3472
3509
 
3510
+ tuple.length = 0;
3473
3511
  this.unchain(key, path);
3474
3512
  };
3475
3513
 
@@ -3545,7 +3583,7 @@ Wp.chainDidChange = function(chain, path, depth) {
3545
3583
  }
3546
3584
  };
3547
3585
 
3548
- Wp.didChange = function() {
3586
+ Wp.didChange = function(suppressEvent) {
3549
3587
  // invalidate my own value first.
3550
3588
  if (this._watching) {
3551
3589
  var obj = this._parent.value();
@@ -3567,10 +3605,12 @@ Wp.didChange = function() {
3567
3605
  if (chains) {
3568
3606
  for(var key in chains) {
3569
3607
  if (!chains.hasOwnProperty(key)) continue;
3570
- chains[key].didChange();
3608
+ chains[key].didChange(suppressEvent);
3571
3609
  }
3572
3610
  }
3573
3611
 
3612
+ if (suppressEvent) return;
3613
+
3574
3614
  // and finally tell parent about my path changing...
3575
3615
  if (this._parent) this._parent.chainDidChange(this, this._key, 1);
3576
3616
  };
@@ -3590,26 +3630,30 @@ function chainsFor(obj) {
3590
3630
 
3591
3631
 
3592
3632
 
3593
- function notifyChains(obj, keyName, methodName) {
3594
- var m = meta(obj, false);
3633
+ function notifyChains(obj, m, keyName, methodName, arg) {
3595
3634
  var nodes = m.chainWatchers;
3635
+
3596
3636
  if (!nodes || nodes.__emberproto__ !== obj) return; // nothing to do
3597
3637
 
3598
3638
  nodes = nodes[keyName];
3599
3639
  if (!nodes) return;
3600
-
3640
+
3601
3641
  for(var key in nodes) {
3602
3642
  if (!nodes.hasOwnProperty(key)) continue;
3603
- nodes[key][methodName](obj, keyName);
3643
+ nodes[key][methodName](arg);
3604
3644
  }
3605
3645
  }
3606
3646
 
3607
- function chainsWillChange(obj, keyName) {
3608
- notifyChains(obj, keyName, 'willChange');
3647
+ Ember.overrideChains = function(obj, keyName, m) {
3648
+ notifyChains(obj, m, keyName, 'didChange', true);
3609
3649
  }
3610
3650
 
3611
- function chainsDidChange(obj, keyName) {
3612
- notifyChains(obj, keyName, 'didChange');
3651
+ function chainsWillChange(obj, keyName, m) {
3652
+ notifyChains(obj, m, keyName, 'willChange');
3653
+ }
3654
+
3655
+ function chainsDidChange(obj, keyName, m) {
3656
+ notifyChains(obj, m, keyName, 'didChange');
3613
3657
  }
3614
3658
 
3615
3659
  // ..........................................................
@@ -3732,12 +3776,12 @@ Ember.rewatch = function(obj) {
3732
3776
 
3733
3777
  @returns {void}
3734
3778
  */
3735
- Ember.propertyWillChange = function(obj, keyName) {
3779
+ var propertyWillChange = Ember.propertyWillChange = function(obj, keyName) {
3736
3780
  var m = meta(obj, false), proto = m.proto, desc = m.descs[keyName];
3737
3781
  if (proto === obj) return ;
3738
3782
  if (desc && desc.willChange) desc.willChange(obj, keyName);
3739
- dependentKeysWillChange(obj, keyName);
3740
- chainsWillChange(obj, keyName);
3783
+ dependentKeysWillChange(obj, keyName, m);
3784
+ chainsWillChange(obj, keyName, m);
3741
3785
  Ember.notifyBeforeObservers(obj, keyName);
3742
3786
  };
3743
3787
 
@@ -3758,15 +3802,56 @@ Ember.propertyWillChange = function(obj, keyName) {
3758
3802
 
3759
3803
  @returns {void}
3760
3804
  */
3761
- Ember.propertyDidChange = function(obj, keyName) {
3805
+ var propertyDidChange = Ember.propertyDidChange = function(obj, keyName) {
3762
3806
  var m = meta(obj, false), proto = m.proto, desc = m.descs[keyName];
3763
3807
  if (proto === obj) return ;
3764
3808
  if (desc && desc.didChange) desc.didChange(obj, keyName);
3765
- dependentKeysDidChange(obj, keyName);
3766
- chainsDidChange(obj, keyName);
3809
+ dependentKeysDidChange(obj, keyName, m);
3810
+ chainsDidChange(obj, keyName, m);
3767
3811
  Ember.notifyObservers(obj, keyName);
3768
3812
  };
3769
3813
 
3814
+ var NODE_STACK = []
3815
+
3816
+ /**
3817
+ Tears down the meta on an object so that it can be garbage collected.
3818
+ Multiple calls will have no effect.
3819
+
3820
+ @param {Object} obj the object to destroy
3821
+ @returns {void}
3822
+ */
3823
+ Ember.destroy = function (obj) {
3824
+ var meta = obj[META_KEY], node, nodes, key, nodeObject;
3825
+ if (meta) {
3826
+ obj[META_KEY] = null;
3827
+ // remove chainWatchers to remove circular references that would prevent GC
3828
+ node = meta.chains;
3829
+ if (node) {
3830
+ NODE_STACK.push(node);
3831
+ // process tree
3832
+ while (NODE_STACK.length > 0) {
3833
+ node = NODE_STACK.pop();
3834
+ // push children
3835
+ nodes = node._chains;
3836
+ if (nodes) {
3837
+ for (key in nodes) {
3838
+ if (nodes.hasOwnProperty(key)) {
3839
+ NODE_STACK.push(nodes[key]);
3840
+ }
3841
+ }
3842
+ }
3843
+ // remove chainWatcher in node object
3844
+ if (node._watching) {
3845
+ nodeObject = node._object;
3846
+ if (nodeObject) {
3847
+ removeChainWatcher(nodeObject, node._key, node);
3848
+ }
3849
+ }
3850
+ }
3851
+ }
3852
+ }
3853
+ };
3854
+
3770
3855
  })({});
3771
3856
 
3772
3857
 
@@ -3802,8 +3887,20 @@ function invoke(target, method, args, ignore) {
3802
3887
  if (args && ignore>0) {
3803
3888
  args = args.length>ignore ? slice.call(args, ignore) : null;
3804
3889
  }
3805
- // IE8's Function.prototype.apply doesn't accept undefined/null arguments.
3806
- return method.apply(target || this, args || []);
3890
+
3891
+ // Unfortunately in some browsers we lose the backtrace if we rethrow the existing error,
3892
+ // so in the event that we don't have an `onerror` handler we don't wrap in a try/catch
3893
+ if ('function' === typeof Ember.onerror) {
3894
+ try {
3895
+ // IE8's Function.prototype.apply doesn't accept undefined/null arguments.
3896
+ return method.apply(target || this, args || []);
3897
+ } catch (error) {
3898
+ Ember.onerror(error);
3899
+ }
3900
+ } else {
3901
+ // IE8's Function.prototype.apply doesn't accept undefined/null arguments.
3902
+ return method.apply(target || this, args || []);
3903
+ }
3807
3904
  }
3808
3905
 
3809
3906
 
@@ -3948,8 +4045,11 @@ Ember.run = run = function(target, method) {
3948
4045
 
3949
4046
  var ret, loop;
3950
4047
  run.begin();
3951
- if (target || method) ret = invoke(target, method, arguments, 2);
3952
- run.end();
4048
+ try {
4049
+ if (target || method) ret = invoke(target, method, arguments, 2);
4050
+ } finally {
4051
+ run.end();
4052
+ }
3953
4053
  return ret;
3954
4054
  };
3955
4055
 
@@ -4257,11 +4357,17 @@ Ember.run.cancel = function(timer) {
4257
4357
  delete timers[timer];
4258
4358
  };
4259
4359
 
4260
-
4261
4360
  // ..........................................................
4262
4361
  // DEPRECATED API
4263
4362
  //
4264
4363
 
4364
+ /**
4365
+ @namespace
4366
+ @name Ember.RunLoop
4367
+ @deprecated
4368
+ @description Compatibility for Ember.run
4369
+ */
4370
+
4265
4371
  /**
4266
4372
  @deprecated
4267
4373
  @method
@@ -4394,7 +4500,8 @@ var NOT = {
4394
4500
  var get = Ember.get,
4395
4501
  getPath = Ember.getPath,
4396
4502
  setPath = Ember.setPath,
4397
- guidFor = Ember.guidFor;
4503
+ guidFor = Ember.guidFor,
4504
+ isGlobalPath = Ember.isGlobalPath;
4398
4505
 
4399
4506
  // Applies a binding's transformations against a value.
4400
4507
  function getTransformedValue(binding, val, obj, dir) {
@@ -4422,9 +4529,18 @@ function empty(val) {
4422
4529
  return val===undefined || val===null || val==='' || (Ember.isArray(val) && get(val, 'length')===0) ;
4423
4530
  }
4424
4531
 
4532
+ function getPathWithGlobals(obj, path) {
4533
+ return getPath(isGlobalPath(path) ? window : obj, path);
4534
+ }
4535
+
4425
4536
  function getTransformedFromValue(obj, binding) {
4426
- var operation = binding._operation;
4427
- var fromValue = operation ? operation(obj, binding._from, binding._operand) : getPath(obj, binding._from);
4537
+ var operation = binding._operation,
4538
+ fromValue;
4539
+ if (operation) {
4540
+ fromValue = operation(obj, binding._from, binding._operand);
4541
+ } else {
4542
+ fromValue = getPathWithGlobals(obj, binding._from);
4543
+ }
4428
4544
  return getTransformedValue(binding, fromValue, obj, 'to');
4429
4545
  }
4430
4546
 
@@ -4434,177 +4550,17 @@ function getTransformedToValue(obj, binding) {
4434
4550
  }
4435
4551
 
4436
4552
  var AND_OPERATION = function(obj, left, right) {
4437
- return getPath(obj, left) && getPath(obj, right);
4553
+ return getPathWithGlobals(obj, left) && getPathWithGlobals(obj, right);
4438
4554
  };
4439
4555
 
4440
4556
  var OR_OPERATION = function(obj, left, right) {
4441
- return getPath(obj, left) || getPath(obj, right);
4557
+ return getPathWithGlobals(obj, left) || getPathWithGlobals(obj, right);
4442
4558
  };
4443
4559
 
4444
4560
  // ..........................................................
4445
4561
  // BINDING
4446
4562
  //
4447
4563
 
4448
- /**
4449
- @class
4450
-
4451
- A binding simply connects the properties of two objects so that whenever the
4452
- value of one property changes, the other property will be changed also. You
4453
- do not usually work with Binding objects directly but instead describe
4454
- bindings in your class definition using something like:
4455
-
4456
- valueBinding: "MyApp.someController.title"
4457
-
4458
- This will create a binding from `MyApp.someController.title` to the `value`
4459
- property of your object instance automatically. Now the two values will be
4460
- kept in sync.
4461
-
4462
- ## Customizing Your Bindings
4463
-
4464
- In addition to synchronizing values, bindings can also perform some basic
4465
- transforms on values. These transforms can help to make sure the data fed
4466
- into one object always meets the expectations of that object regardless of
4467
- what the other object outputs.
4468
-
4469
- To customize a binding, you can use one of the many helper methods defined
4470
- on Ember.Binding like so:
4471
-
4472
- valueBinding: Ember.Binding.single("MyApp.someController.title")
4473
-
4474
- This will create a binding just like the example above, except that now the
4475
- binding will convert the value of `MyApp.someController.title` to a single
4476
- object (removing any arrays) before applying it to the `value` property of
4477
- your object.
4478
-
4479
- You can also chain helper methods to build custom bindings like so:
4480
-
4481
- valueBinding: Ember.Binding.single("MyApp.someController.title").notEmpty("(EMPTY)")
4482
-
4483
- This will force the value of MyApp.someController.title to be a single value
4484
- and then check to see if the value is "empty" (null, undefined, empty array,
4485
- or an empty string). If it is empty, the value will be set to the string
4486
- "(EMPTY)".
4487
-
4488
- ## One Way Bindings
4489
-
4490
- One especially useful binding customization you can use is the `oneWay()`
4491
- helper. This helper tells Ember that you are only interested in
4492
- receiving changes on the object you are binding from. For example, if you
4493
- are binding to a preference and you want to be notified if the preference
4494
- has changed, but your object will not be changing the preference itself, you
4495
- could do:
4496
-
4497
- bigTitlesBinding: Ember.Binding.oneWay("MyApp.preferencesController.bigTitles")
4498
-
4499
- This way if the value of MyApp.preferencesController.bigTitles changes the
4500
- "bigTitles" property of your object will change also. However, if you
4501
- change the value of your "bigTitles" property, it will not update the
4502
- preferencesController.
4503
-
4504
- One way bindings are almost twice as fast to setup and twice as fast to
4505
- execute because the binding only has to worry about changes to one side.
4506
-
4507
- You should consider using one way bindings anytime you have an object that
4508
- may be created frequently and you do not intend to change a property; only
4509
- to monitor it for changes. (such as in the example above).
4510
-
4511
- ## Adding Custom Transforms
4512
-
4513
- In addition to using the standard helpers provided by Ember, you can
4514
- also defined your own custom transform functions which will be used to
4515
- convert the value. To do this, just define your transform function and add
4516
- it to the binding with the transform() helper. The following example will
4517
- not allow Integers less than ten. Note that it checks the value of the
4518
- bindings and allows all other values to pass:
4519
-
4520
- valueBinding: Ember.Binding.transform(function(value, binding) {
4521
- return ((Ember.typeOf(value) === 'number') && (value < 10)) ? 10 : value;
4522
- }).from("MyApp.someController.value")
4523
-
4524
- If you would like to instead use this transform on a number of bindings,
4525
- you can also optionally add your own helper method to Ember.Binding. This
4526
- method should simply return the value of `this.transform()`. The example
4527
- below adds a new helper called `notLessThan()` which will limit the value to
4528
- be not less than the passed minimum:
4529
-
4530
- Ember.Binding.reopen({
4531
- notLessThan: function(minValue) {
4532
- return this.transform(function(value, binding) {
4533
- return ((Ember.typeOf(value) === 'number') && (value < minValue)) ? minValue : value;
4534
- });
4535
- }
4536
- });
4537
-
4538
- You could specify this in your core.js file, for example. Then anywhere in
4539
- your application you can use it to define bindings like so:
4540
-
4541
- valueBinding: Ember.Binding.from("MyApp.someController.value").notLessThan(10)
4542
-
4543
- Also, remember that helpers are chained so you can use your helper along
4544
- with any other helpers. The example below will create a one way binding that
4545
- does not allow empty values or values less than 10:
4546
-
4547
- valueBinding: Ember.Binding.oneWay("MyApp.someController.value").notEmpty().notLessThan(10)
4548
-
4549
- ## How to Manually Adding Binding
4550
-
4551
- All of the examples above show you how to configure a custom binding, but
4552
- the result of these customizations will be a binding template, not a fully
4553
- active binding. The binding will actually become active only when you
4554
- instantiate the object the binding belongs to. It is useful however, to
4555
- understand what actually happens when the binding is activated.
4556
-
4557
- For a binding to function it must have at least a "from" property and a "to"
4558
- property. The from property path points to the object/key that you want to
4559
- bind from while the to path points to the object/key you want to bind to.
4560
-
4561
- When you define a custom binding, you are usually describing the property
4562
- you want to bind from (such as "MyApp.someController.value" in the examples
4563
- above). When your object is created, it will automatically assign the value
4564
- you want to bind "to" based on the name of your binding key. In the
4565
- examples above, during init, Ember objects will effectively call
4566
- something like this on your binding:
4567
-
4568
- binding = Ember.Binding.from(this.valueBinding).to("value");
4569
-
4570
- This creates a new binding instance based on the template you provide, and
4571
- sets the to path to the "value" property of the new object. Now that the
4572
- binding is fully configured with a "from" and a "to", it simply needs to be
4573
- connected to become active. This is done through the connect() method:
4574
-
4575
- binding.connect(this);
4576
-
4577
- Note that when you connect a binding you pass the object you want it to be
4578
- connected to. This object will be used as the root for both the from and
4579
- to side of the binding when inspecting relative paths. This allows the
4580
- binding to be automatically inherited by subclassed objects as well.
4581
-
4582
- Now that the binding is connected, it will observe both the from and to side
4583
- and relay changes.
4584
-
4585
- If you ever needed to do so (you almost never will, but it is useful to
4586
- understand this anyway), you could manually create an active binding by
4587
- using the Ember.bind() helper method. (This is the same method used by
4588
- to setup your bindings on objects):
4589
-
4590
- Ember.bind(MyApp.anotherObject, "value", "MyApp.someController.value");
4591
-
4592
- Both of these code fragments have the same effect as doing the most friendly
4593
- form of binding creation like so:
4594
-
4595
- MyApp.anotherObject = Ember.Object.create({
4596
- valueBinding: "MyApp.someController.value",
4597
-
4598
- // OTHER CODE FOR THIS OBJECT...
4599
-
4600
- });
4601
-
4602
- Ember's built in binding creation method makes it easy to automatically
4603
- create bindings for you. You should always use the highest-level APIs
4604
- available, even if you understand how to it works underneath.
4605
-
4606
- @since Ember 0.9
4607
- */
4608
4564
  var K = function() {};
4609
4565
  var Binding = function(toPath, fromPath) {
4610
4566
  var self;
@@ -4627,7 +4583,7 @@ var Binding = function(toPath, fromPath) {
4627
4583
 
4628
4584
  K.prototype = Binding.prototype;
4629
4585
 
4630
- Binding.prototype = {
4586
+ Binding.prototype = /** @scope Ember.Binding.prototype */ {
4631
4587
  // ..........................................................
4632
4588
  // CONFIG
4633
4589
  //
@@ -4951,7 +4907,7 @@ Binding.prototype = {
4951
4907
 
4952
4908
  // get the direction of the binding for the object we are
4953
4909
  // synchronizing from
4954
- var guid = guidFor(obj), direction = this[guid], val, transformedValue;
4910
+ var guid = guidFor(obj), direction = this[guid];
4955
4911
 
4956
4912
  var fromPath = this._from, toPath = this._to;
4957
4913
 
@@ -4965,13 +4921,13 @@ Binding.prototype = {
4965
4921
 
4966
4922
  // if we're synchronizing from the remote object...
4967
4923
  if (direction === 'fwd') {
4968
- if (log) { Ember.Logger.log(' ', this.toString(), val, '->', fromValue, obj); }
4969
- Ember.trySetPath(obj, toPath, fromValue);
4924
+ if (log) { Ember.Logger.log(' ', this.toString(), toValue, '->', fromValue, obj); }
4925
+ Ember.trySetPath(Ember.isGlobalPath(toPath) ? window : obj, toPath, fromValue);
4970
4926
 
4971
4927
  // if we're synchronizing *to* the remote object
4972
4928
  } else if (direction === 'back') {// && !this._oneWay) {
4973
- if (log) { Ember.Logger.log(' ', this.toString(), val, '<-', fromValue, obj); }
4974
- Ember.trySetPath(obj, fromPath, toValue);
4929
+ if (log) { Ember.Logger.log(' ', this.toString(), toValue, '<-', fromValue, obj); }
4930
+ Ember.trySetPath(Ember.isGlobalPath(fromPath) ? window : obj, fromPath, toValue);
4975
4931
  }
4976
4932
  }
4977
4933
 
@@ -4985,7 +4941,8 @@ function mixinProperties(to, from) {
4985
4941
  }
4986
4942
  }
4987
4943
 
4988
- mixinProperties(Binding, {
4944
+ mixinProperties(Binding,
4945
+ /** @scope Ember.Binding */ {
4989
4946
 
4990
4947
  /**
4991
4948
  @see Ember.Binding.prototype.from
@@ -5103,13 +5060,182 @@ mixinProperties(Binding, {
5103
5060
 
5104
5061
  });
5105
5062
 
5106
- Ember.Binding = Binding;
5107
-
5108
5063
  /**
5109
- Global helper method to create a new binding. Just pass the root object
5110
- along with a to and from path to create and connect the binding. The new
5111
- binding object will be returned which you can further configure with
5112
- transforms and other conditions.
5064
+ @class
5065
+
5066
+ A binding simply connects the properties of two objects so that whenever the
5067
+ value of one property changes, the other property will be changed also. You
5068
+ do not usually work with Binding objects directly but instead describe
5069
+ bindings in your class definition using something like:
5070
+
5071
+ valueBinding: "MyApp.someController.title"
5072
+
5073
+ This will create a binding from `MyApp.someController.title` to the `value`
5074
+ property of your object instance automatically. Now the two values will be
5075
+ kept in sync.
5076
+
5077
+ ## Customizing Your Bindings
5078
+
5079
+ In addition to synchronizing values, bindings can also perform some basic
5080
+ transforms on values. These transforms can help to make sure the data fed
5081
+ into one object always meets the expectations of that object regardless of
5082
+ what the other object outputs.
5083
+
5084
+ To customize a binding, you can use one of the many helper methods defined
5085
+ on Ember.Binding like so:
5086
+
5087
+ valueBinding: Ember.Binding.single("MyApp.someController.title")
5088
+
5089
+ This will create a binding just like the example above, except that now the
5090
+ binding will convert the value of `MyApp.someController.title` to a single
5091
+ object (removing any arrays) before applying it to the `value` property of
5092
+ your object.
5093
+
5094
+ You can also chain helper methods to build custom bindings like so:
5095
+
5096
+ valueBinding: Ember.Binding.single("MyApp.someController.title").notEmpty("(EMPTY)")
5097
+
5098
+ This will force the value of MyApp.someController.title to be a single value
5099
+ and then check to see if the value is "empty" (null, undefined, empty array,
5100
+ or an empty string). If it is empty, the value will be set to the string
5101
+ "(EMPTY)".
5102
+
5103
+ ## One Way Bindings
5104
+
5105
+ One especially useful binding customization you can use is the `oneWay()`
5106
+ helper. This helper tells Ember that you are only interested in
5107
+ receiving changes on the object you are binding from. For example, if you
5108
+ are binding to a preference and you want to be notified if the preference
5109
+ has changed, but your object will not be changing the preference itself, you
5110
+ could do:
5111
+
5112
+ bigTitlesBinding: Ember.Binding.oneWay("MyApp.preferencesController.bigTitles")
5113
+
5114
+ This way if the value of MyApp.preferencesController.bigTitles changes the
5115
+ "bigTitles" property of your object will change also. However, if you
5116
+ change the value of your "bigTitles" property, it will not update the
5117
+ preferencesController.
5118
+
5119
+ One way bindings are almost twice as fast to setup and twice as fast to
5120
+ execute because the binding only has to worry about changes to one side.
5121
+
5122
+ You should consider using one way bindings anytime you have an object that
5123
+ may be created frequently and you do not intend to change a property; only
5124
+ to monitor it for changes. (such as in the example above).
5125
+
5126
+ ## Adding Custom Transforms
5127
+
5128
+ In addition to using the standard helpers provided by Ember, you can
5129
+ also defined your own custom transform functions which will be used to
5130
+ convert the value. To do this, just define your transform function and add
5131
+ it to the binding with the transform() helper. The following example will
5132
+ not allow Integers less than ten. Note that it checks the value of the
5133
+ bindings and allows all other values to pass:
5134
+
5135
+ valueBinding: Ember.Binding.transform(function(value, binding) {
5136
+ return ((Ember.typeOf(value) === 'number') && (value < 10)) ? 10 : value;
5137
+ }).from("MyApp.someController.value")
5138
+
5139
+ If you would like to instead use this transform on a number of bindings,
5140
+ you can also optionally add your own helper method to Ember.Binding. This
5141
+ method should simply return the value of `this.transform()`. The example
5142
+ below adds a new helper called `notLessThan()` which will limit the value to
5143
+ be not less than the passed minimum:
5144
+
5145
+ Ember.Binding.reopen({
5146
+ notLessThan: function(minValue) {
5147
+ return this.transform(function(value, binding) {
5148
+ return ((Ember.typeOf(value) === 'number') && (value < minValue)) ? minValue : value;
5149
+ });
5150
+ }
5151
+ });
5152
+
5153
+ You could specify this in your core.js file, for example. Then anywhere in
5154
+ your application you can use it to define bindings like so:
5155
+
5156
+ valueBinding: Ember.Binding.from("MyApp.someController.value").notLessThan(10)
5157
+
5158
+ Also, remember that helpers are chained so you can use your helper along
5159
+ with any other helpers. The example below will create a one way binding that
5160
+ does not allow empty values or values less than 10:
5161
+
5162
+ valueBinding: Ember.Binding.oneWay("MyApp.someController.value").notEmpty().notLessThan(10)
5163
+
5164
+ Finally, it's also possible to specify bi-directional transforms. To do this,
5165
+ you can pass a hash to `transform` with `to` and `from`. In the following
5166
+ example, we are expecting a lowercase string that we want to transform to
5167
+ uppercase.
5168
+
5169
+ valueBinding: Ember.Binding.transform({
5170
+ to: function(value, binding) { return value.toUpperCase(); },
5171
+ from: function(value, binding) { return value.toLowerCase(); }
5172
+
5173
+ ## How to Manually Adding Binding
5174
+
5175
+ All of the examples above show you how to configure a custom binding, but
5176
+ the result of these customizations will be a binding template, not a fully
5177
+ active binding. The binding will actually become active only when you
5178
+ instantiate the object the binding belongs to. It is useful however, to
5179
+ understand what actually happens when the binding is activated.
5180
+
5181
+ For a binding to function it must have at least a "from" property and a "to"
5182
+ property. The from property path points to the object/key that you want to
5183
+ bind from while the to path points to the object/key you want to bind to.
5184
+
5185
+ When you define a custom binding, you are usually describing the property
5186
+ you want to bind from (such as "MyApp.someController.value" in the examples
5187
+ above). When your object is created, it will automatically assign the value
5188
+ you want to bind "to" based on the name of your binding key. In the
5189
+ examples above, during init, Ember objects will effectively call
5190
+ something like this on your binding:
5191
+
5192
+ binding = Ember.Binding.from(this.valueBinding).to("value");
5193
+
5194
+ This creates a new binding instance based on the template you provide, and
5195
+ sets the to path to the "value" property of the new object. Now that the
5196
+ binding is fully configured with a "from" and a "to", it simply needs to be
5197
+ connected to become active. This is done through the connect() method:
5198
+
5199
+ binding.connect(this);
5200
+
5201
+ Note that when you connect a binding you pass the object you want it to be
5202
+ connected to. This object will be used as the root for both the from and
5203
+ to side of the binding when inspecting relative paths. This allows the
5204
+ binding to be automatically inherited by subclassed objects as well.
5205
+
5206
+ Now that the binding is connected, it will observe both the from and to side
5207
+ and relay changes.
5208
+
5209
+ If you ever needed to do so (you almost never will, but it is useful to
5210
+ understand this anyway), you could manually create an active binding by
5211
+ using the Ember.bind() helper method. (This is the same method used by
5212
+ to setup your bindings on objects):
5213
+
5214
+ Ember.bind(MyApp.anotherObject, "value", "MyApp.someController.value");
5215
+
5216
+ Both of these code fragments have the same effect as doing the most friendly
5217
+ form of binding creation like so:
5218
+
5219
+ MyApp.anotherObject = Ember.Object.create({
5220
+ valueBinding: "MyApp.someController.value",
5221
+
5222
+ // OTHER CODE FOR THIS OBJECT...
5223
+
5224
+ });
5225
+
5226
+ Ember's built in binding creation method makes it easy to automatically
5227
+ create bindings for you. You should always use the highest-level APIs
5228
+ available, even if you understand how to it works underneath.
5229
+
5230
+ @since Ember 0.9
5231
+ */
5232
+ Ember.Binding = Binding;
5233
+
5234
+ /**
5235
+ Global helper method to create a new binding. Just pass the root object
5236
+ along with a to and from path to create and connect the binding. The new
5237
+ binding object will be returned which you can further configure with
5238
+ transforms and other conditions.
5113
5239
 
5114
5240
  @param {Object} obj
5115
5241
  The root object of the transform.
@@ -5210,6 +5336,9 @@ function ComputedProperty(func, opts) {
5210
5336
  this._dependentKeys = opts && opts.dependentKeys;
5211
5337
  }
5212
5338
 
5339
+ /**
5340
+ @constructor
5341
+ */
5213
5342
  Ember.ComputedProperty = ComputedProperty;
5214
5343
  ComputedProperty.prototype = new Ember.Descriptor();
5215
5344
 
@@ -5265,6 +5394,10 @@ function mkCpSetter(keyName, desc) {
5265
5394
  };
5266
5395
  }
5267
5396
 
5397
+ /**
5398
+ @extends Ember.ComputedProperty
5399
+ @private
5400
+ */
5268
5401
  var Cp = ComputedProperty.prototype;
5269
5402
 
5270
5403
  /**
@@ -5434,6 +5567,7 @@ var array_Slice = Array.prototype.slice;
5434
5567
 
5435
5568
  */
5436
5569
 
5570
+ /** @private */
5437
5571
  var metaPath = Ember.metaPath;
5438
5572
 
5439
5573
  // Gets the set of all actions, keyed on the guid of each action's
@@ -5505,6 +5639,8 @@ function invokeEvents(targetSet, params) {
5505
5639
  parameters passed to an observer. if you pass an xform function, it will
5506
5640
  be invoked and is able to translate event listener parameters into the form
5507
5641
  that observers are expecting.
5642
+
5643
+ @name Ember.addListener
5508
5644
  */
5509
5645
  function addListener(obj, eventName, target, method, xform) {
5510
5646
  ember_assert("You must pass at least an object and event name to Ember.addListener", !!obj && !!eventName);
@@ -5563,7 +5699,6 @@ function watchedEvents(obj) {
5563
5699
  }
5564
5700
 
5565
5701
  function sendEvent(obj, eventName) {
5566
- ember_assert("You must pass an object and event name to Ember.sendEvent", !!obj && !!eventName);
5567
5702
 
5568
5703
  // first give object a chance to handle it
5569
5704
  if (obj !== Ember && 'function' === typeof obj.sendEvent) {
@@ -5639,6 +5774,7 @@ var Mixin, MixinDelegate, REQUIRED, Alias;
5639
5774
  var classToString, superClassString;
5640
5775
 
5641
5776
  var a_map = Array.prototype.map;
5777
+ var a_slice = Array.prototype.slice;
5642
5778
  var EMPTY_META = {}; // dummy for non-writable meta
5643
5779
  var META_SKIP = { __emberproto__: true, __ember_count__: true };
5644
5780
 
@@ -5886,17 +6022,21 @@ function applyMixin(obj, mixins, partial) {
5886
6022
  }
5887
6023
 
5888
6024
  Ember.mixin = function(obj) {
5889
- var args = Array.prototype.slice.call(arguments, 1);
6025
+ var args = a_slice.call(arguments, 1);
5890
6026
  return applyMixin(obj, args, false);
5891
6027
  };
5892
6028
 
5893
6029
 
6030
+ /**
6031
+ @constructor
6032
+ @name Ember.Mixin
6033
+ */
5894
6034
  Mixin = function() { return initMixin(this, arguments); };
5895
6035
 
5896
6036
  Mixin._apply = applyMixin;
5897
6037
 
5898
6038
  Mixin.applyPartial = function(obj) {
5899
- var args = Array.prototype.slice.call(arguments, 1);
6039
+ var args = a_slice.call(arguments, 1);
5900
6040
  return applyMixin(obj, args, true);
5901
6041
  };
5902
6042
 
@@ -5935,15 +6075,17 @@ Mixin.prototype.reopen = function() {
5935
6075
 
5936
6076
  var TMP_ARRAY = [];
5937
6077
  Mixin.prototype.apply = function(obj) {
5938
- TMP_ARRAY.length=0;
5939
6078
  TMP_ARRAY[0] = this;
5940
- return applyMixin(obj, TMP_ARRAY, false);
6079
+ var ret = applyMixin(obj, TMP_ARRAY, false);
6080
+ TMP_ARRAY.length=0;
6081
+ return ret;
5941
6082
  };
5942
6083
 
5943
6084
  Mixin.prototype.applyPartial = function(obj) {
5944
- TMP_ARRAY.length=0;
5945
6085
  TMP_ARRAY[0] = this;
5946
- return applyMixin(obj, TMP_ARRAY, true);
6086
+ var ret = applyMixin(obj, TMP_ARRAY, true);
6087
+ TMP_ARRAY.length=0;
6088
+ return ret;
5947
6089
  };
5948
6090
 
5949
6091
  function _detect(curMixin, targetMixin, seen) {
@@ -5968,7 +6110,7 @@ Mixin.prototype.detect = function(obj) {
5968
6110
 
5969
6111
  Mixin.prototype.without = function() {
5970
6112
  var ret = new Mixin(this);
5971
- ret._without = Array.prototype.slice.call(arguments);
6113
+ ret._without = a_slice.call(arguments);
5972
6114
  return ret;
5973
6115
  };
5974
6116
 
@@ -6025,6 +6167,9 @@ function findNamespaces() {
6025
6167
  if (Namespace.PROCESSED) { return; }
6026
6168
 
6027
6169
  for (var prop in window) {
6170
+ // get(window.globalStorage, 'isNamespace') would try to read the storage for domain isNamespace and cause exception in Firefox.
6171
+ // globalStorage is a storage obsoleted by the WhatWG storage specification. See https://developer.mozilla.org/en/DOM/Storage#globalStorage
6172
+ if (prop === "globalStorage" && window.StorageList && window.globalStorage instanceof window.StorageList) { continue; }
6028
6173
  // Unfortunately, some versions of IE don't support window.hasOwnProperty
6029
6174
  if (window.hasOwnProperty && !window.hasOwnProperty(prop)) { continue; }
6030
6175
 
@@ -6130,13 +6275,13 @@ Ember.MixinDelegate = MixinDelegate;
6130
6275
  //
6131
6276
 
6132
6277
  Ember.observer = function(func) {
6133
- var paths = Array.prototype.slice.call(arguments, 1);
6278
+ var paths = a_slice.call(arguments, 1);
6134
6279
  func.__ember_observes__ = paths;
6135
6280
  return func;
6136
6281
  };
6137
6282
 
6138
6283
  Ember.beforeObserver = function(func) {
6139
- var paths = Array.prototype.slice.call(arguments, 1);
6284
+ var paths = a_slice.call(arguments, 1);
6140
6285
  func.__ember_observesBefore__ = paths;
6141
6286
  return func;
6142
6287
  };
@@ -6174,6 +6319,7 @@ Ember.beforeObserver = function(func) {
6174
6319
  //
6175
6320
 
6176
6321
  var get = Ember.get, set = Ember.set;
6322
+ var a_slice = Array.prototype.slice;
6177
6323
 
6178
6324
  var contexts = [];
6179
6325
  function popCtx() {
@@ -6186,9 +6332,11 @@ function pushCtx(ctx) {
6186
6332
  }
6187
6333
 
6188
6334
  function iter(key, value) {
6335
+ var valueProvided = arguments.length === 2;
6336
+
6189
6337
  function i(item) {
6190
6338
  var cur = get(item, key);
6191
- return value===undefined ? !!cur : value===cur;
6339
+ return valueProvided ? value===cur : !!cur;
6192
6340
  }
6193
6341
  return i ;
6194
6342
  }
@@ -6283,6 +6431,13 @@ Ember.Enumerable = Ember.Mixin.create( /** @lends Ember.Enumerable */ {
6283
6431
  If your enumerable is empty, this method should return undefined.
6284
6432
 
6285
6433
  @returns {Object} the object or undefined
6434
+
6435
+ @example
6436
+ var arr = ["a", "b", "c"];
6437
+ arr.firstObject(); => "a"
6438
+
6439
+ var arr = [];
6440
+ arr.firstObject(); => undefined
6286
6441
  */
6287
6442
  firstObject: Ember.computed(function() {
6288
6443
  if (get(this, 'length')===0) return undefined ;
@@ -6293,12 +6448,21 @@ Ember.Enumerable = Ember.Mixin.create( /** @lends Ember.Enumerable */ {
6293
6448
  ret = this.nextObject(0, null, context);
6294
6449
  pushCtx(context);
6295
6450
  return ret ;
6296
- }).property('[]').cacheable(),
6451
+ }).property(),
6297
6452
 
6298
6453
  /**
6299
- Helper method returns the last object from a collection.
6454
+ Helper method returns the last object from a collection. If your enumerable
6455
+ contains only one object, this method should always return that object.
6456
+ If your enumerable is empty, this method should return undefined.
6300
6457
 
6301
- @returns {Object} the object or undefined
6458
+ @returns {Object} the last object or undefined
6459
+
6460
+ @example
6461
+ var arr = ["a", "b", "c"];
6462
+ arr.lastObject(); => "c"
6463
+
6464
+ var arr = [];
6465
+ arr.lastObject(); => undefined
6302
6466
  */
6303
6467
  lastObject: Ember.computed(function() {
6304
6468
  var len = get(this, 'length');
@@ -6314,8 +6478,7 @@ Ember.Enumerable = Ember.Mixin.create( /** @lends Ember.Enumerable */ {
6314
6478
  pushCtx(context);
6315
6479
  return last;
6316
6480
  }
6317
-
6318
- }).property('[]').cacheable(),
6481
+ }).property(),
6319
6482
 
6320
6483
  /**
6321
6484
  Returns true if the passed object can be found in the receiver. The
@@ -6370,18 +6533,13 @@ Ember.Enumerable = Ember.Mixin.create( /** @lends Ember.Enumerable */ {
6370
6533
  },
6371
6534
 
6372
6535
  /**
6373
- Retrieves the named value on each member object. This is more efficient
6374
- than using one of the wrapper methods defined here. Objects that
6375
- implement Ember.Observable will use the get() method, otherwise the property
6376
- will be accessed directly.
6536
+ Alias for mapProperty
6377
6537
 
6378
- @param {String} key The key to retrieve
6379
- @returns {Array} Extracted values
6538
+ @params key {String} name of the property
6539
+ @returns {Array} The mapped array.
6380
6540
  */
6381
6541
  getEach: function(key) {
6382
- return this.map(function(item) {
6383
- return get(item, key);
6384
- });
6542
+ return this.mapProperty(key);
6385
6543
  },
6386
6544
 
6387
6545
  /**
@@ -6486,7 +6644,7 @@ Ember.Enumerable = Ember.Mixin.create( /** @lends Ember.Enumerable */ {
6486
6644
  @returns {Array} filtered array
6487
6645
  */
6488
6646
  filterProperty: function(key, value) {
6489
- return this.filter(iter(key, value));
6647
+ return this.filter(iter.apply(this, arguments));
6490
6648
  },
6491
6649
 
6492
6650
  /**
@@ -6541,7 +6699,7 @@ Ember.Enumerable = Ember.Mixin.create( /** @lends Ember.Enumerable */ {
6541
6699
  @returns {Object} found item or null
6542
6700
  */
6543
6701
  findProperty: function(key, value) {
6544
- return this.find(iter(key, value));
6702
+ return this.find(iter.apply(this, arguments));
6545
6703
  },
6546
6704
 
6547
6705
  /**
@@ -6586,7 +6744,7 @@ Ember.Enumerable = Ember.Mixin.create( /** @lends Ember.Enumerable */ {
6586
6744
  @returns {Array} filtered array
6587
6745
  */
6588
6746
  everyProperty: function(key, value) {
6589
- return this.every(iter(key, value));
6747
+ return this.every(iter.apply(this, arguments));
6590
6748
  },
6591
6749
 
6592
6750
 
@@ -6632,7 +6790,7 @@ Ember.Enumerable = Ember.Mixin.create( /** @lends Ember.Enumerable */ {
6632
6790
  @returns {Boolean} true
6633
6791
  */
6634
6792
  someProperty: function(key, value) {
6635
- return this.some(iter(key, value));
6793
+ return this.some(iter.apply(this, arguments));
6636
6794
  },
6637
6795
 
6638
6796
  /**
@@ -6688,7 +6846,7 @@ Ember.Enumerable = Ember.Mixin.create( /** @lends Ember.Enumerable */ {
6688
6846
  */
6689
6847
  invoke: function(methodName) {
6690
6848
  var args, ret = [];
6691
- if (arguments.length>1) args = Array.prototype.slice.call(arguments, 1);
6849
+ if (arguments.length>1) args = a_slice.call(arguments, 1);
6692
6850
 
6693
6851
  this.forEach(function(x, idx) {
6694
6852
  var method = x && x[methodName];
@@ -6702,7 +6860,7 @@ Ember.Enumerable = Ember.Mixin.create( /** @lends Ember.Enumerable */ {
6702
6860
 
6703
6861
  /**
6704
6862
  Simply converts the enumerable into a genuine array. The order is not
6705
- gauranteed. Corresponds to the method implemented by Prototype.
6863
+ guaranteed. Corresponds to the method implemented by Prototype.
6706
6864
 
6707
6865
  @returns {Array} the enumerable as an array.
6708
6866
  */
@@ -6843,7 +7001,6 @@ Ember.Enumerable = Ember.Mixin.create( /** @lends Ember.Enumerable */ {
6843
7001
  if (removing === -1) removing = null;
6844
7002
  if (adding === -1) adding = null;
6845
7003
 
6846
- Ember.propertyWillChange(this, '[]');
6847
7004
  if (hasDelta) Ember.propertyWillChange(this, 'length');
6848
7005
  Ember.sendEvent(this, '@enumerable:before', removing, adding);
6849
7006
 
@@ -6891,7 +7048,6 @@ Ember.Enumerable = Ember.Mixin.create( /** @lends Ember.Enumerable */ {
6891
7048
 
6892
7049
  Ember.sendEvent(this, '@enumerable:change', removing, adding);
6893
7050
  if (hasDelta) Ember.propertyDidChange(this, 'length');
6894
- Ember.propertyDidChange(this, '[]');
6895
7051
 
6896
7052
  return this ;
6897
7053
  }
@@ -7031,11 +7187,23 @@ Ember.Array = Ember.Mixin.create(Ember.Enumerable, /** @scope Ember.Array.protot
7031
7187
  },
7032
7188
 
7033
7189
  /**
7034
- Returns the index for a particular object in the index.
7190
+ Returns the index of the given object's first occurrence.
7191
+ If no startAt argument is given, the starting location to
7192
+ search is 0. If it's negative, will count backward from
7193
+ the end of the array. Returns -1 if no match is found.
7035
7194
 
7036
7195
  @param {Object} object the item to search for
7037
- @param {NUmber} startAt optional starting location to search, default 0
7038
- @returns {Number} index of -1 if not found
7196
+ @param {Number} startAt optional starting location to search, default 0
7197
+ @returns {Number} index or -1 if not found
7198
+
7199
+ @example
7200
+ var arr = ["a", "b", "c", "d", "a"];
7201
+ arr.indexOf("a"); => 0
7202
+ arr.indexOf("z"); => -1
7203
+ arr.indexOf("a", 2); => 4
7204
+ arr.indexOf("a", -1); => 4
7205
+ arr.indexOf("b", 3); => -1
7206
+ arr.indexOf("a", 100); => -1
7039
7207
  */
7040
7208
  indexOf: function(object, startAt) {
7041
7209
  var idx, len = get(this, 'length');
@@ -7050,16 +7218,28 @@ Ember.Array = Ember.Mixin.create(Ember.Enumerable, /** @scope Ember.Array.protot
7050
7218
  },
7051
7219
 
7052
7220
  /**
7053
- Returns the last index for a particular object in the index.
7221
+ Returns the index of the given object's last occurrence.
7222
+ If no startAt argument is given, the search starts from
7223
+ the last position. If it's negative, will count backward
7224
+ from the end of the array. Returns -1 if no match is found.
7054
7225
 
7055
7226
  @param {Object} object the item to search for
7056
- @param {NUmber} startAt optional starting location to search, default 0
7057
- @returns {Number} index of -1 if not found
7227
+ @param {Number} startAt optional starting location to search, default 0
7228
+ @returns {Number} index or -1 if not found
7229
+
7230
+ @example
7231
+ var arr = ["a", "b", "c", "d", "a"];
7232
+ arr.lastIndexOf("a"); => 4
7233
+ arr.lastIndexOf("z"); => -1
7234
+ arr.lastIndexOf("a", 2); => 0
7235
+ arr.lastIndexOf("a", -1); => 4
7236
+ arr.lastIndexOf("b", 3); => 1
7237
+ arr.lastIndexOf("a", 100); => 4
7058
7238
  */
7059
7239
  lastIndexOf: function(object, startAt) {
7060
7240
  var idx, len = get(this, 'length');
7061
7241
 
7062
- if (startAt === undefined) startAt = len-1;
7242
+ if (startAt === undefined || startAt >= len) startAt = len-1;
7063
7243
  if (startAt < 0) startAt += len;
7064
7244
 
7065
7245
  for(idx=startAt;idx>=0;idx--) {
@@ -7704,11 +7884,12 @@ Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ {
7704
7884
  @returns {Ember.Observable}
7705
7885
  */
7706
7886
  setProperties: function(hash) {
7707
- Ember.beginPropertyChanges(this);
7708
- for(var prop in hash) {
7709
- if (hash.hasOwnProperty(prop)) set(this, prop, hash[prop]);
7710
- }
7711
- Ember.endPropertyChanges(this);
7887
+ var self = this;
7888
+ Ember.changeProperties(function(){
7889
+ for(var prop in hash) {
7890
+ if (hash.hasOwnProperty(prop)) set(self, prop, hash[prop]);
7891
+ }
7892
+ });
7712
7893
  return this;
7713
7894
  },
7714
7895
 
@@ -7981,7 +8162,8 @@ function makeCtor() {
7981
8162
 
7982
8163
  var CoreObject = makeCtor();
7983
8164
 
7984
- CoreObject.PrototypeMixin = Ember.Mixin.create({
8165
+ CoreObject.PrototypeMixin = Ember.Mixin.create(
8166
+ /** @scope Ember.CoreObject */ {
7985
8167
 
7986
8168
  reopen: function() {
7987
8169
  Ember.Mixin._apply(this, arguments, true);
@@ -8019,7 +8201,7 @@ CoreObject.PrototypeMixin = Ember.Mixin.create({
8019
8201
  @private
8020
8202
  */
8021
8203
  _scheduledDestroy: function() {
8022
- this[Ember.META_KEY] = null;
8204
+ Ember.destroy(this);
8023
8205
  },
8024
8206
 
8025
8207
  bind: function(to, from) {
@@ -8111,6 +8293,9 @@ var ClassMixin = Ember.Mixin.create({
8111
8293
  CoreObject.ClassMixin = ClassMixin;
8112
8294
  ClassMixin.apply(CoreObject);
8113
8295
 
8296
+ /**
8297
+ @class
8298
+ */
8114
8299
  Ember.CoreObject = CoreObject;
8115
8300
 
8116
8301
 
@@ -8239,14 +8424,13 @@ Ember.none = function(obj) {
8239
8424
  };
8240
8425
 
8241
8426
  /**
8242
- Verifies that a value is either null or an empty string. Return false if
8243
- the object is not a string.
8427
+ Verifies that a value is null or an empty string | array | function.
8244
8428
 
8245
8429
  @param {Object} obj Value to test
8246
8430
  @returns {Boolean}
8247
8431
  */
8248
8432
  Ember.empty = function(obj) {
8249
- return obj === null || obj === undefined || obj === '';
8433
+ return obj === null || obj === undefined || (obj.length === 0 && typeof obj !== 'function');
8250
8434
  };
8251
8435
 
8252
8436
  /**
@@ -8518,12 +8702,15 @@ Ember.Error.prototype = Ember.create(Error.prototype);
8518
8702
  var STRING_DASHERIZE_REGEXP = (/[ _]/g);
8519
8703
  var STRING_DASHERIZE_CACHE = {};
8520
8704
  var STRING_DECAMELIZE_REGEXP = (/([a-z])([A-Z])/g);
8521
-
8705
+ var STRING_CAMELIZE_REGEXP = (/(\-|_|\s)+(.)?/g);
8706
+ var STRING_UNDERSCORE_REGEXP_1 = (/([a-z\d])([A-Z]+)/g);
8707
+ var STRING_UNDERSCORE_REGEXP_2 = (/\-|\s+/g);
8708
+
8522
8709
  /**
8523
- Defines the hash of localized strings for the current language. Used by
8710
+ Defines the hash of localized strings for the current language. Used by
8524
8711
  the `Ember.String.loc()` helper. To localize, add string values to this
8525
8712
  hash.
8526
-
8713
+
8527
8714
  @property {String}
8528
8715
  */
8529
8716
  Ember.STRINGS = {};
@@ -8532,7 +8719,7 @@ Ember.STRINGS = {};
8532
8719
  Defines string helper methods including string formatting and localization.
8533
8720
  Unless Ember.EXTEND_PROTOTYPES = false these methods will also be added to the
8534
8721
  String.prototype as well.
8535
-
8722
+
8536
8723
  @namespace
8537
8724
  */
8538
8725
  Ember.String = {
@@ -8567,35 +8754,35 @@ Ember.String = {
8567
8754
 
8568
8755
  /**
8569
8756
  Formats the passed string, but first looks up the string in the localized
8570
- strings hash. This is a convenient way to localize text. See
8757
+ strings hash. This is a convenient way to localize text. See
8571
8758
  `Ember.String.fmt()` for more information on formatting.
8572
-
8759
+
8573
8760
  Note that it is traditional but not required to prefix localized string
8574
8761
  keys with an underscore or other character so you can easily identify
8575
8762
  localized strings.
8576
-
8763
+
8577
8764
  # Example Usage
8578
-
8765
+
8579
8766
  @javascript@
8580
8767
  Ember.STRINGS = {
8581
8768
  '_Hello World': 'Bonjour le monde',
8582
8769
  '_Hello %@ %@': 'Bonjour %@ %@'
8583
8770
  };
8584
-
8771
+
8585
8772
  Ember.String.loc("_Hello World");
8586
8773
  => 'Bonjour le monde';
8587
-
8774
+
8588
8775
  Ember.String.loc("_Hello %@ %@", ["John", "Smith"]);
8589
8776
  => "Bonjour John Smith";
8590
-
8591
-
8592
-
8777
+
8778
+
8779
+
8593
8780
  @param {String} str
8594
8781
  The string to format
8595
-
8782
+
8596
8783
  @param {Array} formats
8597
8784
  Optional array of parameters to interpolate into string.
8598
-
8785
+
8599
8786
  @returns {String} formatted string
8600
8787
  */
8601
8788
  loc: function(str, formats) {
@@ -8607,12 +8794,12 @@ Ember.String = {
8607
8794
  Splits a string into separate units separated by spaces, eliminating any
8608
8795
  empty strings in the process. This is a convenience method for split that
8609
8796
  is mostly useful when applied to the String.prototype.
8610
-
8797
+
8611
8798
  # Example Usage
8612
-
8799
+
8613
8800
  @javascript@
8614
- Ember.String.w("alpha beta gamma").forEach(function(key) {
8615
- console.log(key);
8801
+ Ember.String.w("alpha beta gamma").forEach(function(key) {
8802
+ console.log(key);
8616
8803
  });
8617
8804
  > alpha
8618
8805
  > beta
@@ -8620,11 +8807,11 @@ Ember.String = {
8620
8807
 
8621
8808
  @param {String} str
8622
8809
  The string to split
8623
-
8810
+
8624
8811
  @returns {String} split string
8625
8812
  */
8626
8813
  w: function(str) { return str.split(/\s+/); },
8627
-
8814
+
8628
8815
  /**
8629
8816
  Converts a camelized string into all lower case separated by underscores.
8630
8817
 
@@ -8668,13 +8855,52 @@ Ember.String = {
8668
8855
  }
8669
8856
 
8670
8857
  return ret;
8671
- }
8672
- };
8673
-
8674
-
8858
+ },
8675
8859
 
8860
+ /**
8861
+ Converts a dasherized string or a string with spaces or underscores into
8862
+ camelized string.
8676
8863
 
8677
- })({});
8864
+ h2. Examples
8865
+
8866
+ | *Input String* | *Output String* |
8867
+ | my favorite items | myFavoriteItems |
8868
+ | css-class-name | cssClassName |
8869
+ | action_name | actionName |
8870
+ | innerHTML | innerHTML |
8871
+
8872
+ @returns {String} the camelized string.
8873
+ */
8874
+ camelize: function(str) {
8875
+ return str.replace(STRING_CAMELIZE_REGEXP, function(match, separator, chr) {
8876
+ return chr ? chr.toUpperCase() : '';
8877
+ });
8878
+ },
8879
+
8880
+ /**
8881
+ More general than decamelize, converts a dasherized or camelcased string or a string with spaces into
8882
+ all lower case separated by undescores.
8883
+
8884
+ h2. Examples
8885
+
8886
+ | *Input String* | *Output String* |
8887
+ | my favorite items | my_favorite_items |
8888
+ | css-class-name | css_class_name |
8889
+ | action_name | action_name |
8890
+ | innerHTML | inner_html |
8891
+
8892
+ @returns {String} the camelized string.
8893
+ */
8894
+ underscore: function(str) {
8895
+ return str.replace(STRING_UNDERSCORE_REGEXP_1, '$1_$2').
8896
+ replace(STRING_UNDERSCORE_REGEXP_2, '_').toLowerCase();
8897
+ }
8898
+ };
8899
+
8900
+
8901
+
8902
+
8903
+ })({});
8678
8904
 
8679
8905
 
8680
8906
  (function(exports) {
@@ -8700,7 +8926,8 @@ var get = Ember.get, set = Ember.set;
8700
8926
 
8701
8927
  @since Ember 0.9
8702
8928
  */
8703
- Ember.Copyable = Ember.Mixin.create({
8929
+ Ember.Copyable = Ember.Mixin.create(
8930
+ /** @scope Ember.Copyable.prototype */ {
8704
8931
 
8705
8932
  /**
8706
8933
  Override to return a copy of the receiver. Default implementation raises
@@ -8809,7 +9036,8 @@ var get = Ember.get, set = Ember.set;
8809
9036
 
8810
9037
  @since Ember 0.9
8811
9038
  */
8812
- Ember.Freezable = Ember.Mixin.create({
9039
+ Ember.Freezable = Ember.Mixin.create(
9040
+ /** @scope Ember.Freezable.prototype */ {
8813
9041
 
8814
9042
  /**
8815
9043
  Set to YES when the object is frozen. Use this property to detect whether
@@ -9219,6 +9447,12 @@ Ember.Set.create = function(items) {
9219
9447
  // License: Licensed under MIT license (see license.js)
9220
9448
  // ==========================================================================
9221
9449
  Ember.CoreObject.subclasses = new Ember.Set();
9450
+
9451
+ /**
9452
+ @class
9453
+ @extends Ember.CoreObject
9454
+ @extends Ember.Observable
9455
+ */
9222
9456
  Ember.Object = Ember.CoreObject.extend(Ember.Observable);
9223
9457
 
9224
9458
 
@@ -9247,7 +9481,8 @@ var get = Ember.get, set = Ember.set;
9247
9481
  @extends Ember.Array
9248
9482
  @extends Ember.MutableArray
9249
9483
  */
9250
- Ember.ArrayProxy = Ember.Object.extend(Ember.MutableArray, {
9484
+ Ember.ArrayProxy = Ember.Object.extend(Ember.MutableArray,
9485
+ /** @scope Ember.ArrayProxy.prototype */ {
9251
9486
 
9252
9487
  /**
9253
9488
  The content array. Must be an object that implements Ember.Array and or
@@ -9379,7 +9614,7 @@ Ember.ArrayProxy = Ember.Object.extend(Ember.MutableArray, {
9379
9614
 
9380
9615
  Then, create a view that binds to your new controller:
9381
9616
 
9382
- {{collection contentBinding="MyApp.listController"}}
9617
+ {{#collection contentBinding="MyApp.listController"}}
9383
9618
  {{content.firstName}} {{content.lastName}}
9384
9619
  {{/collection}}
9385
9620
 
@@ -9409,8 +9644,10 @@ Ember.ArrayController = Ember.ArrayProxy.extend();
9409
9644
  var fmt = Ember.String.fmt,
9410
9645
  w = Ember.String.w,
9411
9646
  loc = Ember.String.loc,
9647
+ camelize = Ember.String.camelize,
9412
9648
  decamelize = Ember.String.decamelize,
9413
- dasherize = Ember.String.dasherize;
9649
+ dasherize = Ember.String.dasherize,
9650
+ underscore = Ember.String.underscore;
9414
9651
 
9415
9652
  if (Ember.EXTEND_PROTOTYPES) {
9416
9653
 
@@ -9434,23 +9671,36 @@ if (Ember.EXTEND_PROTOTYPES) {
9434
9671
  String.prototype.loc = function() {
9435
9672
  return loc(this, arguments);
9436
9673
  };
9437
-
9674
+
9675
+ /**
9676
+ @see Ember.String.camelize
9677
+ */
9678
+ String.prototype.camelize = function() {
9679
+ return camelize(this);
9680
+ };
9681
+
9438
9682
  /**
9439
9683
  @see Ember.String.decamelize
9440
9684
  */
9441
9685
  String.prototype.decamelize = function() {
9442
9686
  return decamelize(this);
9443
9687
  };
9444
-
9688
+
9445
9689
  /**
9446
9690
  @see Ember.String.dasherize
9447
9691
  */
9448
9692
  String.prototype.dasherize = function() {
9449
9693
  return dasherize(this);
9450
9694
  };
9451
- }
9452
9695
 
9696
+ /**
9697
+ @see Ember.String.underscore
9698
+ */
9699
+ String.prototype.underscore = function() {
9700
+ return underscore(this);
9701
+ };
9453
9702
 
9703
+ }
9454
9704
 
9455
9705
 
9456
9706
  })({});
@@ -9463,6 +9713,8 @@ if (Ember.EXTEND_PROTOTYPES) {
9463
9713
  // Portions ©2008-2011 Apple Inc. All rights reserved.
9464
9714
  // License: Licensed under MIT license (see license.js)
9465
9715
  // ==========================================================================
9716
+ var a_slice = Array.prototype.slice;
9717
+
9466
9718
  if (Ember.EXTEND_PROTOTYPES) {
9467
9719
 
9468
9720
  Function.prototype.property = function() {
@@ -9471,12 +9723,12 @@ if (Ember.EXTEND_PROTOTYPES) {
9471
9723
  };
9472
9724
 
9473
9725
  Function.prototype.observes = function() {
9474
- this.__ember_observes__ = Array.prototype.slice.call(arguments);
9726
+ this.__ember_observes__ = a_slice.call(arguments);
9475
9727
  return this;
9476
9728
  };
9477
9729
 
9478
9730
  Function.prototype.observesBefore = function() {
9479
- this.__ember_observesBefore__ = Array.prototype.slice.call(arguments);
9731
+ this.__ember_observesBefore__ = a_slice.call(arguments);
9480
9732
  return this;
9481
9733
  };
9482
9734
 
@@ -9617,7 +9869,7 @@ Ember.Comparable = Ember.Mixin.create( /** @scope Ember.Comparable.prototype */{
9617
9869
 
9618
9870
 
9619
9871
  (function(exports) {
9620
- var get = Ember.get, set = Ember.set;
9872
+ var get = Ember.get, set = Ember.set, getPath = Ember.getPath;
9621
9873
 
9622
9874
  Ember.TargetActionSupport = Ember.Mixin.create({
9623
9875
  target: null,
@@ -9627,7 +9879,10 @@ Ember.TargetActionSupport = Ember.Mixin.create({
9627
9879
  var target = get(this, 'target');
9628
9880
 
9629
9881
  if (Ember.typeOf(target) === "string") {
9630
- return Ember.getPath(this, target);
9882
+ // TODO: Remove the false when deprecation is done
9883
+ var value = getPath(this, target, false);
9884
+ if (value === undefined) { value = getPath(window, target); }
9885
+ return value;
9631
9886
  } else {
9632
9887
  return target;
9633
9888
  }
@@ -9638,14 +9893,21 @@ Ember.TargetActionSupport = Ember.Mixin.create({
9638
9893
  target = get(this, 'targetObject');
9639
9894
 
9640
9895
  if (target && action) {
9896
+ var ret;
9897
+
9641
9898
  if (typeof target.send === 'function') {
9642
- target.send(action, this);
9899
+ ret = target.send(action, this);
9643
9900
  } else {
9644
9901
  if (typeof action === 'string') {
9645
9902
  action = target[action];
9646
9903
  }
9647
- action.call(target, this);
9904
+ ret = action.call(target, this);
9648
9905
  }
9906
+ if (ret !== false) ret = true;
9907
+
9908
+ return ret;
9909
+ } else {
9910
+ return false;
9649
9911
  }
9650
9912
  }
9651
9913
  });
@@ -10069,7 +10331,7 @@ Ember.NativeArray = NativeArray;
10069
10331
  */
10070
10332
  Ember.A = function(arr){
10071
10333
  if (arr === undefined) { arr = []; }
10072
- return Ember.NativeArray.apply(Array.prototype.slice.apply(arr));
10334
+ return Ember.NativeArray.apply(arr);
10073
10335
  };
10074
10336
 
10075
10337
  /**
@@ -10080,6 +10342,8 @@ Ember.A = function(arr){
10080
10342
  */
10081
10343
  Ember.NativeArray.activate = function() {
10082
10344
  NativeArray.apply(Array.prototype);
10345
+
10346
+ Ember.A = function(arr) { return arr || []; }
10083
10347
  };
10084
10348
 
10085
10349
  if (Ember.EXTEND_PROTOTYPES) Ember.NativeArray.activate();
@@ -10210,7 +10474,7 @@ Ember._RenderBuffer = Ember.Object.extend(
10210
10474
  set(this ,'elementClasses', Ember.A());
10211
10475
  set(this, 'elementAttributes', {});
10212
10476
  set(this, 'elementStyle', {});
10213
- set(this, 'childBuffers', Ember.A());
10477
+ set(this, 'childBuffers', []);
10214
10478
  set(this, 'elements', {});
10215
10479
  },
10216
10480
 
@@ -10221,7 +10485,7 @@ Ember._RenderBuffer = Ember.Object.extend(
10221
10485
  @returns {Ember.RenderBuffer} this
10222
10486
  */
10223
10487
  push: function(string) {
10224
- get(this, 'childBuffers').pushObject(String(string));
10488
+ get(this, 'childBuffers').push(String(string));
10225
10489
  return this;
10226
10490
  },
10227
10491
 
@@ -10247,15 +10511,38 @@ Ember._RenderBuffer = Ember.Object.extend(
10247
10511
  return this;
10248
10512
  },
10249
10513
 
10514
+ // duck type attribute functionality like jQuery so a render buffer
10515
+ // can be used like a jQuery object in attribute binding scenarios.
10516
+
10250
10517
  /**
10251
10518
  Adds an attribute which will be rendered to the element.
10252
10519
 
10253
10520
  @param {String} name The name of the attribute
10254
10521
  @param {String} value The value to add to the attribute
10255
- @returns {Ember.RenderBuffer} this
10522
+ @returns {Ember.RenderBuffer|String} this or the current attribute value
10256
10523
  */
10257
10524
  attr: function(name, value) {
10258
- get(this, 'elementAttributes')[name] = value;
10525
+ var attributes = get(this, 'elementAttributes');
10526
+
10527
+ if (arguments.length === 1) {
10528
+ return attributes[name]
10529
+ } else {
10530
+ attributes[name] = value;
10531
+ }
10532
+
10533
+ return this;
10534
+ },
10535
+
10536
+ /**
10537
+ Remove an attribute from the list of attributes to render.
10538
+
10539
+ @param {String} name The name of the attribute
10540
+ @returns {Ember.RenderBuffer} this
10541
+ */
10542
+ removeAttr: function(name) {
10543
+ var attributes = get(this, 'elementAttributes');
10544
+ delete attributes[name];
10545
+
10259
10546
  return this;
10260
10547
  },
10261
10548
 
@@ -10333,7 +10620,7 @@ Ember._RenderBuffer = Ember.Object.extend(
10333
10620
  */
10334
10621
  begin: function(tagName) {
10335
10622
  return this.newBuffer(tagName, this, function(buffer) {
10336
- get(this, 'childBuffers').pushObject(buffer);
10623
+ get(this, 'childBuffers').push(buffer);
10337
10624
  });
10338
10625
  },
10339
10626
 
@@ -10344,7 +10631,7 @@ Ember._RenderBuffer = Ember.Object.extend(
10344
10631
  */
10345
10632
  prepend: function(tagName) {
10346
10633
  return this.newBuffer(tagName, this, function(buffer) {
10347
- get(this, 'childBuffers').insertAt(0, buffer);
10634
+ get(this, 'childBuffers').splice(0, 0, buffer);
10348
10635
  });
10349
10636
  },
10350
10637
 
@@ -10372,7 +10659,7 @@ Ember._RenderBuffer = Ember.Object.extend(
10372
10659
  return this.newBuffer(tagName, parentBuffer, function(buffer) {
10373
10660
  var siblings = get(parentBuffer, 'childBuffers');
10374
10661
  var index = siblings.indexOf(this);
10375
- siblings.insertAt(index + 1, buffer);
10662
+ siblings.splice(index + 1, 0, buffer);
10376
10663
  });
10377
10664
  },
10378
10665
 
@@ -10482,10 +10769,15 @@ Ember.EventDispatcher = Ember.Object.extend(
10482
10769
  The root DOM element to which event listeners should be attached. Event
10483
10770
  listeners will be attached to the document unless this is overridden.
10484
10771
 
10772
+ Can be specified as a DOMElement or a selector string.
10773
+
10774
+ The default body is a string since this may be evaluated before document.body
10775
+ exists in the DOM.
10776
+
10485
10777
  @type DOMElement
10486
- @default document
10778
+ @default 'body'
10487
10779
  */
10488
- rootElement: document,
10780
+ rootElement: 'body',
10489
10781
 
10490
10782
  /**
10491
10783
  @private
@@ -10536,6 +10828,8 @@ Ember.EventDispatcher = Ember.Object.extend(
10536
10828
 
10537
10829
  rootElement.addClass('ember-application');
10538
10830
 
10831
+ ember_assert('Unable to add "ember-application" class to rootElement. Make sure you the body or an element in the body.', rootElement.is('.ember-application'));
10832
+
10539
10833
  for (event in events) {
10540
10834
  if (events.hasOwnProperty(event)) {
10541
10835
  this.setupHandler(rootElement, event, events[event]);
@@ -10616,17 +10910,9 @@ Ember.EventDispatcher = Ember.Object.extend(
10616
10910
 
10617
10911
  /** @private */
10618
10912
  _bubbleEvent: function(view, evt, eventName) {
10619
- var result = true, handler,
10620
- self = this;
10621
-
10622
- Ember.run(function() {
10623
- handler = view[eventName];
10624
- if (Ember.typeOf(handler) === 'function') {
10625
- result = handler.call(view, evt);
10626
- }
10627
- });
10628
-
10629
- return result;
10913
+ return Ember.run(function() {
10914
+ return view.handleEvent(eventName, evt);
10915
+ });
10630
10916
  },
10631
10917
 
10632
10918
  /** @private */
@@ -10680,10 +10966,14 @@ Ember.Application = Ember.Namespace.extend(
10680
10966
  /** @scope Ember.Application.prototype */{
10681
10967
 
10682
10968
  /**
10969
+ The root DOM element of the Application.
10970
+
10971
+ Can be specified as DOMElement or a selector string.
10972
+
10683
10973
  @type DOMElement
10684
- @default document
10974
+ @default 'body'
10685
10975
  */
10686
- rootElement: document,
10976
+ rootElement: 'body',
10687
10977
 
10688
10978
  /**
10689
10979
  @type Ember.EventDispatcher
@@ -10709,21 +10999,35 @@ Ember.Application = Ember.Namespace.extend(
10709
10999
 
10710
11000
  set(this, 'eventDispatcher', eventDispatcher);
10711
11001
 
10712
- var self = this;
10713
- Ember.$(document).ready(function() {
10714
- self.ready();
10715
- });
11002
+ // jQuery 1.7 doesn't call the ready callback if already ready
11003
+ if (Ember.$.isReady) {
11004
+ this.didBecomeReady();
11005
+ } else {
11006
+ var self = this;
11007
+ Ember.$(document).ready(function() {
11008
+ self.didBecomeReady();
11009
+ });
11010
+ }
10716
11011
 
10717
11012
  this._super();
10718
11013
  },
10719
11014
 
10720
- ready: function() {
11015
+ /** @private */
11016
+ didBecomeReady: function() {
10721
11017
  var eventDispatcher = get(this, 'eventDispatcher'),
10722
11018
  customEvents = get(this, 'customEvents');
10723
11019
 
10724
11020
  eventDispatcher.setup(customEvents);
11021
+
11022
+ this.ready();
10725
11023
  },
10726
11024
 
11025
+ /**
11026
+ Called when the Application has become ready.
11027
+ The call will be delayed until the DOM has become ready.
11028
+ */
11029
+ ready: Ember.K,
11030
+
10727
11031
  /** @private */
10728
11032
  destroy: function() {
10729
11033
  get(this, 'eventDispatcher').destroy();
@@ -10772,6 +11076,7 @@ queues.splice(jQuery.inArray('actions', queues)+1, 0, 'render');
10772
11076
  /*globals ember_assert */
10773
11077
  var get = Ember.get, set = Ember.set, addObserver = Ember.addObserver;
10774
11078
  var getPath = Ember.getPath, meta = Ember.meta, fmt = Ember.String.fmt;
11079
+ var a_slice = Array.prototype.slice;
10775
11080
 
10776
11081
  var childViewsProperty = Ember.computed(function() {
10777
11082
  var childViews = get(this, '_childViews');
@@ -10910,13 +11215,19 @@ Ember.View = Ember.Object.extend(
10910
11215
  }
10911
11216
  }).property('_parentView'),
10912
11217
 
11218
+ // return the current view, not including virtual views
11219
+ concreteView: Ember.computed(function() {
11220
+ if (!this.isVirtual) { return this; }
11221
+ else { return get(this, 'parentView'); }
11222
+ }).property('_parentView'),
11223
+
10913
11224
  /**
10914
11225
  If false, the view will appear hidden in DOM.
10915
11226
 
10916
11227
  @type Boolean
10917
- @default true
11228
+ @default null
10918
11229
  */
10919
- isVisible: true,
11230
+ isVisible: null,
10920
11231
 
10921
11232
  /**
10922
11233
  Array of child views. You should never edit this array directly.
@@ -11063,7 +11374,7 @@ Ember.View = Ember.Object.extend(
11063
11374
  var fn = state[name];
11064
11375
 
11065
11376
  if (fn) {
11066
- var args = Array.prototype.slice.call(arguments, 1);
11377
+ var args = a_slice.call(arguments, 1);
11067
11378
  args.unshift(this);
11068
11379
 
11069
11380
  return fn.apply(this, args);
@@ -11192,38 +11503,22 @@ Ember.View = Ember.Object.extend(
11192
11503
 
11193
11504
  if (!attributeBindings) { return; }
11194
11505
 
11195
- attributeBindings.forEach(function(attribute) {
11506
+ attributeBindings.forEach(function(attributeName) {
11196
11507
  // Create an observer to add/remove/change the attribute if the
11197
11508
  // JavaScript property changes.
11198
11509
  var observer = function() {
11199
11510
  elem = this.$();
11200
- var currentValue = elem.attr(attribute);
11201
- attributeValue = get(this, attribute);
11202
-
11203
- type = typeof attributeValue;
11511
+ attributeValue = get(this, attributeName);
11204
11512
 
11205
- if ((type === 'string' || (type === 'number' && !isNaN(attributeValue))) && attributeValue !== currentValue) {
11206
- elem.attr(attribute, attributeValue);
11207
- } else if (attributeValue && type === 'boolean') {
11208
- elem.attr(attribute, attribute);
11209
- } else if (!attributeValue) {
11210
- elem.removeAttr(attribute);
11211
- }
11513
+ Ember.View.applyAttributeBindings(elem, attributeName, attributeValue)
11212
11514
  };
11213
11515
 
11214
- addObserver(this, attribute, observer);
11516
+ addObserver(this, attributeName, observer);
11215
11517
 
11216
11518
  // Determine the current value and add it to the render buffer
11217
11519
  // if necessary.
11218
- attributeValue = get(this, attribute);
11219
- type = typeof attributeValue;
11220
-
11221
- if (type === 'string' || type === 'number') {
11222
- buffer.attr(attribute, attributeValue);
11223
- } else if (attributeValue && type === 'boolean') {
11224
- // Apply boolean attributes in the form attribute="attribute"
11225
- buffer.attr(attribute, attribute);
11226
- }
11520
+ attributeValue = get(this, attributeName);
11521
+ Ember.View.applyAttributeBindings(buffer, attributeName, attributeValue);
11227
11522
  }, this);
11228
11523
  },
11229
11524
 
@@ -11347,6 +11642,9 @@ Ember.View = Ember.Object.extend(
11347
11642
  // Schedule the DOM element to be created and appended to the given
11348
11643
  // element after bindings have synchronized.
11349
11644
  this._insertElementLater(function() {
11645
+ if (get(this, 'isVisible') === null) {
11646
+ set(this, 'isVisible', true);
11647
+ }
11350
11648
  this.$().appendTo(target);
11351
11649
  });
11352
11650
 
@@ -11467,7 +11765,7 @@ Ember.View = Ember.Object.extend(
11467
11765
  */
11468
11766
  renderBuffer: function(tagName) {
11469
11767
  tagName = tagName || get(this, 'tagName');
11470
- if (tagName == null) { tagName = tagName || 'div'; }
11768
+ if (tagName == null) { tagName = 'div'; }
11471
11769
 
11472
11770
  return Ember.RenderBuffer(tagName);
11473
11771
  },
@@ -11656,7 +11954,7 @@ Ember.View = Ember.Object.extend(
11656
11954
  // insert a new buffer after the "parent buffer").
11657
11955
  if (parentBuffer) {
11658
11956
  var tagName = get(this, 'tagName');
11659
- tagName = tagName == null ? 'div' : tagName;
11957
+ if (tagName == null) { tagName = 'div'; }
11660
11958
 
11661
11959
  buffer = parentBuffer[bufferOperation](tagName);
11662
11960
  } else {
@@ -11705,7 +12003,7 @@ Ember.View = Ember.Object.extend(
11705
12003
  buffer.attr('role', role);
11706
12004
  }
11707
12005
 
11708
- if (!get(this, 'isVisible')) {
12006
+ if (get(this, 'isVisible') === false) {
11709
12007
  buffer.style('display', 'none');
11710
12008
  }
11711
12009
  },
@@ -11845,6 +12143,14 @@ Ember.View = Ember.Object.extend(
11845
12143
  set(this, 'domManager', this.domManagerClass.create({ view: this }));
11846
12144
 
11847
12145
  meta(this)["Ember.View"] = {};
12146
+
12147
+ var viewController = get(this, 'viewController');
12148
+ if (viewController) {
12149
+ viewController = Ember.getPath(viewController);
12150
+ if (viewController) {
12151
+ set(viewController, 'view', this);
12152
+ }
12153
+ }
11848
12154
  },
11849
12155
 
11850
12156
  appendChild: function(view, options) {
@@ -11959,7 +12265,10 @@ Ember.View = Ember.Object.extend(
11959
12265
  view = view.create(attrs || {}, { _parentView: this });
11960
12266
 
11961
12267
  var viewName = attrs && attrs.viewName || view.viewName;
11962
- if (viewName) { set(this, viewName, view); }
12268
+
12269
+ // don't set the property on a virtual view, as they are invisible to
12270
+ // consumers of the view API
12271
+ if (viewName) { set(get(this, 'concreteView'), viewName, view); }
11963
12272
  } else {
11964
12273
  ember_assert('must pass instance of View', view instanceof Ember.View);
11965
12274
  set(view, '_parentView', this);
@@ -11967,6 +12276,9 @@ Ember.View = Ember.Object.extend(
11967
12276
  return view;
11968
12277
  },
11969
12278
 
12279
+ becameVisible: Ember.K,
12280
+ becameHidden: Ember.K,
12281
+
11970
12282
  /**
11971
12283
  @private
11972
12284
 
@@ -11974,9 +12286,54 @@ Ember.View = Ember.Object.extend(
11974
12286
  element of the actual DOM element.
11975
12287
  */
11976
12288
  _isVisibleDidChange: Ember.observer(function() {
11977
- this.$().toggle(get(this, 'isVisible'));
12289
+ var isVisible = get(this, 'isVisible');
12290
+
12291
+ this.$().toggle(isVisible);
12292
+
12293
+ if (this._isAncestorHidden()) { return; }
12294
+
12295
+ if (isVisible) {
12296
+ this._notifyBecameVisible();
12297
+ } else {
12298
+ this._notifyBecameHidden();
12299
+ }
11978
12300
  }, 'isVisible'),
11979
12301
 
12302
+ _notifyBecameVisible: function() {
12303
+ this.becameVisible();
12304
+
12305
+ this.forEachChildView(function(view) {
12306
+ var isVisible = get(view, 'isVisible');
12307
+
12308
+ if (isVisible || isVisible === null) {
12309
+ view._notifyBecameVisible();
12310
+ }
12311
+ });
12312
+ },
12313
+
12314
+ _notifyBecameHidden: function() {
12315
+ this.becameHidden();
12316
+ this.forEachChildView(function(view) {
12317
+ var isVisible = get(view, 'isVisible');
12318
+
12319
+ if (isVisible || isVisible === null) {
12320
+ view._notifyBecameHidden();
12321
+ }
12322
+ });
12323
+ },
12324
+
12325
+ _isAncestorHidden: function() {
12326
+ var parent = get(this, 'parentView');
12327
+
12328
+ while (parent) {
12329
+ if (get(parent, 'isVisible') === false) { return true; }
12330
+
12331
+ parent = get(parent, 'parentView');
12332
+ }
12333
+
12334
+ return false;
12335
+ },
12336
+
11980
12337
  clearBuffer: function() {
11981
12338
  this.invokeRecursively(function(view) {
11982
12339
  meta(view)['Ember.View'].buffer = null;
@@ -11991,6 +12348,19 @@ Ember.View = Ember.Object.extend(
11991
12348
  view.transitionTo(state);
11992
12349
  });
11993
12350
  }
12351
+ },
12352
+
12353
+ // .......................................................
12354
+ // EVENT HANDLING
12355
+ //
12356
+
12357
+ /**
12358
+ @private
12359
+
12360
+ Handle events from `Ember.EventDispatcher`
12361
+ */
12362
+ handleEvent: function(eventName, evt) {
12363
+ return this.invokeForState('handleEvent', eventName, evt);
11994
12364
  }
11995
12365
 
11996
12366
  });
@@ -12075,6 +12445,20 @@ Ember.View.views = {};
12075
12445
  // method.
12076
12446
  Ember.View.childViewsProperty = childViewsProperty;
12077
12447
 
12448
+ Ember.View.applyAttributeBindings = function(elem, name, value) {
12449
+ var type = typeof value;
12450
+ var currentValue = elem.attr(name);
12451
+
12452
+ // if this changes, also change the logic in ember-handlebars/lib/helpers/binding.js
12453
+ if ((type === 'string' || (type === 'number' && !isNaN(value))) && value !== currentValue) {
12454
+ elem.attr(name, value);
12455
+ } else if (value && type === 'boolean') {
12456
+ elem.attr(name, name);
12457
+ } else if (!value) {
12458
+ elem.removeAttr(name);
12459
+ }
12460
+ };
12461
+
12078
12462
  })({});
12079
12463
 
12080
12464
 
@@ -12100,6 +12484,11 @@ Ember.View.states = {
12100
12484
 
12101
12485
  getElement: function() {
12102
12486
  return null;
12487
+ },
12488
+
12489
+ // Handle events from `Ember.EventDispatcher`
12490
+ handleEvent: function() {
12491
+ return true; // continue event propagation
12103
12492
  }
12104
12493
  }
12105
12494
  };
@@ -12296,6 +12685,16 @@ Ember.View.states.hasElement = {
12296
12685
 
12297
12686
  get(view, 'domManager').remove();
12298
12687
  return view;
12688
+ },
12689
+
12690
+ // Handle events from `Ember.EventDispatcher`
12691
+ handleEvent: function(view, eventName, evt) {
12692
+ var handler = view[eventName];
12693
+ if (Ember.typeOf(handler) === 'function') {
12694
+ return handler.call(view, evt);
12695
+ } else {
12696
+ return true; // continue event propagation
12697
+ }
12299
12698
  }
12300
12699
  };
12301
12700
 
@@ -12429,7 +12828,7 @@ Ember.ContainerView = Ember.View.extend({
12429
12828
  },
12430
12829
 
12431
12830
  /**
12432
- When the container view is destroyer, tear down the child views
12831
+ When the container view is destroyed, tear down the child views
12433
12832
  array observer.
12434
12833
 
12435
12834
  @private
@@ -12456,6 +12855,11 @@ Ember.ContainerView = Ember.View.extend({
12456
12855
  @param {Number} removed the number of child views removed
12457
12856
  **/
12458
12857
  childViewsWillChange: function(views, start, removed) {
12858
+ if (removed === 0) { return; }
12859
+
12860
+ var changedViews = views.slice(start, removed);
12861
+ this.setParentView(changedViews, null);
12862
+
12459
12863
  this.invokeForState('childViewsWillChange', views, start, removed);
12460
12864
  },
12461
12865
 
@@ -12480,10 +12884,19 @@ Ember.ContainerView = Ember.View.extend({
12480
12884
  // No new child views were added; bail out.
12481
12885
  if (added === 0) return;
12482
12886
 
12887
+ var changedViews = views.slice(start, added);
12888
+ this.setParentView(changedViews, this);
12889
+
12483
12890
  // Let the current state handle the changes
12484
12891
  this.invokeForState('childViewsDidChange', views, start, added);
12485
12892
  },
12486
12893
 
12894
+ setParentView: function(views, parentView) {
12895
+ views.forEach(function(view) {
12896
+ set(view, '_parentView', parentView);
12897
+ });
12898
+ },
12899
+
12487
12900
  /**
12488
12901
  Schedules a child view to be inserted into the DOM after bindings have
12489
12902
  finished syncing for this run loop.
@@ -12693,6 +13106,10 @@ Ember.CollectionView = Ember.ContainerView.extend(
12693
13106
  childViews = get(this, 'childViews'),
12694
13107
  addedViews = [], view, item, idx, len, itemTagName;
12695
13108
 
13109
+ if ('string' === typeof itemViewClass) {
13110
+ itemViewClass = Ember.getPath(itemViewClass);
13111
+ }
13112
+
12696
13113
  ember_assert(fmt("itemViewClass must be a subclass of Ember.View, not %@", [itemViewClass]), Ember.View.detect(itemViewClass));
12697
13114
 
12698
13115
  len = content ? get(content, 'length') : 0;
@@ -12772,7 +13189,8 @@ Ember.CollectionView.CONTAINER_MAP = {
12772
13189
  // Portions ©2008-2011 Apple Inc. All rights reserved.
12773
13190
  // License: Licensed under MIT license (see license.js)
12774
13191
  // ==========================================================================
12775
- Ember.$ = jQuery;
13192
+ ember_assert("Ember requires jQuery 1.6 or 1.7", window.jQuery && jQuery().jquery.match(/^1\.[67](.\d+)?$/));
13193
+ Ember.$ = window.jQuery;
12776
13194
  })({});
12777
13195
 
12778
13196
  (function(exports) {
@@ -12784,14 +13202,50 @@ Ember.State = Ember.Object.extend({
12784
13202
  start: null,
12785
13203
 
12786
13204
  init: function() {
12787
- Ember.keys(this).forEach(function(name) {
12788
- var value = this[name];
13205
+ var states = get(this, 'states'), foundStates;
13206
+
13207
+ // As a convenience, loop over the properties
13208
+ // of this state and look for any that are other
13209
+ // Ember.State instances or classes, and move them
13210
+ // to the `states` hash. This avoids having to
13211
+ // create an explicit separate hash.
13212
+
13213
+ if (!states) {
13214
+ states = {};
13215
+ for (var name in this) {
13216
+ if (name === "constructor") { continue; }
13217
+ value = this.setupChild(name, this[name]);
12789
13218
 
12790
- if (value && value.isState) {
12791
- set(value, 'parentState', this);
12792
- set(value, 'name', (get(this, 'name') || '') + '.' + name);
13219
+ if (value) {
13220
+ foundStates = true;
13221
+ states[name] = value;
13222
+ }
12793
13223
  }
12794
- }, this);
13224
+
13225
+ if (foundStates) { set(this, 'states', states); }
13226
+ } else {
13227
+ for (var name in states) {
13228
+ this.setupChild(name, states[name]);
13229
+ }
13230
+ }
13231
+
13232
+ set(this, 'routes', {});
13233
+ },
13234
+
13235
+ setupChild: function(name, value) {
13236
+ if (!value) { return false; }
13237
+
13238
+ if (Ember.State.detect(value)) {
13239
+ value = value.create();
13240
+ }
13241
+
13242
+ if (value.isState) {
13243
+ set(value, 'parentState', this);
13244
+ set(value, 'name', (get(this, 'name') || '') + '.' + name);
13245
+ return value;
13246
+ }
13247
+
13248
+ return false;
12795
13249
  },
12796
13250
 
12797
13251
  enter: Ember.K,
@@ -12805,29 +13259,20 @@ Ember.State = Ember.Object.extend({
12805
13259
  var get = Ember.get, set = Ember.set, getPath = Ember.getPath, fmt = Ember.String.fmt;
12806
13260
  Ember.LOG_STATE_TRANSITIONS = false;
12807
13261
 
12808
- Ember.StateManager = Ember.State.extend({
13262
+ /**
13263
+ @class
13264
+ */
13265
+ Ember.StateManager = Ember.State.extend(
13266
+ /** @scope Ember.State.prototype */ {
13267
+
12809
13268
  /**
12810
- When creating a new storyboard, look for a default state to transition
13269
+ When creating a new statemanager, look for a default state to transition
12811
13270
  into. This state can either be named `start`, or can be specified using the
12812
13271
  `initialState` property.
12813
13272
  */
12814
13273
  init: function() {
12815
13274
  this._super();
12816
13275
 
12817
- var states = get(this, 'states');
12818
- if (!states) {
12819
- states = {};
12820
- Ember.keys(this).forEach(function(name) {
12821
- var value = get(this, name);
12822
-
12823
- if (value && value.isState) {
12824
- states[name] = value;
12825
- }
12826
- }, this);
12827
-
12828
- set(this, 'states', states);
12829
- }
12830
-
12831
13276
  var initialState = get(this, 'initialState');
12832
13277
 
12833
13278
  if (!initialState && get(this, 'start')) {
@@ -12842,11 +13287,13 @@ Ember.StateManager = Ember.State.extend({
12842
13287
  currentState: null,
12843
13288
 
12844
13289
  /**
13290
+ @property
13291
+
12845
13292
  If the current state is a view state or the descendent of a view state,
12846
13293
  this property will be the view associated with it. If there is no
12847
13294
  view state active in this state manager, this value will be null.
12848
13295
  */
12849
- currentView: SC.computed(function() {
13296
+ currentView: Ember.computed(function() {
12850
13297
  var currentState = get(this, 'currentState'),
12851
13298
  view;
12852
13299
 
@@ -12872,7 +13319,7 @@ Ember.StateManager = Ember.State.extend({
12872
13319
  var action = currentState[event];
12873
13320
 
12874
13321
  if (action) {
12875
- if (log) { console.log(fmt("STORYBOARDS: Sending event '%@' to state %@.", [event, currentState.name])); }
13322
+ if (log) { console.log(fmt("STATEMANAGER: Sending event '%@' to state %@.", [event, currentState.name])); }
12876
13323
  action.call(currentState, this, context);
12877
13324
  } else {
12878
13325
  var parentState = get(currentState, 'parentState');
@@ -12880,28 +13327,72 @@ Ember.StateManager = Ember.State.extend({
12880
13327
  }
12881
13328
  },
12882
13329
 
13330
+ findStatesByRoute: function(state, route) {
13331
+ if (!route || route === "") { return undefined; }
13332
+ var r = route.split('.'), ret = [];
13333
+
13334
+ for (var i=0, len = r.length; i < len; i += 1) {
13335
+ var states = get(state, 'states') ;
13336
+
13337
+ if (!states) { return undefined; }
13338
+
13339
+ var s = get(states, r[i]);
13340
+ if (s) { state = s; ret.push(s); }
13341
+ else { return undefined; }
13342
+ }
13343
+
13344
+ return ret;
13345
+ },
13346
+
12883
13347
  goToState: function(name) {
13348
+ if (Ember.empty(name)) { return; }
13349
+
12884
13350
  var currentState = get(this, 'currentState') || this, state, newState;
12885
13351
 
12886
- var exitStates = Ember.A();
13352
+ var exitStates = [], enterStates;
12887
13353
 
12888
- newState = getPath(currentState, name);
12889
13354
  state = currentState;
12890
13355
 
12891
- if (!newState) {
13356
+ if (state.routes[name]) {
13357
+ // cache hit
13358
+ exitStates = state.routes[name].exitStates;
13359
+ enterStates = state.routes[name].enterStates;
13360
+ state = state.routes[name].futureState;
13361
+ } else {
13362
+ // cache miss
13363
+
13364
+ newState = this.findStatesByRoute(currentState, name);
13365
+
12892
13366
  while (state && !newState) {
12893
- exitStates[Ember.guidFor(state)] = state;
12894
- exitStates.push(state);
13367
+ exitStates.unshift(state);
12895
13368
 
12896
13369
  state = get(state, 'parentState');
12897
13370
  if (!state) {
12898
- state = get(this, 'states');
13371
+ newState = this.findStatesByRoute(this, name);
13372
+ if (!newState) { return; }
13373
+ }
13374
+ newState = this.findStatesByRoute(state, name);
13375
+ }
13376
+
13377
+ enterStates = newState.slice(0), exitStates = exitStates.slice(0);
13378
+
13379
+ if (enterStates.length > 0) {
13380
+ state = enterStates[enterStates.length - 1];
13381
+
13382
+ while (enterStates.length > 0 && enterStates[0] === exitStates[0]) {
13383
+ enterStates.shift();
13384
+ exitStates.shift();
12899
13385
  }
12900
- newState = getPath(state, name);
12901
13386
  }
13387
+
13388
+ currentState.routes[name] = {
13389
+ exitStates: exitStates,
13390
+ enterStates: enterStates,
13391
+ futureState: state
13392
+ };
12902
13393
  }
12903
13394
 
12904
- this.enterState(state, name, exitStates);
13395
+ this.enterState(exitStates, enterStates, state);
12905
13396
  },
12906
13397
 
12907
13398
  getState: function(name) {
@@ -12938,37 +13429,28 @@ Ember.StateManager = Ember.State.extend({
12938
13429
  if (!async) { transition.resume(); }
12939
13430
  },
12940
13431
 
12941
- enterState: function(parent, name, exitStates) {
13432
+ enterState: function(exitStates, enterStates, state) {
12942
13433
  var log = Ember.LOG_STATE_TRANSITIONS;
12943
13434
 
12944
- var parts = name.split("."), state = parent, enterStates = Ember.A();
12945
-
12946
- parts.forEach(function(name) {
12947
- state = state[name];
12948
-
12949
- var guid = Ember.guidFor(state);
12950
-
12951
- if (guid in exitStates) {
12952
- exitStates.removeObject(state);
12953
- delete exitStates[guid];
12954
- } else {
12955
- enterStates.push(state);
12956
- }
12957
- });
12958
-
12959
13435
  var stateManager = this;
12960
13436
 
12961
13437
  this.asyncEach(exitStates, function(state, transition) {
12962
13438
  state.exit(stateManager, transition);
12963
13439
  }, function() {
12964
13440
  this.asyncEach(enterStates, function(state, transition) {
12965
- if (log) { console.log("STORYBOARDS: Entering " + state.name); }
13441
+ if (log) { console.log("STATEMANAGER: Entering " + state.name); }
12966
13442
  state.enter(stateManager, transition);
12967
13443
  }, function() {
12968
- var startState = state, enteredState;
13444
+ var startState = state, enteredState, initialSubstate;
13445
+
13446
+ initialSubstate = get(startState, 'initialSubstate');
13447
+
13448
+ if (!initialSubstate) {
13449
+ initialSubstate = 'start';
13450
+ }
12969
13451
 
12970
13452
  // right now, start states cannot be entered asynchronously
12971
- while (startState = get(startState, 'start')) {
13453
+ while (startState = get(startState, initialSubstate)) {
12972
13454
  enteredState = startState;
12973
13455
  startState.enter(stateManager);
12974
13456
  }
@@ -12989,10 +13471,25 @@ Ember.ViewState = Ember.State.extend({
12989
13471
  isViewState: true,
12990
13472
 
12991
13473
  enter: function(stateManager) {
12992
- var view = get(this, 'view');
13474
+ var view = get(this, 'view'), root, childViews;
12993
13475
 
12994
13476
  if (view) {
12995
- view.appendTo(stateManager.get('rootElement') || 'body');
13477
+ if (Ember.View.detect(view)) {
13478
+ view = view.create();
13479
+ set(this, 'view', view);
13480
+ }
13481
+
13482
+ ember_assert('view must be an Ember.View', view instanceof Ember.View);
13483
+
13484
+ root = stateManager.get('rootView');
13485
+
13486
+ if (root) {
13487
+ childViews = get(root, 'childViews');
13488
+ childViews.pushObject(view);
13489
+ } else {
13490
+ root = stateManager.get('rootElement') || 'body';
13491
+ view.appendTo(root);
13492
+ }
12996
13493
  }
12997
13494
  },
12998
13495
 
@@ -13000,18 +13497,27 @@ Ember.ViewState = Ember.State.extend({
13000
13497
  var view = get(this, 'view');
13001
13498
 
13002
13499
  if (view) {
13003
- view.remove();
13500
+ // If the view has a parent view, then it is
13501
+ // part of a view hierarchy and should be removed
13502
+ // from its parent.
13503
+ if (get(view, 'parentView')) {
13504
+ view.removeFromParent();
13505
+ } else {
13506
+
13507
+ // Otherwise, the view is a "root view" and
13508
+ // was appended directly to the DOM.
13509
+ view.remove();
13510
+ }
13004
13511
  }
13005
13512
  }
13006
13513
  });
13007
13514
 
13008
-
13009
13515
  })({});
13010
13516
 
13011
13517
 
13012
13518
  (function(exports) {
13013
13519
  // ==========================================================================
13014
- // Project: Ember Storyboards
13520
+ // Project: Ember Statecharts
13015
13521
  // Copyright: ©2011 Living Social Inc. and contributors.
13016
13522
  // License: Licensed under MIT license (see license.js)
13017
13523
  // ==========================================================================
@@ -13437,6 +13943,17 @@ Ember.ViewState = Ember.State.extend({
13437
13943
  // License: Licensed under MIT license (see license.js)
13438
13944
  // ==========================================================================
13439
13945
  /*globals Handlebars */
13946
+ /**
13947
+ @namespace
13948
+ @name Handlebars
13949
+ @private
13950
+ */
13951
+
13952
+ /**
13953
+ @namespace
13954
+ @name Handlebars.helpers
13955
+ @description Helpers for Handlebars templates
13956
+ */
13440
13957
 
13441
13958
  /**
13442
13959
  @class
@@ -13462,12 +13979,6 @@ Ember.ViewState = Ember.State.extend({
13462
13979
  Note that you won't usually need to use Ember.Handlebars yourself. Instead, use
13463
13980
  Ember.View, which takes care of integration into the view layer for you.
13464
13981
  */
13465
- /**
13466
- @namespace
13467
-
13468
- Ember Handlebars is an extension to Handlebars that makes the built-in
13469
- Handlebars helpers and {{mustaches}} binding-aware.
13470
- */
13471
13982
  Ember.Handlebars = Ember.create(Handlebars);
13472
13983
 
13473
13984
  Ember.Handlebars.helpers = Ember.create(Handlebars.helpers);
@@ -13511,7 +14022,7 @@ Ember.Handlebars.Compiler.prototype.mustache = function(mustache) {
13511
14022
  if (mustache.params.length || mustache.hash) {
13512
14023
  return Handlebars.Compiler.prototype.mustache.call(this, mustache);
13513
14024
  } else {
13514
- var id = new Handlebars.AST.IdNode(['bind']);
14025
+ var id = new Handlebars.AST.IdNode(['_triageMustache']);
13515
14026
 
13516
14027
  // Update the mustache node to include a hash value indicating whether the original node
13517
14028
  // was escaped. This will allow us to properly escape values when the underlying value
@@ -13525,6 +14036,19 @@ Ember.Handlebars.Compiler.prototype.mustache = function(mustache) {
13525
14036
  }
13526
14037
  };
13527
14038
 
14039
+ /**
14040
+ Used for precompilation of Ember Handlebars templates. This will not be used during normal
14041
+ app execution.
14042
+
14043
+ @param {String} string The template to precompile
14044
+ */
14045
+ Ember.Handlebars.precompile = function(string) {
14046
+ var ast = Handlebars.parse(string);
14047
+ var options = { data: true, stringParams: true };
14048
+ var environment = new Ember.Handlebars.Compiler().compile(ast, options);
14049
+ return new Ember.Handlebars.JavaScriptCompiler().compile(environment, options, undefined, true);
14050
+ };
14051
+
13528
14052
  /**
13529
14053
  The entry point for Ember Handlebars. This replaces the default Handlebars.compile and turns on
13530
14054
  template-local data and String parameters.
@@ -13540,6 +14064,21 @@ Ember.Handlebars.compile = function(string) {
13540
14064
  return Handlebars.template(templateSpec);
13541
14065
  };
13542
14066
 
14067
+ /**
14068
+ Lookup both on root and on window
14069
+
14070
+ @param {Object} root The object to look up the property on
14071
+ @param {String} path The path to be lookedup
14072
+ */
14073
+ Ember.Handlebars.getPath = function(root, path) {
14074
+ // TODO: Remove this `false` when the `getPath` globals support is removed
14075
+ var value = Ember.getPath(root, path, false);
14076
+ if (value === undefined && root !== window && Ember.isGlobalPath(path)) {
14077
+ value = Ember.getPath(window, path);
14078
+ }
14079
+ return value;
14080
+ };
14081
+
13543
14082
  /**
13544
14083
  Registers a helper in Handlebars that will be called if no property with the
13545
14084
  given name can be found on the current context object, and no helper with
@@ -13609,11 +14148,11 @@ Ember.Checkbox = Ember.View.extend({
13609
14148
  // Copyright: ©2011 Strobe Inc. and contributors.
13610
14149
  // License: Licensed under MIT license (see license.js)
13611
14150
  // ==========================================================================
13612
- /** @class */
13613
-
13614
14151
  var get = Ember.get, set = Ember.set;
13615
14152
 
13616
- Ember.TextSupport = Ember.Mixin.create({
14153
+ /** @class */
14154
+ Ember.TextSupport = Ember.Mixin.create(
14155
+ /** @scope Ember.TextSupport.prototype */ {
13617
14156
 
13618
14157
  value: "",
13619
14158
 
@@ -13626,17 +14165,14 @@ Ember.TextSupport = Ember.Mixin.create({
13626
14165
 
13627
14166
  focusOut: function(event) {
13628
14167
  this._elementValueDidChange();
13629
- return false;
13630
14168
  },
13631
14169
 
13632
14170
  change: function(event) {
13633
14171
  this._elementValueDidChange();
13634
- return false;
13635
14172
  },
13636
14173
 
13637
14174
  keyUp: function(event) {
13638
14175
  this.interpretKeyEvents(event);
13639
- return false;
13640
14176
  },
13641
14177
 
13642
14178
  /**
@@ -13651,7 +14187,7 @@ Ember.TextSupport = Ember.Mixin.create({
13651
14187
  },
13652
14188
 
13653
14189
  _elementValueDidChange: function() {
13654
- set(this, 'value', this.$().val() || '');
14190
+ set(this, 'value', this.$().val());
13655
14191
  }
13656
14192
 
13657
14193
  });
@@ -13670,10 +14206,12 @@ Ember.TextSupport.KEY_EVENTS = {
13670
14206
  // Copyright: ©2011 Strobe Inc. and contributors.
13671
14207
  // License: Licensed under MIT license (see license.js)
13672
14208
  // ==========================================================================
13673
- /** @class */
13674
-
13675
14209
  var get = Ember.get, set = Ember.set;
13676
14210
 
14211
+ /**
14212
+ @class
14213
+ @extends Ember.TextSupport
14214
+ */
13677
14215
  Ember.TextField = Ember.View.extend(Ember.TextSupport,
13678
14216
  /** @scope Ember.TextField.prototype */ {
13679
14217
 
@@ -13681,14 +14219,7 @@ Ember.TextField = Ember.View.extend(Ember.TextSupport,
13681
14219
 
13682
14220
  tagName: "input",
13683
14221
  attributeBindings: ['type', 'value'],
13684
- type: "text",
13685
-
13686
- /**
13687
- @private
13688
- */
13689
- _updateElementValue: function() {
13690
- this.$().val(get(this, 'value'));
13691
- }
14222
+ type: "text"
13692
14223
 
13693
14224
  });
13694
14225
 
@@ -13708,11 +14239,26 @@ Ember.Button = Ember.View.extend(Ember.TargetActionSupport, {
13708
14239
  classNameBindings: ['isActive'],
13709
14240
 
13710
14241
  tagName: 'button',
13711
- attributeBindings: ['type', 'disabled'],
13712
- type: 'button',
13713
- disabled: false,
14242
+
13714
14243
  propagateEvents: false,
13715
14244
 
14245
+ attributeBindings: ['type', 'disabled', 'href'],
14246
+
14247
+ // Defaults to 'button' if tagName is 'input' or 'button'
14248
+ type: Ember.computed(function(key, value) {
14249
+ var tagName = this.get('tagName');
14250
+ if (value !== undefined) { this._type = value; }
14251
+ if (this._type !== undefined) { return this._type; }
14252
+ if (tagName === 'input' || tagName === 'button') { return 'button'; }
14253
+ }).property('tagName').cacheable(),
14254
+
14255
+ disabled: false,
14256
+
14257
+ // Allow 'a' tags to act like buttons
14258
+ href: Ember.computed(function() {
14259
+ return this.get('tagName') === 'a' ? '#' : null;
14260
+ }).property('tagName').cacheable(),
14261
+
13716
14262
  mouseDown: function() {
13717
14263
  if (!get(this, 'disabled')) {
13718
14264
  set(this, 'isActive', true);
@@ -13738,7 +14284,6 @@ Ember.Button = Ember.View.extend(Ember.TargetActionSupport, {
13738
14284
 
13739
14285
  mouseUp: function(event) {
13740
14286
  if (get(this, 'isActive')) {
13741
-
13742
14287
  // Actually invoke the button's target and action.
13743
14288
  // This method comes from the Ember.TargetActionSupport mixin.
13744
14289
  this.triggerAction();
@@ -13750,16 +14295,30 @@ Ember.Button = Ember.View.extend(Ember.TargetActionSupport, {
13750
14295
  return get(this, 'propagateEvents');
13751
14296
  },
13752
14297
 
14298
+ keyDown: function(event) {
14299
+ // Handle space or enter
14300
+ if (event.keyCode === 13 || event.keyCode === 32) {
14301
+ this.mouseDown();
14302
+ }
14303
+ },
14304
+
14305
+ keyUp: function(event) {
14306
+ // Handle space or enter
14307
+ if (event.keyCode === 13 || event.keyCode === 32) {
14308
+ this.mouseUp();
14309
+ }
14310
+ },
14311
+
13753
14312
  // TODO: Handle proper touch behavior. Including should make inactive when
13754
14313
  // finger moves more than 20x outside of the edge of the button (vs mouse
13755
14314
  // which goes inactive as soon as mouse goes out of edges.)
13756
14315
 
13757
14316
  touchStart: function(touch) {
13758
- this.mouseDown(touch);
14317
+ return this.mouseDown(touch);
13759
14318
  },
13760
14319
 
13761
14320
  touchEnd: function(touch) {
13762
- this.mouseUp(touch);
14321
+ return this.mouseUp(touch);
13763
14322
  }
13764
14323
  });
13765
14324
 
@@ -13772,11 +14331,14 @@ Ember.Button = Ember.View.extend(Ember.TargetActionSupport, {
13772
14331
  // Copyright: ©2011 Strobe Inc. and contributors.
13773
14332
  // License: Licensed under MIT license (see license.js)
13774
14333
  // ==========================================================================
13775
- /** @class */
13776
-
13777
14334
  var get = Ember.get, set = Ember.set;
13778
14335
 
13779
- Ember.TextArea = Ember.View.extend(Ember.TextSupport, {
14336
+ /**
14337
+ @class
14338
+ @extends Ember.TextSupport
14339
+ */
14340
+ Ember.TextArea = Ember.View.extend(Ember.TextSupport,
14341
+ /** @scope Ember.TextArea.prototype */ {
13780
14342
 
13781
14343
  classNames: ['ember-text-area'],
13782
14344
 
@@ -13808,11 +14370,11 @@ Ember.TabContainerView = Ember.View.extend();
13808
14370
  var get = Ember.get, getPath = Ember.getPath;
13809
14371
 
13810
14372
  Ember.TabPaneView = Ember.View.extend({
13811
- tabsContainer: SC.computed(function() {
14373
+ tabsContainer: Ember.computed(function() {
13812
14374
  return this.nearestInstanceOf(Ember.TabContainerView);
13813
14375
  }).property(),
13814
14376
 
13815
- isVisible: SC.computed(function() {
14377
+ isVisible: Ember.computed(function() {
13816
14378
  return get(this, 'viewName') === getPath(this, 'tabsContainer.currentView');
13817
14379
  }).property('tabsContainer.currentView')
13818
14380
  });
@@ -13824,7 +14386,7 @@ Ember.TabPaneView = Ember.View.extend({
13824
14386
  var get = Ember.get, setPath = Ember.setPath;
13825
14387
 
13826
14388
  Ember.TabView = Ember.View.extend({
13827
- tabsContainer: SC.computed(function() {
14389
+ tabsContainer: Ember.computed(function() {
13828
14390
  return this.nearestInstanceOf(Ember.TabContainerView);
13829
14391
  }).property(),
13830
14392
 
@@ -13840,6 +14402,93 @@ Ember.TabView = Ember.View.extend({
13840
14402
  })({});
13841
14403
 
13842
14404
 
14405
+ (function(exports) {
14406
+ var set = Ember.set, get = Ember.get, getPath = Ember.getPath;
14407
+
14408
+ Ember.Select = Ember.View.extend({
14409
+ tagName: 'select',
14410
+ template: Ember.Handlebars.compile(
14411
+ '{{#if prompt}}<option>{{prompt}}</option>{{/if}}' +
14412
+ '{{#each content}}{{view Ember.SelectOption contentBinding="this"}}{{/each}}'
14413
+ ),
14414
+
14415
+ content: null,
14416
+ selection: null,
14417
+ prompt: null,
14418
+
14419
+ optionLabelPath: 'content',
14420
+ optionValuePath: 'content',
14421
+
14422
+
14423
+ didInsertElement: function() {
14424
+ var selection = get(this, 'selection');
14425
+
14426
+ if (selection) { this.selectionDidChange(); }
14427
+
14428
+ this.change();
14429
+ },
14430
+
14431
+ change: function() {
14432
+ var selectedIndex = this.$()[0].selectedIndex,
14433
+ content = get(this, 'content'),
14434
+ prompt = get(this, 'prompt');
14435
+
14436
+ if (!content) { return; }
14437
+ if (prompt && selectedIndex === 0) { set(this, 'selection', null); return; }
14438
+
14439
+ if (prompt) { selectedIndex -= 1; }
14440
+ set(this, 'selection', content.objectAt(selectedIndex));
14441
+ },
14442
+
14443
+ selectionDidChange: Ember.observer(function() {
14444
+ var el = this.$()[0],
14445
+ content = get(this, 'content'),
14446
+ selection = get(this, 'selection'),
14447
+ selectionIndex = content.indexOf(selection),
14448
+ prompt = get(this, 'prompt');
14449
+
14450
+ if (prompt) { selectionIndex += 1; }
14451
+ if (el) { el.selectedIndex = selectionIndex; }
14452
+ }, 'selection')
14453
+ });
14454
+
14455
+ Ember.SelectOption = Ember.View.extend({
14456
+ tagName: 'option',
14457
+ template: Ember.Handlebars.compile("{{label}}"),
14458
+ attributeBindings: ['value'],
14459
+
14460
+ init: function() {
14461
+ this.labelPathDidChange();
14462
+ this.valuePathDidChange();
14463
+
14464
+ this._super();
14465
+ },
14466
+
14467
+ labelPathDidChange: Ember.observer(function() {
14468
+ var labelPath = getPath(this, 'parentView.optionLabelPath');
14469
+
14470
+ if (!labelPath) { return; }
14471
+
14472
+ Ember.defineProperty(this, 'label', Ember.computed(function() {
14473
+ return getPath(this, labelPath);
14474
+ }).property(labelPath).cacheable());
14475
+ }, 'parentView.optionLabelPath'),
14476
+
14477
+ valuePathDidChange: Ember.observer(function() {
14478
+ var valuePath = getPath(this, 'parentView.optionValuePath');
14479
+
14480
+ if (!valuePath) { return; }
14481
+
14482
+ Ember.defineProperty(this, 'value', Ember.computed(function() {
14483
+ return getPath(this, valuePath);
14484
+ }).property(valuePath).cacheable());
14485
+ }, 'parentView.optionValuePath')
14486
+ });
14487
+
14488
+
14489
+ })({});
14490
+
14491
+
13843
14492
  (function(exports) {
13844
14493
  // ==========================================================================
13845
14494
  // Project: Ember Handlebar Views
@@ -13935,7 +14584,7 @@ Ember.Metamorph = Ember.Mixin.create({
13935
14584
  // ==========================================================================
13936
14585
  /*globals Handlebars */
13937
14586
 
13938
- var get = Ember.get, set = Ember.set, getPath = Ember.getPath;
14587
+ var get = Ember.get, set = Ember.set, getPath = Ember.Handlebars.getPath;
13939
14588
  /**
13940
14589
  @ignore
13941
14590
  @private
@@ -14006,6 +14655,29 @@ Ember._BindableSpanView = Ember.View.extend(Ember.Metamorph,
14006
14655
  */
14007
14656
  property: null,
14008
14657
 
14658
+ normalizedValue: Ember.computed(function() {
14659
+ var property = get(this, 'property'),
14660
+ context = get(this, 'previousContext'),
14661
+ valueNormalizer = get(this, 'valueNormalizerFunc'),
14662
+ result;
14663
+
14664
+ // Use the current context as the result if no
14665
+ // property is provided.
14666
+ if (property === '') {
14667
+ result = context;
14668
+ } else {
14669
+ result = getPath(context, property);
14670
+ }
14671
+
14672
+ return valueNormalizer ? valueNormalizer(result) : result;
14673
+ }).property('property', 'previousContext', 'valueNormalizerFunc'),
14674
+
14675
+ rerenderIfNeeded: function() {
14676
+ if (!get(this, 'isDestroyed') && get(this, 'normalizedValue') !== this._lastNormalizedValue) {
14677
+ this.rerender();
14678
+ }
14679
+ },
14680
+
14009
14681
  /**
14010
14682
  Determines which template to invoke, sets up the correct state based on
14011
14683
  that logic, then invokes the default Ember.View `render` implementation.
@@ -14028,23 +14700,14 @@ Ember._BindableSpanView = Ember.View.extend(Ember.Metamorph,
14028
14700
  var escape = get(this, 'isEscaped');
14029
14701
 
14030
14702
  var shouldDisplay = get(this, 'shouldDisplayFunc'),
14031
- property = get(this, 'property'),
14032
14703
  preserveContext = get(this, 'preserveContext'),
14033
14704
  context = get(this, 'previousContext');
14034
14705
 
14035
14706
  var inverseTemplate = get(this, 'inverseTemplate'),
14036
14707
  displayTemplate = get(this, 'displayTemplate');
14037
14708
 
14038
- var result;
14039
-
14040
-
14041
- // Use the current context as the result if no
14042
- // property is provided.
14043
- if (property === '') {
14044
- result = context;
14045
- } else {
14046
- result = getPath(context, property);
14047
- }
14709
+ var result = get(this, 'normalizedValue');
14710
+ this._lastNormalizedValue = result;
14048
14711
 
14049
14712
  // First, test the conditional to see if we should
14050
14713
  // render the template or not.
@@ -14095,12 +14758,15 @@ Ember._BindableSpanView = Ember.View.extend(Ember.Metamorph,
14095
14758
  // License: Licensed under MIT license (see license.js)
14096
14759
  // ==========================================================================
14097
14760
  /*globals Handlebars */
14098
- var get = Ember.get, getPath = Ember.getPath, set = Ember.set, fmt = Ember.String.fmt;
14761
+ var get = Ember.get, getPath = Ember.Handlebars.getPath, set = Ember.set, fmt = Ember.String.fmt;
14762
+
14763
+ var EmberHandlebars = Ember.Handlebars, helpers = EmberHandlebars.helpers;
14764
+ var helpers = EmberHandlebars.helpers;
14099
14765
 
14100
14766
  (function() {
14101
14767
  // Binds a property into the DOM. This will create a hook in DOM that the
14102
- // KVO system will look for and upate if the property changes.
14103
- var bind = function(property, options, preserveContext, shouldDisplay) {
14768
+ // KVO system will look for and update if the property changes.
14769
+ var bind = function(property, options, preserveContext, shouldDisplay, valueNormalizer) {
14104
14770
  var data = options.data,
14105
14771
  fn = options.fn,
14106
14772
  inverse = options.inverse,
@@ -14115,6 +14781,7 @@ var get = Ember.get, getPath = Ember.getPath, set = Ember.set, fmt = Ember.Strin
14115
14781
  var bindView = view.createChildView(Ember._BindableSpanView, {
14116
14782
  preserveContext: preserveContext,
14117
14783
  shouldDisplayFunc: shouldDisplay,
14784
+ valueNormalizerFunc: valueNormalizer,
14118
14785
  displayTemplate: fn,
14119
14786
  inverseTemplate: inverse,
14120
14787
  property: property,
@@ -14124,15 +14791,9 @@ var get = Ember.get, getPath = Ember.getPath, set = Ember.set, fmt = Ember.Strin
14124
14791
 
14125
14792
  view.appendChild(bindView);
14126
14793
 
14127
- var observer, invoker;
14128
-
14129
- observer = function(){
14130
- // Double check since sometimes the view gets destroyed after this observer is already queued
14131
- if (!get(bindView, 'isDestroyed')) { bindView.rerender(); }
14132
- };
14133
-
14134
- invoker = function() {
14135
- Ember.run.once(observer);
14794
+ /** @private */
14795
+ var observer = function() {
14796
+ Ember.run.once(bindView, 'rerenderIfNeeded');
14136
14797
  };
14137
14798
 
14138
14799
  // Observes the given property on the context and
@@ -14140,7 +14801,7 @@ var get = Ember.get, getPath = Ember.getPath, set = Ember.set, fmt = Ember.Strin
14140
14801
  // is an empty string, we are printing the current context
14141
14802
  // object ({{this}}) so updating it is not our responsibility.
14142
14803
  if (property !== '') {
14143
- Ember.addObserver(ctx, property, invoker);
14804
+ Ember.addObserver(ctx, property, observer);
14144
14805
  }
14145
14806
  } else {
14146
14807
  // The object is not observable, so just render it out and
@@ -14149,6 +14810,30 @@ var get = Ember.get, getPath = Ember.getPath, set = Ember.set, fmt = Ember.Strin
14149
14810
  }
14150
14811
  };
14151
14812
 
14813
+ /**
14814
+ '_triageMustache' is used internally select between a binding and helper for
14815
+ the given context. Until this point, it would be hard to determine if the
14816
+ mustache is a property reference or a regular helper reference. This triage
14817
+ helper resolves that.
14818
+
14819
+ This would not be typically invoked by directly.
14820
+
14821
+ @private
14822
+ @name Handlebars.helpers._triageMustache
14823
+ @param {String} property Property/helperID to triage
14824
+ @param {Function} fn Context to provide for rendering
14825
+ @returns {String} HTML string
14826
+ */
14827
+ EmberHandlebars.registerHelper('_triageMustache', function(property, fn) {
14828
+ ember_assert("You cannot pass more than one argument to the _triageMustache helper", arguments.length <= 2);
14829
+ if (helpers[property]) {
14830
+ return helpers[property].call(this, fn);
14831
+ }
14832
+ else {
14833
+ return helpers.bind.apply(this, arguments);
14834
+ }
14835
+ });
14836
+
14152
14837
  /**
14153
14838
  `bind` can be used to display a value, then update that value if it
14154
14839
  changes. For example, if you wanted to print the `title` property of
@@ -14169,7 +14854,7 @@ var get = Ember.get, getPath = Ember.getPath, set = Ember.set, fmt = Ember.Strin
14169
14854
  @param {Function} fn Context to provide for rendering
14170
14855
  @returns {String} HTML string
14171
14856
  */
14172
- Ember.Handlebars.registerHelper('bind', function(property, fn) {
14857
+ EmberHandlebars.registerHelper('bind', function(property, fn) {
14173
14858
  ember_assert("You cannot pass more than one argument to the bind helper", arguments.length <= 2);
14174
14859
 
14175
14860
  var context = (fn.contexts && fn.contexts[0]) || this;
@@ -14193,16 +14878,17 @@ var get = Ember.get, getPath = Ember.getPath, set = Ember.set, fmt = Ember.Strin
14193
14878
  @param {Function} fn Context to provide for rendering
14194
14879
  @returns {String} HTML string
14195
14880
  */
14196
- Ember.Handlebars.registerHelper('boundIf', function(property, fn) {
14881
+ EmberHandlebars.registerHelper('boundIf', function(property, fn) {
14197
14882
  var context = (fn.contexts && fn.contexts[0]) || this;
14198
-
14199
- return bind.call(context, property, fn, true, function(result) {
14883
+ var func = function(result) {
14200
14884
  if (Ember.typeOf(result) === 'array') {
14201
14885
  return get(result, 'length') !== 0;
14202
14886
  } else {
14203
14887
  return !!result;
14204
14888
  }
14205
- } );
14889
+ };
14890
+
14891
+ return bind.call(context, property, fn, true, func, func);
14206
14892
  });
14207
14893
  })();
14208
14894
 
@@ -14212,11 +14898,11 @@ var get = Ember.get, getPath = Ember.getPath, set = Ember.set, fmt = Ember.Strin
14212
14898
  @param {Hash} options
14213
14899
  @returns {String} HTML string
14214
14900
  */
14215
- Ember.Handlebars.registerHelper('with', function(context, options) {
14901
+ EmberHandlebars.registerHelper('with', function(context, options) {
14216
14902
  ember_assert("You must pass exactly one argument to the with helper", arguments.length == 2);
14217
14903
  ember_assert("You must pass a block to the with helper", options.fn && options.fn !== Handlebars.VM.noop);
14218
14904
 
14219
- return Ember.Handlebars.helpers.bind.call(options.contexts[0], context, options);
14905
+ return helpers.bind.call(options.contexts[0], context, options);
14220
14906
  });
14221
14907
 
14222
14908
 
@@ -14226,11 +14912,11 @@ Ember.Handlebars.registerHelper('with', function(context, options) {
14226
14912
  @param {Hash} options
14227
14913
  @returns {String} HTML string
14228
14914
  */
14229
- Ember.Handlebars.registerHelper('if', function(context, options) {
14915
+ EmberHandlebars.registerHelper('if', function(context, options) {
14230
14916
  ember_assert("You must pass exactly one argument to the if helper", arguments.length == 2);
14231
14917
  ember_assert("You must pass a block to the if helper", options.fn && options.fn !== Handlebars.VM.noop);
14232
14918
 
14233
- return Ember.Handlebars.helpers.boundIf.call(options.contexts[0], context, options);
14919
+ return helpers.boundIf.call(options.contexts[0], context, options);
14234
14920
  });
14235
14921
 
14236
14922
  /**
@@ -14239,7 +14925,7 @@ Ember.Handlebars.registerHelper('if', function(context, options) {
14239
14925
  @param {Hash} options
14240
14926
  @returns {String} HTML string
14241
14927
  */
14242
- Ember.Handlebars.registerHelper('unless', function(context, options) {
14928
+ EmberHandlebars.registerHelper('unless', function(context, options) {
14243
14929
  ember_assert("You must pass exactly one argument to the unless helper", arguments.length == 2);
14244
14930
  ember_assert("You must pass a block to the unless helper", options.fn && options.fn !== Handlebars.VM.noop);
14245
14931
 
@@ -14248,7 +14934,7 @@ Ember.Handlebars.registerHelper('unless', function(context, options) {
14248
14934
  options.fn = inverse;
14249
14935
  options.inverse = fn;
14250
14936
 
14251
- return Ember.Handlebars.helpers.boundIf.call(options.contexts[0], context, options);
14937
+ return helpers.boundIf.call(options.contexts[0], context, options);
14252
14938
  });
14253
14939
 
14254
14940
  /**
@@ -14261,7 +14947,7 @@ Ember.Handlebars.registerHelper('unless', function(context, options) {
14261
14947
  @param {Hash} options
14262
14948
  @returns {String} HTML string
14263
14949
  */
14264
- Ember.Handlebars.registerHelper('bindAttr', function(options) {
14950
+ EmberHandlebars.registerHelper('bindAttr', function(options) {
14265
14951
 
14266
14952
  var attrs = options.hash;
14267
14953
 
@@ -14279,7 +14965,7 @@ Ember.Handlebars.registerHelper('bindAttr', function(options) {
14279
14965
  // Handle classes differently, as we can bind multiple classes
14280
14966
  var classBindings = attrs['class'];
14281
14967
  if (classBindings !== null && classBindings !== undefined) {
14282
- var classResults = Ember.Handlebars.bindClasses(this, classBindings, view, dataId);
14968
+ var classResults = EmberHandlebars.bindClasses(this, classBindings, view, dataId);
14283
14969
  ret.push('class="' + classResults.join(' ') + '"');
14284
14970
  delete attrs['class'];
14285
14971
  }
@@ -14299,6 +14985,7 @@ Ember.Handlebars.registerHelper('bindAttr', function(options) {
14299
14985
 
14300
14986
  var observer, invoker;
14301
14987
 
14988
+ /** @private */
14302
14989
  observer = function observer() {
14303
14990
  var result = getPath(ctx, property);
14304
14991
 
@@ -14315,22 +15002,10 @@ Ember.Handlebars.registerHelper('bindAttr', function(options) {
14315
15002
  return;
14316
15003
  }
14317
15004
 
14318
- var currentValue = elem.attr(attr);
14319
-
14320
- // A false result will remove the attribute from the element. This is
14321
- // to support attributes such as disabled, whose presence is meaningful.
14322
- if (result === false && currentValue) {
14323
- elem.removeAttr(attr);
14324
-
14325
- // Likewise, a true result will set the attribute's name as the value.
14326
- } else if (result === true && currentValue !== attr) {
14327
- elem.attr(attr, attr);
14328
-
14329
- } else if (currentValue !== result) {
14330
- elem.attr(attr, result);
14331
- }
15005
+ Ember.View.applyAttributeBindings(elem, attr, result);
14332
15006
  };
14333
15007
 
15008
+ /** @private */
14334
15009
  invoker = function() {
14335
15010
  Ember.run.once(observer);
14336
15011
  };
@@ -14340,21 +15015,19 @@ Ember.Handlebars.registerHelper('bindAttr', function(options) {
14340
15015
  // unique data id and update the attribute to the new value.
14341
15016
  Ember.addObserver(ctx, property, invoker);
14342
15017
 
14343
- // Use the attribute's name as the value when it is YES
14344
- if (value === true) {
14345
- value = attr;
14346
- }
15018
+ // if this changes, also change the logic in ember-views/lib/views/view.js
15019
+ var type = typeof value;
14347
15020
 
14348
- // Do not add the attribute when the value is false
14349
- if (value !== false) {
14350
- // Return the current value, in the form src="foo.jpg"
15021
+ if ((type === 'string' || (type === 'number' && !isNaN(value)))) {
14351
15022
  ret.push(attr + '="' + value + '"');
15023
+ } else if (value && type === 'boolean') {
15024
+ ret.push(attr + '="' + attr + '"');
14352
15025
  }
14353
15026
  }, this);
14354
15027
 
14355
15028
  // Add the unique identifier
14356
15029
  ret.push('data-bindAttr-' + dataId + '="' + dataId + '"');
14357
- return new Ember.Handlebars.SafeString(ret.join(' '));
15030
+ return new EmberHandlebars.SafeString(ret.join(' '));
14358
15031
  });
14359
15032
 
14360
15033
  /**
@@ -14383,7 +15056,7 @@ Ember.Handlebars.registerHelper('bindAttr', function(options) {
14383
15056
 
14384
15057
  @returns {Array} An array of class names to add
14385
15058
  */
14386
- Ember.Handlebars.bindClasses = function(context, classBindings, view, bindAttrId) {
15059
+ EmberHandlebars.bindClasses = function(context, classBindings, view, bindAttrId) {
14387
15060
  var ret = [], newClass, value, elem;
14388
15061
 
14389
15062
  // Helper method to retrieve the property from the context and
@@ -14391,9 +15064,10 @@ Ember.Handlebars.bindClasses = function(context, classBindings, view, bindAttrId
14391
15064
  // a Boolean or not.
14392
15065
  var classStringForProperty = function(property) {
14393
15066
  var split = property.split(':'),
14394
- property = split[0],
14395
15067
  className = split[1];
14396
15068
 
15069
+ property = split[0];
15070
+
14397
15071
  var val = getPath(context, property);
14398
15072
 
14399
15073
  // If value is a Boolean and true, return the dasherized property
@@ -14432,6 +15106,7 @@ Ember.Handlebars.bindClasses = function(context, classBindings, view, bindAttrId
14432
15106
 
14433
15107
  // Set up an observer on the context. If the property changes, toggle the
14434
15108
  // class name.
15109
+ /** @private */
14435
15110
  observer = function() {
14436
15111
  // Get the current value of the property
14437
15112
  newClass = classStringForProperty(binding);
@@ -14458,6 +15133,7 @@ Ember.Handlebars.bindClasses = function(context, classBindings, view, bindAttrId
14458
15133
  }
14459
15134
  };
14460
15135
 
15136
+ /** @private */
14461
15137
  invoker = function() {
14462
15138
  Ember.run.once(observer);
14463
15139
  };
@@ -14540,15 +15216,10 @@ Ember.Handlebars.ViewHelper = Ember.Object.create({
14540
15216
  if (Ember.IS_BINDING.test(prop)) {
14541
15217
  path = options[prop];
14542
15218
  if (!Ember.isGlobalPath(path)) {
14543
- // Binding to parentViews was previously deprecated. In most cases it shouldn't be necessary, but since
14544
- // there are a few valid use cases and most people have broken the parentView habit, we're no longer
14545
- // providing a warning about it.
14546
- if (!PARENT_VIEW_PATH.test(path)) {
14547
- if (path === 'this') {
14548
- options[prop] = 'bindingContext';
14549
- } else {
14550
- options[prop] = 'bindingContext.'+path;
14551
- }
15219
+ if (path === 'this') {
15220
+ options[prop] = 'bindingContext';
15221
+ } else {
15222
+ options[prop] = 'bindingContext.'+path;
14552
15223
  }
14553
15224
  }
14554
15225
  }
@@ -14570,7 +15241,7 @@ Ember.Handlebars.ViewHelper = Ember.Object.create({
14570
15241
  newView;
14571
15242
 
14572
15243
  if ('string' === typeof path) {
14573
- newView = Ember.getPath(thisContext, path);
15244
+ newView = Ember.Handlebars.getPath(thisContext, path);
14574
15245
  ember_assert("Unable to find view at path '" + path + "'", !!newView);
14575
15246
  } else {
14576
15247
  newView = path;
@@ -14622,7 +15293,7 @@ Ember.Handlebars.registerHelper('view', function(path, options) {
14622
15293
  /*globals Handlebars ember_assert */
14623
15294
 
14624
15295
  // TODO: Don't require all of this module
14625
- var get = Ember.get, fmt = Ember.String.fmt;
15296
+ var get = Ember.get, getPath = Ember.Handlebars.getPath, fmt = Ember.String.fmt;
14626
15297
 
14627
15298
  /**
14628
15299
  @name Handlebars.helpers.collection
@@ -14647,7 +15318,7 @@ Ember.Handlebars.registerHelper('collection', function(path, options) {
14647
15318
  // If passed a path string, convert that into an object.
14648
15319
  // Otherwise, just default to the standard class.
14649
15320
  var collectionClass;
14650
- collectionClass = path ? Ember.getPath(this, path) : Ember.CollectionView;
15321
+ collectionClass = path ? getPath(this, path) : Ember.CollectionView;
14651
15322
  ember_assert(fmt("%@ #collection: Could not find %@", data.view, path), !!collectionClass);
14652
15323
 
14653
15324
  var hash = options.hash, itemHash = {}, match;
@@ -14656,7 +15327,7 @@ Ember.Handlebars.registerHelper('collection', function(path, options) {
14656
15327
  var itemViewClass, itemViewPath = hash.itemViewClass;
14657
15328
  var collectionPrototype = get(collectionClass, 'proto');
14658
15329
  delete hash.itemViewClass;
14659
- itemViewClass = itemViewPath ? Ember.getPath(collectionPrototype, itemViewPath) : collectionPrototype.itemViewClass;
15330
+ itemViewClass = itemViewPath ? getPath(collectionPrototype, itemViewPath) : collectionPrototype.itemViewClass;
14660
15331
  ember_assert(fmt("%@ #collection: Could not find %@", data.view, itemViewPath), !!itemViewClass);
14661
15332
 
14662
15333
  // Go through options passed to the {{collection}} helper and extract options
@@ -14714,7 +15385,7 @@ Ember.Handlebars.registerHelper('collection', function(path, options) {
14714
15385
  // License: Licensed under MIT license (see license.js)
14715
15386
  // ==========================================================================
14716
15387
  /*globals Handlebars */
14717
- var getPath = Ember.getPath;
15388
+ var getPath = Ember.Handlebars.getPath;
14718
15389
 
14719
15390
  /**
14720
15391
  `unbound` allows you to output a property without binding. *Important:* The
@@ -14827,6 +15498,64 @@ Ember.Handlebars.registerHelper('template', function(name, options) {
14827
15498
  })({});
14828
15499
 
14829
15500
 
15501
+ (function(exports) {
15502
+ var EmberHandlebars = Ember.Handlebars, getPath = Ember.Handlebars.getPath;
15503
+
15504
+ var ActionHelper = EmberHandlebars.ActionHelper = {};
15505
+
15506
+ ActionHelper.registerAction = function(actionName, eventName, target, view) {
15507
+ var actionId = (++jQuery.uuid).toString(),
15508
+ existingHandler = view[eventName],
15509
+ handler;
15510
+
15511
+ if (existingHandler) {
15512
+ var handler = function(event) {
15513
+ var ret;
15514
+ if ($(event.target).closest('[data-ember-action]').attr('data-ember-action') === actionId) {
15515
+ ret = target[actionName](event);
15516
+ }
15517
+ return ret !== false ? existingHandler.call(view, event) : ret;
15518
+ };
15519
+ } else {
15520
+ var handler = function(event) {
15521
+ if ($(event.target).closest('[data-ember-action]').attr('data-ember-action') === actionId) {
15522
+ return target[actionName](event);
15523
+ }
15524
+ };
15525
+ }
15526
+
15527
+ view[eventName] = handler;
15528
+
15529
+ view.reopen({
15530
+ rerender: function() {
15531
+ if (existingHandler) {
15532
+ view[eventName] = existingHandler;
15533
+ } else {
15534
+ view[eventName] = null;
15535
+ }
15536
+ return this._super();
15537
+ }
15538
+ });
15539
+
15540
+ return actionId;
15541
+ };
15542
+
15543
+ EmberHandlebars.registerHelper('action', function(actionName, options) {
15544
+ var hash = options.hash || {},
15545
+ eventName = options.hash.on || "click",
15546
+ view = options.data.view,
15547
+ target;
15548
+
15549
+ if (view.isVirtual) { view = view.get('parentView'); }
15550
+ target = options.hash.target ? getPath(this, options.hash.target) : view;
15551
+
15552
+ var actionId = ActionHelper.registerAction(actionName, eventName, target, view);
15553
+ return new EmberHandlebars.SafeString('data-ember-action="' + actionId + '"');
15554
+ });
15555
+
15556
+ })({});
15557
+
15558
+
14830
15559
  (function(exports) {
14831
15560
  // ==========================================================================
14832
15561
  // Project: Ember Handlebar Views
@@ -14851,8 +15580,8 @@ Ember.Handlebars.registerHelper('template', function(name, options) {
14851
15580
  // with Ember's Handlebars and are suitable for use as a view's template.
14852
15581
  // Those with type="text/x-raw-handlebars" will be compiled with regular
14853
15582
  // Handlebars and are suitable for use in views' computed properties.
14854
- Ember.Handlebars.bootstrap = function() {
14855
- Ember.$('script[type="text/html"], script[type="text/x-handlebars"], script[type="text/x-raw-handlebars"]')
15583
+ Ember.Handlebars.bootstrap = function(ctx) {
15584
+ Ember.$('script[type="text/html"], script[type="text/x-handlebars"], script[type="text/x-raw-handlebars"]', ctx)
14856
15585
  .each(function() {
14857
15586
  // Get a reference to the script tag
14858
15587
  var script = Ember.$(this),
@@ -14864,7 +15593,7 @@ Ember.Handlebars.bootstrap = function() {
14864
15593
  // id if no name is found.
14865
15594
  templateName = script.attr('data-template-name') || script.attr('id'),
14866
15595
  template = compile(script.html()),
14867
- view, viewPath;
15596
+ view, viewPath, tagName;
14868
15597
 
14869
15598
  if (templateName) {
14870
15599
  // For templates which have a name, we save them and then remove them from the DOM
@@ -14889,8 +15618,13 @@ Ember.Handlebars.bootstrap = function() {
14889
15618
  viewPath = script.attr('data-view');
14890
15619
  view = viewPath ? Ember.getPath(viewPath) : Ember.View;
14891
15620
 
15621
+ // Users can optionally specify a custom tag name to use by setting the
15622
+ // data-tag-name attribute on the script tag.
15623
+ tagName = script.attr('data-tag-name');
15624
+
14892
15625
  view = view.create({
14893
- template: template
15626
+ template: template,
15627
+ tagName: (tagName) ? tagName : undefined
14894
15628
  });
14895
15629
 
14896
15630
  view._insertElementLater(function() {
@@ -14903,7 +15637,11 @@ Ember.Handlebars.bootstrap = function() {
14903
15637
  });
14904
15638
  };
14905
15639
 
14906
- Ember.$(document).ready(Ember.Handlebars.bootstrap);
15640
+ Ember.$(document).ready(
15641
+ function(){
15642
+ Ember.Handlebars.bootstrap( Ember.$(document) );
15643
+ }
15644
+ );
14907
15645
 
14908
15646
  })({});
14909
15647