Add Intel copyright header.
[profile/ivi/cowhide.git] / lib / ember-1.0.0-pre.4.js
1 // Version: v1.0.0-pre.4
2 // Last commit: 855db1a (2013-01-17 23:06:53 -0800)
3
4 (function() {
5 /*global __fail__*/
6
7 /**
8 Ember Debug
9
10 @module ember
11 @submodule ember-debug
12 */
13
14 /**
15 @class Ember
16 */
17
18 if ('undefined' === typeof Ember) {
19   Ember = {};
20
21   if ('undefined' !== typeof window) {
22     window.Em = window.Ember = Em = Ember;
23   }
24 }
25
26 Ember.ENV = 'undefined' === typeof ENV ? {} : ENV;
27
28 if (!('MANDATORY_SETTER' in Ember.ENV)) {
29   Ember.ENV.MANDATORY_SETTER = true; // default to true for debug dist
30 }
31
32 /**
33   Define an assertion that will throw an exception if the condition is not
34   met. Ember build tools will remove any calls to `Ember.assert()` when
35   doing a production build. Example:
36
37   ```javascript
38   // Test for truthiness
39   Ember.assert('Must pass a valid object', obj);
40   // Fail unconditionally
41   Ember.assert('This code path should never be run')
42   ```
43
44   @method assert
45   @param {String} desc A description of the assertion. This will become
46     the text of the Error thrown if the assertion fails.
47   @param {Boolean} test Must be truthy for the assertion to pass. If
48     falsy, an exception will be thrown.
49 */
50 Ember.assert = function(desc, test) {
51   if (!test) throw new Error("assertion failed: "+desc);
52 };
53
54
55 /**
56   Display a warning with the provided message. Ember build tools will
57   remove any calls to `Ember.warn()` when doing a production build.
58
59   @method warn
60   @param {String} message A warning to display.
61   @param {Boolean} test An optional boolean. If falsy, the warning
62     will be displayed.
63 */
64 Ember.warn = function(message, test) {
65   if (!test) {
66     Ember.Logger.warn("WARNING: "+message);
67     if ('trace' in Ember.Logger) Ember.Logger.trace();
68   }
69 };
70
71 /**
72   Display a deprecation warning with the provided message and a stack trace
73   (Chrome and Firefox only). Ember build tools will remove any calls to
74   `Ember.deprecate()` when doing a production build.
75
76   @method deprecate
77   @param {String} message A description of the deprecation.
78   @param {Boolean} test An optional boolean. If falsy, the deprecation
79     will be displayed.
80 */
81 Ember.deprecate = function(message, test) {
82   if (Ember && Ember.TESTING_DEPRECATION) { return; }
83
84   if (arguments.length === 1) { test = false; }
85   if (test) { return; }
86
87   if (Ember && Ember.ENV.RAISE_ON_DEPRECATION) { throw new Error(message); }
88
89   var error;
90
91   // When using new Error, we can't do the arguments check for Chrome. Alternatives are welcome
92   try { __fail__.fail(); } catch (e) { error = e; }
93
94   if (Ember.LOG_STACKTRACE_ON_DEPRECATION && error.stack) {
95     var stack, stackStr = '';
96     if (error['arguments']) {
97       // Chrome
98       stack = error.stack.replace(/^\s+at\s+/gm, '').
99                           replace(/^([^\(]+?)([\n$])/gm, '{anonymous}($1)$2').
100                           replace(/^Object.<anonymous>\s*\(([^\)]+)\)/gm, '{anonymous}($1)').split('\n');
101       stack.shift();
102     } else {
103       // Firefox
104       stack = error.stack.replace(/(?:\n@:0)?\s+$/m, '').
105                           replace(/^\(/gm, '{anonymous}(').split('\n');
106     }
107
108     stackStr = "\n    " + stack.slice(2).join("\n    ");
109     message = message + stackStr;
110   }
111
112   Ember.Logger.warn("DEPRECATION: "+message);
113 };
114
115
116
117 /**
118   Display a deprecation warning with the provided message and a stack trace
119   (Chrome and Firefox only) when the wrapped method is called.
120
121   Ember build tools will not remove calls to `Ember.deprecateFunc()`, though
122   no warnings will be shown in production.
123
124   @method deprecateFunc
125   @param {String} message A description of the deprecation.
126   @param {Function} func The function to be deprecated.
127 */
128 Ember.deprecateFunc = function(message, func) {
129   return function() {
130     Ember.deprecate(message);
131     return func.apply(this, arguments);
132   };
133 };
134
135 if ('undefined' !== typeof window) {
136   window.ember_assert         = Ember.deprecateFunc("ember_assert is deprecated. Please use Ember.assert instead.",               Ember.assert);
137   window.ember_warn           = Ember.deprecateFunc("ember_warn is deprecated. Please use Ember.warn instead.",                   Ember.warn);
138   window.ember_deprecate      = Ember.deprecateFunc("ember_deprecate is deprecated. Please use Ember.deprecate instead.",         Ember.deprecate);
139   window.ember_deprecateFunc  = Ember.deprecateFunc("ember_deprecateFunc is deprecated. Please use Ember.deprecateFunc instead.", Ember.deprecateFunc);
140 }
141
142 })();
143
144 // Version: v1.0.0-pre.3-19-g015138e
145 // Last commit: 015138e (2013-01-17 23:02:17 -0800)
146
147
148 (function() {
149 var define, requireModule;
150
151 (function() {
152   var registry = {}, seen = {};
153
154   define = function(name, deps, callback) {
155     registry[name] = { deps: deps, callback: callback };
156   };
157
158   requireModule = function(name) {
159     if (seen[name]) { return seen[name]; }
160     seen[name] = {};
161
162     var mod = registry[name],
163         deps = mod.deps,
164         callback = mod.callback,
165         reified = [],
166         exports;
167
168     for (var i=0, l=deps.length; i<l; i++) {
169       if (deps[i] === 'exports') {
170         reified.push(exports = {});
171       } else {
172         reified.push(requireModule(deps[i]));
173       }
174     }
175
176     var value = callback.apply(this, reified);
177     return seen[name] = exports || value;
178   };
179 })();
180 (function() {
181 /*globals Em:true ENV */
182
183 /**
184 @module ember
185 @submodule ember-metal
186 */
187
188 /**
189   All Ember methods and functions are defined inside of this namespace. You
190   generally should not add new properties to this namespace as it may be
191   overwritten by future versions of Ember.
192
193   You can also use the shorthand `Em` instead of `Ember`.
194
195   Ember-Runtime is a framework that provides core functions for Ember including
196   cross-platform functions, support for property observing and objects. Its
197   focus is on small size and performance. You can use this in place of or
198   along-side other cross-platform libraries such as jQuery.
199
200   The core Runtime framework is based on the jQuery API with a number of
201   performance optimizations.
202
203   @class Ember
204   @static
205   @version 1.0.0-pre.4
206 */
207
208 if ('undefined' === typeof Ember) {
209   // Create core object. Make it act like an instance of Ember.Namespace so that
210   // objects assigned to it are given a sane string representation.
211   Ember = {};
212 }
213
214 // Default imports, exports and lookup to the global object;
215 var imports = Ember.imports = Ember.imports || this;
216 var exports = Ember.exports = Ember.exports || this;
217 var lookup  = Ember.lookup  = Ember.lookup  || this;
218
219 // aliases needed to keep minifiers from removing the global context
220 exports.Em = exports.Ember = Em = Ember;
221
222 // Make sure these are set whether Ember was already defined or not
223
224 Ember.isNamespace = true;
225
226 Ember.toString = function() { return "Ember"; };
227
228
229 /**
230   @property VERSION
231   @type String
232   @default '1.0.0-pre.4'
233   @final
234 */
235 Ember.VERSION = '1.0.0-pre.4';
236
237 /**
238   Standard environmental variables. You can define these in a global `ENV`
239   variable before loading Ember to control various configuration
240   settings.
241
242   @property ENV
243   @type Hash
244 */
245 Ember.ENV = Ember.ENV || ('undefined' === typeof ENV ? {} : ENV);
246
247 Ember.config = Ember.config || {};
248
249 // ..........................................................
250 // BOOTSTRAP
251 //
252
253 /**
254   Determines whether Ember should enhances some built-in object prototypes to
255   provide a more friendly API. If enabled, a few methods will be added to
256   `Function`, `String`, and `Array`. `Object.prototype` will not be enhanced,
257   which is the one that causes most trouble for people.
258
259   In general we recommend leaving this option set to true since it rarely
260   conflicts with other code. If you need to turn it off however, you can
261   define an `ENV.EXTEND_PROTOTYPES` config to disable it.
262
263   @property EXTEND_PROTOTYPES
264   @type Boolean
265   @default true
266 */
267 Ember.EXTEND_PROTOTYPES = Ember.ENV.EXTEND_PROTOTYPES;
268
269 if (typeof Ember.EXTEND_PROTOTYPES === 'undefined') {
270   Ember.EXTEND_PROTOTYPES = true;
271 }
272
273 /**
274   Determines whether Ember logs a full stack trace during deprecation warnings
275
276   @property LOG_STACKTRACE_ON_DEPRECATION
277   @type Boolean
278   @default true
279 */
280 Ember.LOG_STACKTRACE_ON_DEPRECATION = (Ember.ENV.LOG_STACKTRACE_ON_DEPRECATION !== false);
281
282 /**
283   Determines whether Ember should add ECMAScript 5 shims to older browsers.
284
285   @property SHIM_ES5
286   @type Boolean
287   @default Ember.EXTEND_PROTOTYPES
288 */
289 Ember.SHIM_ES5 = (Ember.ENV.SHIM_ES5 === false) ? false : Ember.EXTEND_PROTOTYPES;
290
291 /**
292   Empty function. Useful for some operations.
293
294   @method K
295   @private
296   @return {Object}
297 */
298 Ember.K = function() { return this; };
299
300
301 // Stub out the methods defined by the ember-debug package in case it's not loaded
302
303 if ('undefined' === typeof Ember.assert) { Ember.assert = Ember.K; }
304 if ('undefined' === typeof Ember.warn) { Ember.warn = Ember.K; }
305 if ('undefined' === typeof Ember.deprecate) { Ember.deprecate = Ember.K; }
306 if ('undefined' === typeof Ember.deprecateFunc) {
307   Ember.deprecateFunc = function(_, func) { return func; };
308 }
309
310 // These are deprecated but still supported
311
312 if ('undefined' === typeof ember_assert) { exports.ember_assert = Ember.K; }
313 if ('undefined' === typeof ember_warn) { exports.ember_warn = Ember.K; }
314 if ('undefined' === typeof ember_deprecate) { exports.ember_deprecate = Ember.K; }
315 if ('undefined' === typeof ember_deprecateFunc) {
316   exports.ember_deprecateFunc = function(_, func) { return func; };
317 }
318
319 /**
320   Previously we used `Ember.$.uuid`, however `$.uuid` has been removed from
321   jQuery master. We'll just bootstrap our own uuid now.
322
323   @property uuid
324   @type Number
325   @private
326 */
327 Ember.uuid = 0;
328
329 // ..........................................................
330 // LOGGER
331 //
332
333 /**
334   Inside Ember-Metal, simply uses the `imports.console` object.
335   Override this to provide more robust logging functionality.
336
337   @class Logger
338   @namespace Ember
339 */
340 Ember.Logger = imports.console || { log: Ember.K, warn: Ember.K, error: Ember.K, info: Ember.K, debug: Ember.K };
341
342
343 // ..........................................................
344 // ERROR HANDLING
345 //
346
347 /**
348   A function may be assigned to `Ember.onerror` to be called when Ember
349   internals encounter an error. This is useful for specialized error handling
350   and reporting code.
351
352   @event onerror
353   @for Ember
354   @param {Exception} error the error object
355 */
356 Ember.onerror = null;
357
358 /**
359   @private
360
361   Wrap code block in a try/catch if {{#crossLink "Ember/onerror"}}{{/crossLink}} is set.
362
363   @method handleErrors
364   @for Ember
365   @param {Function} func
366   @param [context]
367 */
368 Ember.handleErrors = function(func, context) {
369   // Unfortunately in some browsers we lose the backtrace if we rethrow the existing error,
370   // so in the event that we don't have an `onerror` handler we don't wrap in a try/catch
371   if ('function' === typeof Ember.onerror) {
372     try {
373       return func.apply(context || this);
374     } catch (error) {
375       Ember.onerror(error);
376     }
377   } else {
378     return func.apply(context || this);
379   }
380 };
381
382 Ember.merge = function(original, updates) {
383   for (var prop in updates) {
384     if (!updates.hasOwnProperty(prop)) { continue; }
385     original[prop] = updates[prop];
386   }
387 };
388
389 })();
390
391
392
393 (function() {
394 /*globals Node */
395 /**
396 @module ember-metal
397 */
398
399 /**
400   Platform specific methods and feature detectors needed by the framework.
401
402   @class platform
403   @namespace Ember
404   @static
405 */
406 var platform = Ember.platform = {};
407
408
409 /**
410   Identical to `Object.create()`. Implements if not available natively.
411
412   @method create
413   @for Ember
414 */
415 Ember.create = Object.create;
416
417 // STUB_OBJECT_CREATE allows us to override other libraries that stub
418 // Object.create different than we would prefer
419 if (!Ember.create || Ember.ENV.STUB_OBJECT_CREATE) {
420   var K = function() {};
421
422   Ember.create = function(obj, props) {
423     K.prototype = obj;
424     obj = new K();
425     if (props) {
426       K.prototype = obj;
427       for (var prop in props) {
428         K.prototype[prop] = props[prop].value;
429       }
430       obj = new K();
431     }
432     K.prototype = null;
433
434     return obj;
435   };
436
437   Ember.create.isSimulated = true;
438 }
439
440 var defineProperty = Object.defineProperty;
441 var canRedefineProperties, canDefinePropertyOnDOM;
442
443 // Catch IE8 where Object.defineProperty exists but only works on DOM elements
444 if (defineProperty) {
445   try {
446     defineProperty({}, 'a',{get:function(){}});
447   } catch (e) {
448     defineProperty = null;
449   }
450 }
451
452 if (defineProperty) {
453   // Detects a bug in Android <3.2 where you cannot redefine a property using
454   // Object.defineProperty once accessors have already been set.
455   canRedefineProperties = (function() {
456     var obj = {};
457
458     defineProperty(obj, 'a', {
459       configurable: true,
460       enumerable: true,
461       get: function() { },
462       set: function() { }
463     });
464
465     defineProperty(obj, 'a', {
466       configurable: true,
467       enumerable: true,
468       writable: true,
469       value: true
470     });
471
472     return obj.a === true;
473   })();
474
475   // This is for Safari 5.0, which supports Object.defineProperty, but not
476   // on DOM nodes.
477   canDefinePropertyOnDOM = (function(){
478     try {
479       defineProperty(document.createElement('div'), 'definePropertyOnDOM', {});
480       return true;
481     } catch(e) { }
482
483     return false;
484   })();
485
486   if (!canRedefineProperties) {
487     defineProperty = null;
488   } else if (!canDefinePropertyOnDOM) {
489     defineProperty = function(obj, keyName, desc){
490       var isNode;
491
492       if (typeof Node === "object") {
493         isNode = obj instanceof Node;
494       } else {
495         isNode = typeof obj === "object" && typeof obj.nodeType === "number" && typeof obj.nodeName === "string";
496       }
497
498       if (isNode) {
499         // TODO: Should we have a warning here?
500         return (obj[keyName] = desc.value);
501       } else {
502         return Object.defineProperty(obj, keyName, desc);
503       }
504     };
505   }
506 }
507
508 /**
509 @class platform
510 @namespace Ember
511 */
512
513 /**
514   Identical to `Object.defineProperty()`. Implements as much functionality
515   as possible if not available natively.
516
517   @method defineProperty
518   @param {Object} obj The object to modify
519   @param {String} keyName property name to modify
520   @param {Object} desc descriptor hash
521   @return {void}
522 */
523 platform.defineProperty = defineProperty;
524
525 /**
526   Set to true if the platform supports native getters and setters.
527
528   @property hasPropertyAccessors
529   @final
530 */
531 platform.hasPropertyAccessors = true;
532
533 if (!platform.defineProperty) {
534   platform.hasPropertyAccessors = false;
535
536   platform.defineProperty = function(obj, keyName, desc) {
537     if (!desc.get) { obj[keyName] = desc.value; }
538   };
539
540   platform.defineProperty.isSimulated = true;
541 }
542
543 if (Ember.ENV.MANDATORY_SETTER && !platform.hasPropertyAccessors) {
544   Ember.ENV.MANDATORY_SETTER = false;
545 }
546
547 })();
548
549
550
551 (function() {
552 /**
553 @module ember-metal
554 */
555
556
557 var o_defineProperty = Ember.platform.defineProperty,
558     o_create = Ember.create,
559     // Used for guid generation...
560     GUID_KEY = '__ember'+ (+ new Date()),
561     uuid         = 0,
562     numberCache  = [],
563     stringCache  = {};
564
565 var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER;
566
567 /**
568   @private
569
570   A unique key used to assign guids and other private metadata to objects.
571   If you inspect an object in your browser debugger you will often see these.
572   They can be safely ignored.
573
574   On browsers that support it, these properties are added with enumeration
575   disabled so they won't show up when you iterate over your properties.
576
577   @property GUID_KEY
578   @for Ember
579   @type String
580   @final
581 */
582 Ember.GUID_KEY = GUID_KEY;
583
584 var GUID_DESC = {
585   writable:    false,
586   configurable: false,
587   enumerable:  false,
588   value: null
589 };
590
591 /**
592   @private
593
594   Generates a new guid, optionally saving the guid to the object that you
595   pass in. You will rarely need to use this method. Instead you should
596   call `Ember.guidFor(obj)`, which return an existing guid if available.
597
598   @method generateGuid
599   @for Ember
600   @param {Object} [obj] Object the guid will be used for. If passed in, the guid will
601     be saved on the object and reused whenever you pass the same object
602     again.
603
604     If no object is passed, just generate a new guid.
605   @param {String} [prefix] Prefix to place in front of the guid. Useful when you want to
606     separate the guid into separate namespaces.
607   @return {String} the guid
608 */
609 Ember.generateGuid = function generateGuid(obj, prefix) {
610   if (!prefix) prefix = 'ember';
611   var ret = (prefix + (uuid++));
612   if (obj) {
613     GUID_DESC.value = ret;
614     o_defineProperty(obj, GUID_KEY, GUID_DESC);
615   }
616   return ret ;
617 };
618
619 /**
620   @private
621
622   Returns a unique id for the object. If the object does not yet have a guid,
623   one will be assigned to it. You can call this on any object,
624   `Ember.Object`-based or not, but be aware that it will add a `_guid`
625   property.
626
627   You can also use this method on DOM Element objects.
628
629   @method guidFor
630   @for Ember
631   @param obj {Object} any object, string, number, Element, or primitive
632   @return {String} the unique guid for this instance.
633 */
634 Ember.guidFor = function guidFor(obj) {
635
636   // special cases where we don't want to add a key to object
637   if (obj === undefined) return "(undefined)";
638   if (obj === null) return "(null)";
639
640   var cache, ret;
641   var type = typeof obj;
642
643   // Don't allow prototype changes to String etc. to change the guidFor
644   switch(type) {
645     case 'number':
646       ret = numberCache[obj];
647       if (!ret) ret = numberCache[obj] = 'nu'+obj;
648       return ret;
649
650     case 'string':
651       ret = stringCache[obj];
652       if (!ret) ret = stringCache[obj] = 'st'+(uuid++);
653       return ret;
654
655     case 'boolean':
656       return obj ? '(true)' : '(false)';
657
658     default:
659       if (obj[GUID_KEY]) return obj[GUID_KEY];
660       if (obj === Object) return '(Object)';
661       if (obj === Array)  return '(Array)';
662       ret = 'ember'+(uuid++);
663       GUID_DESC.value = ret;
664       o_defineProperty(obj, GUID_KEY, GUID_DESC);
665       return ret;
666   }
667 };
668
669 // ..........................................................
670 // META
671 //
672
673 var META_DESC = {
674   writable:    true,
675   configurable: false,
676   enumerable:  false,
677   value: null
678 };
679
680 var META_KEY = Ember.GUID_KEY+'_meta';
681
682 /**
683   The key used to store meta information on object for property observing.
684
685   @property META_KEY
686   @for Ember
687   @private
688   @final
689   @type String
690 */
691 Ember.META_KEY = META_KEY;
692
693 // Placeholder for non-writable metas.
694 var EMPTY_META = {
695   descs: {},
696   watching: {}
697 };
698
699 if (MANDATORY_SETTER) { EMPTY_META.values = {}; }
700
701 Ember.EMPTY_META = EMPTY_META;
702
703 if (Object.freeze) Object.freeze(EMPTY_META);
704
705 var isDefinePropertySimulated = Ember.platform.defineProperty.isSimulated;
706
707 function Meta(obj) {
708   this.descs = {};
709   this.watching = {};
710   this.cache = {};
711   this.source = obj;
712 }
713
714 if (isDefinePropertySimulated) {
715   // on platforms that don't support enumerable false
716   // make meta fail jQuery.isPlainObject() to hide from
717   // jQuery.extend() by having a property that fails
718   // hasOwnProperty check.
719   Meta.prototype.__preventPlainObject__ = true;
720
721   // Without non-enumerable properties, meta objects will be output in JSON
722   // unless explicitly suppressed
723   Meta.prototype.toJSON = function () { };
724 }
725
726 /**
727   Retrieves the meta hash for an object. If `writable` is true ensures the
728   hash is writable for this object as well.
729
730   The meta object contains information about computed property descriptors as
731   well as any watched properties and other information. You generally will
732   not access this information directly but instead work with higher level
733   methods that manipulate this hash indirectly.
734
735   @method meta
736   @for Ember
737   @private
738
739   @param {Object} obj The object to retrieve meta for
740   @param {Boolean} [writable=true] Pass `false` if you do not intend to modify
741     the meta hash, allowing the method to avoid making an unnecessary copy.
742   @return {Hash}
743 */
744 Ember.meta = function meta(obj, writable) {
745
746   var ret = obj[META_KEY];
747   if (writable===false) return ret || EMPTY_META;
748
749   if (!ret) {
750     if (!isDefinePropertySimulated) o_defineProperty(obj, META_KEY, META_DESC);
751
752     ret = new Meta(obj);
753
754     if (MANDATORY_SETTER) { ret.values = {}; }
755
756     obj[META_KEY] = ret;
757
758     // make sure we don't accidentally try to create constructor like desc
759     ret.descs.constructor = null;
760
761   } else if (ret.source !== obj) {
762     if (!isDefinePropertySimulated) o_defineProperty(obj, META_KEY, META_DESC);
763
764     ret = o_create(ret);
765     ret.descs    = o_create(ret.descs);
766     ret.watching = o_create(ret.watching);
767     ret.cache    = {};
768     ret.source   = obj;
769
770     if (MANDATORY_SETTER) { ret.values = o_create(ret.values); }
771
772     obj[META_KEY] = ret;
773   }
774   return ret;
775 };
776
777 Ember.getMeta = function getMeta(obj, property) {
778   var meta = Ember.meta(obj, false);
779   return meta[property];
780 };
781
782 Ember.setMeta = function setMeta(obj, property, value) {
783   var meta = Ember.meta(obj, true);
784   meta[property] = value;
785   return value;
786 };
787
788 /**
789   @private
790
791   In order to store defaults for a class, a prototype may need to create
792   a default meta object, which will be inherited by any objects instantiated
793   from the class's constructor.
794
795   However, the properties of that meta object are only shallow-cloned,
796   so if a property is a hash (like the event system's `listeners` hash),
797   it will by default be shared across all instances of that class.
798
799   This method allows extensions to deeply clone a series of nested hashes or
800   other complex objects. For instance, the event system might pass
801   `['listeners', 'foo:change', 'ember157']` to `prepareMetaPath`, which will
802   walk down the keys provided.
803
804   For each key, if the key does not exist, it is created. If it already
805   exists and it was inherited from its constructor, the constructor's
806   key is cloned.
807
808   You can also pass false for `writable`, which will simply return
809   undefined if `prepareMetaPath` discovers any part of the path that
810   shared or undefined.
811
812   @method metaPath
813   @for Ember
814   @param {Object} obj The object whose meta we are examining
815   @param {Array} path An array of keys to walk down
816   @param {Boolean} writable whether or not to create a new meta
817     (or meta property) if one does not already exist or if it's
818     shared with its constructor
819 */
820 Ember.metaPath = function metaPath(obj, path, writable) {
821   var meta = Ember.meta(obj, writable), keyName, value;
822
823   for (var i=0, l=path.length; i<l; i++) {
824     keyName = path[i];
825     value = meta[keyName];
826
827     if (!value) {
828       if (!writable) { return undefined; }
829       value = meta[keyName] = { __ember_source__: obj };
830     } else if (value.__ember_source__ !== obj) {
831       if (!writable) { return undefined; }
832       value = meta[keyName] = o_create(value);
833       value.__ember_source__ = obj;
834     }
835
836     meta = value;
837   }
838
839   return value;
840 };
841
842 /**
843   @private
844
845   Wraps the passed function so that `this._super` will point to the superFunc
846   when the function is invoked. This is the primitive we use to implement
847   calls to super.
848
849   @method wrap
850   @for Ember
851   @param {Function} func The function to call
852   @param {Function} superFunc The super function.
853   @return {Function} wrapped function.
854 */
855 Ember.wrap = function(func, superFunc) {
856   function K() {}
857
858   function superWrapper() {
859     var ret, sup = this._super;
860     this._super = superFunc || K;
861     ret = func.apply(this, arguments);
862     this._super = sup;
863     return ret;
864   }
865
866   superWrapper.wrappedFunction = func;
867   superWrapper.__ember_observes__ = func.__ember_observes__;
868   superWrapper.__ember_observesBefore__ = func.__ember_observesBefore__;
869
870   return superWrapper;
871 };
872
873 /**
874   Returns true if the passed object is an array or Array-like.
875
876   Ember Array Protocol:
877
878     - the object has an objectAt property
879     - the object is a native Array
880     - the object is an Object, and has a length property
881
882   Unlike `Ember.typeOf` this method returns true even if the passed object is
883   not formally array but appears to be array-like (i.e. implements `Ember.Array`)
884
885   ```javascript
886   Ember.isArray();                                            // false
887   Ember.isArray([]);                                          // true
888   Ember.isArray( Ember.ArrayProxy.create({ content: [] }) );  // true
889   ```
890
891   @method isArray
892   @for Ember
893   @param {Object} obj The object to test
894   @return {Boolean}
895 */
896 Ember.isArray = function(obj) {
897   if (!obj || obj.setInterval) { return false; }
898   if (Array.isArray && Array.isArray(obj)) { return true; }
899   if (Ember.Array && Ember.Array.detect(obj)) { return true; }
900   if ((obj.length !== undefined) && 'object'===typeof obj) { return true; }
901   return false;
902 };
903
904 /**
905   Forces the passed object to be part of an array. If the object is already
906   an array or array-like, returns the object. Otherwise adds the object to
907   an array. If obj is `null` or `undefined`, returns an empty array.
908
909   ```javascript
910   Ember.makeArray();                           // []
911   Ember.makeArray(null);                       // []
912   Ember.makeArray(undefined);                  // []
913   Ember.makeArray('lindsay');                  // ['lindsay']
914   Ember.makeArray([1,2,42]);                   // [1,2,42]
915
916   var controller = Ember.ArrayProxy.create({ content: [] });
917   Ember.makeArray(controller) === controller;  // true
918   ```
919
920   @method makeArray
921   @for Ember
922   @param {Object} obj the object
923   @return {Array}
924 */
925 Ember.makeArray = function(obj) {
926   if (obj === null || obj === undefined) { return []; }
927   return Ember.isArray(obj) ? obj : [obj];
928 };
929
930 function canInvoke(obj, methodName) {
931   return !!(obj && typeof obj[methodName] === 'function');
932 }
933
934 /**
935   Checks to see if the `methodName` exists on the `obj`.
936
937   @method canInvoke
938   @for Ember
939   @param {Object} obj The object to check for the method
940   @param {String} methodName The method name to check for
941 */
942 Ember.canInvoke = canInvoke;
943
944 /**
945   Checks to see if the `methodName` exists on the `obj`,
946   and if it does, invokes it with the arguments passed.
947
948   @method tryInvoke
949   @for Ember
950   @param {Object} obj The object to check for the method
951   @param {String} methodName The method name to check for
952   @param {Array} [args] The arguments to pass to the method
953   @return {anything} the return value of the invoked method or undefined if it cannot be invoked
954 */
955 Ember.tryInvoke = function(obj, methodName, args) {
956   if (canInvoke(obj, methodName)) {
957     return obj[methodName].apply(obj, args || []);
958   }
959 };
960
961 // https://github.com/emberjs/ember.js/pull/1617
962 var needsFinallyFix = (function() {
963   var count = 0;
964   try{
965     try { }
966     finally {
967       count++;
968       throw new Error('needsFinallyFixTest');
969     }
970   } catch (e) {}
971
972   return count !== 1;
973 })();
974
975 /**
976   Provides try { } finally { } functionality, while working
977   around Safari's double finally bug.
978
979   @method tryFinally
980   @for Ember
981   @param {Function} function The function to run the try callback
982   @param {Function} function The function to run the finally callback
983   @param [binding]
984   @return {anything} The return value is the that of the finalizer,
985   unless that valueis undefined, in which case it is the return value
986   of the tryable
987 */
988
989 if (needsFinallyFix) {
990   Ember.tryFinally = function(tryable, finalizer, binding) {
991     var result, finalResult, finalError;
992
993     binding = binding || this;
994
995     try {
996       result = tryable.call(binding);
997     } finally {
998       try {
999         finalResult = finalizer.call(binding);
1000       } catch (e){
1001         finalError = e;
1002       }
1003     }
1004
1005     if (finalError) { throw finalError; }
1006
1007     return (finalResult === undefined) ? result : finalResult;
1008   };
1009 } else {
1010   Ember.tryFinally = function(tryable, finalizer, binding) {
1011     var result, finalResult;
1012
1013     binding = binding || this;
1014
1015     try {
1016       result = tryable.call(binding);
1017     } finally {
1018       finalResult = finalizer.call(binding);
1019     }
1020
1021     return (finalResult === undefined) ? result : finalResult;
1022   };
1023 }
1024
1025 /**
1026   Provides try { } catch finally { } functionality, while working
1027   around Safari's double finally bug.
1028
1029   @method tryCatchFinally
1030   @for Ember
1031   @param {Function} function The function to run the try callback
1032   @param {Function} function The function to run the catchable callback
1033   @param {Function} function The function to run the finally callback
1034   @param [binding]
1035   @return {anything} The return value is the that of the finalizer,
1036   unless that value is undefined, in which case it is the return value
1037   of the tryable.
1038 */
1039 if (needsFinallyFix) {
1040   Ember.tryCatchFinally = function(tryable, catchable, finalizer, binding) {
1041     var result, finalResult, finalError, finalReturn;
1042
1043     binding = binding || this;
1044
1045     try {
1046       result = tryable.call(binding);
1047     } catch(error) {
1048       result = catchable.call(binding, error);
1049     } finally {
1050       try {
1051         finalResult = finalizer.call(binding);
1052       } catch (e){
1053         finalError = e;
1054       }
1055     }
1056
1057     if (finalError) { throw finalError; }
1058
1059     return (finalResult === undefined) ? result : finalResult;
1060   };
1061 } else {
1062   Ember.tryCatchFinally = function(tryable, catchable, finalizer, binding) {
1063     var result, finalResult;
1064
1065     binding = binding || this;
1066
1067     try {
1068       result = tryable.call(binding);
1069     } catch(error) {
1070       result = catchable.call(binding, error);
1071     } finally {
1072       finalResult = finalizer.call(binding);
1073     }
1074
1075     return (finalResult === undefined) ? result : finalResult;
1076   };
1077 }
1078
1079 })();
1080
1081
1082
1083 (function() {
1084 // Ember.tryCatchFinally
1085
1086 /**
1087   The purpose of the Ember Instrumentation module is
1088   to provide efficient, general-purpose instrumentation
1089   for Ember.
1090
1091   Subscribe to a listener by using `Ember.subscribe`:
1092
1093   ```javascript
1094   Ember.subscribe("render", {
1095     before: function(name, timestamp, payload) {
1096
1097     },
1098
1099     after: function(name, timestamp, payload) {
1100
1101     }
1102   });
1103   ```
1104
1105   If you return a value from the `before` callback, that same
1106   value will be passed as a fourth parameter to the `after`
1107   callback.
1108
1109   Instrument a block of code by using `Ember.instrument`:
1110
1111   ```javascript
1112   Ember.instrument("render.handlebars", payload, function() {
1113     // rendering logic
1114   }, binding);
1115   ```
1116
1117   Event names passed to `Ember.instrument` are namespaced
1118   by periods, from more general to more specific. Subscribers
1119   can listen for events by whatever level of granularity they
1120   are interested in.
1121
1122   In the above example, the event is `render.handlebars`,
1123   and the subscriber listened for all events beginning with
1124   `render`. It would receive callbacks for events named
1125   `render`, `render.handlebars`, `render.container`, or
1126   even `render.handlebars.layout`.
1127
1128   @class Instrumentation
1129   @namespace Ember
1130   @static
1131 */
1132 Ember.Instrumentation = {};
1133
1134 var subscribers = [], cache = {};
1135
1136 var populateListeners = function(name) {
1137   var listeners = [], subscriber;
1138
1139   for (var i=0, l=subscribers.length; i<l; i++) {
1140     subscriber = subscribers[i];
1141     if (subscriber.regex.test(name)) {
1142       listeners.push(subscriber.object);
1143     }
1144   }
1145
1146   cache[name] = listeners;
1147   return listeners;
1148 };
1149
1150 var time = (function() {
1151         var perf = 'undefined' !== typeof window ? window.performance || {} : {};
1152         var fn = perf.now || perf.mozNow || perf.webkitNow || perf.msNow || perf.oNow;
1153         // fn.bind will be available in all the browsers that support the advanced window.performance... ;-)
1154         return fn ? fn.bind(perf) : function() { return +new Date(); };
1155 })();
1156
1157
1158 Ember.Instrumentation.instrument = function(name, payload, callback, binding) {
1159   var listeners = cache[name], timeName, ret;
1160
1161   if (Ember.STRUCTURED_PROFILE) {
1162     timeName = name + ": " + payload.object;
1163     console.time(timeName);
1164   }
1165
1166   if (!listeners) {
1167     listeners = populateListeners(name);
1168   }
1169
1170   if (listeners.length === 0) {
1171     ret = callback.call(binding);
1172     if (Ember.STRUCTURED_PROFILE) { console.timeEnd(timeName); }
1173     return ret;
1174   }
1175
1176   var beforeValues = [], listener, i, l;
1177
1178   function tryable(){
1179     for (i=0, l=listeners.length; i<l; i++) {
1180       listener = listeners[i];
1181       beforeValues[i] = listener.before(name, time(), payload);
1182     }
1183
1184     return callback.call(binding);
1185   }
1186
1187   function catchable(e){
1188     payload = payload || {};
1189     payload.exception = e;
1190   }
1191
1192   function finalizer() {
1193     for (i=0, l=listeners.length; i<l; i++) {
1194       listener = listeners[i];
1195       listener.after(name, time(), payload, beforeValues[i]);
1196     }
1197
1198     if (Ember.STRUCTURED_PROFILE) {
1199       console.timeEnd(timeName);
1200     }
1201   }
1202
1203   return Ember.tryCatchFinally(tryable, catchable, finalizer);
1204 };
1205
1206 Ember.Instrumentation.subscribe = function(pattern, object) {
1207   var paths = pattern.split("."), path, regex = [];
1208
1209   for (var i=0, l=paths.length; i<l; i++) {
1210     path = paths[i];
1211     if (path === "*") {
1212       regex.push("[^\\.]*");
1213     } else {
1214       regex.push(path);
1215     }
1216   }
1217
1218   regex = regex.join("\\.");
1219   regex = regex + "(\\..*)?";
1220
1221   var subscriber = {
1222     pattern: pattern,
1223     regex: new RegExp("^" + regex + "$"),
1224     object: object
1225   };
1226
1227   subscribers.push(subscriber);
1228   cache = {};
1229
1230   return subscriber;
1231 };
1232
1233 Ember.Instrumentation.unsubscribe = function(subscriber) {
1234   var index;
1235
1236   for (var i=0, l=subscribers.length; i<l; i++) {
1237     if (subscribers[i] === subscriber) {
1238       index = i;
1239     }
1240   }
1241
1242   subscribers.splice(index, 1);
1243   cache = {};
1244 };
1245
1246 Ember.Instrumentation.reset = function() {
1247   subscribers = [];
1248   cache = {};
1249 };
1250
1251 Ember.instrument = Ember.Instrumentation.instrument;
1252 Ember.subscribe = Ember.Instrumentation.subscribe;
1253
1254 })();
1255
1256
1257
1258 (function() {
1259 /*jshint newcap:false*/
1260
1261 /**
1262 @module ember-metal
1263 */
1264
1265 // NOTE: There is a bug in jshint that doesn't recognize `Object()` without `new`
1266 // as being ok unless both `newcap:false` and not `use strict`.
1267 // https://github.com/jshint/jshint/issues/392
1268
1269 // Testing this is not ideal, but we want to use native functions
1270 // if available, but not to use versions created by libraries like Prototype
1271 var isNativeFunc = function(func) {
1272   // This should probably work in all browsers likely to have ES5 array methods
1273   return func && Function.prototype.toString.call(func).indexOf('[native code]') > -1;
1274 };
1275
1276 // From: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/map
1277 var arrayMap = isNativeFunc(Array.prototype.map) ? Array.prototype.map : function(fun /*, thisp */) {
1278   //"use strict";
1279
1280   if (this === void 0 || this === null) {
1281     throw new TypeError();
1282   }
1283
1284   var t = Object(this);
1285   var len = t.length >>> 0;
1286   if (typeof fun !== "function") {
1287     throw new TypeError();
1288   }
1289
1290   var res = new Array(len);
1291   var thisp = arguments[1];
1292   for (var i = 0; i < len; i++) {
1293     if (i in t) {
1294       res[i] = fun.call(thisp, t[i], i, t);
1295     }
1296   }
1297
1298   return res;
1299 };
1300
1301 // From: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/foreach
1302 var arrayForEach = isNativeFunc(Array.prototype.forEach) ? Array.prototype.forEach : function(fun /*, thisp */) {
1303   //"use strict";
1304
1305   if (this === void 0 || this === null) {
1306     throw new TypeError();
1307   }
1308
1309   var t = Object(this);
1310   var len = t.length >>> 0;
1311   if (typeof fun !== "function") {
1312     throw new TypeError();
1313   }
1314
1315   var thisp = arguments[1];
1316   for (var i = 0; i < len; i++) {
1317     if (i in t) {
1318       fun.call(thisp, t[i], i, t);
1319     }
1320   }
1321 };
1322
1323 var arrayIndexOf = isNativeFunc(Array.prototype.indexOf) ? Array.prototype.indexOf : function (obj, fromIndex) {
1324   if (fromIndex === null || fromIndex === undefined) { fromIndex = 0; }
1325   else if (fromIndex < 0) { fromIndex = Math.max(0, this.length + fromIndex); }
1326   for (var i = fromIndex, j = this.length; i < j; i++) {
1327     if (this[i] === obj) { return i; }
1328   }
1329   return -1;
1330 };
1331
1332 Ember.ArrayPolyfills = {
1333   map: arrayMap,
1334   forEach: arrayForEach,
1335   indexOf: arrayIndexOf
1336 };
1337
1338 var utils = Ember.EnumerableUtils = {
1339   map: function(obj, callback, thisArg) {
1340     return obj.map ? obj.map.call(obj, callback, thisArg) : arrayMap.call(obj, callback, thisArg);
1341   },
1342
1343   forEach: function(obj, callback, thisArg) {
1344     return obj.forEach ? obj.forEach.call(obj, callback, thisArg) : arrayForEach.call(obj, callback, thisArg);
1345   },
1346
1347   indexOf: function(obj, element, index) {
1348     return obj.indexOf ? obj.indexOf.call(obj, element, index) : arrayIndexOf.call(obj, element, index);
1349   },
1350
1351   indexesOf: function(obj, elements) {
1352     return elements === undefined ? [] : utils.map(elements, function(item) {
1353       return utils.indexOf(obj, item);
1354     });
1355   },
1356
1357   addObject: function(array, item) {
1358     var index = utils.indexOf(array, item);
1359     if (index === -1) { array.push(item); }
1360   },
1361
1362   removeObject: function(array, item) {
1363     var index = utils.indexOf(array, item);
1364     if (index !== -1) { array.splice(index, 1); }
1365   },
1366
1367   replace: function(array, idx, amt, objects) {
1368     if (array.replace) {
1369       return array.replace(idx, amt, objects);
1370     } else {
1371       var args = Array.prototype.concat.apply([idx, amt], objects);
1372       return array.splice.apply(array, args);
1373     }
1374   }
1375 };
1376
1377
1378 if (Ember.SHIM_ES5) {
1379   if (!Array.prototype.map) {
1380     Array.prototype.map = arrayMap;
1381   }
1382
1383   if (!Array.prototype.forEach) {
1384     Array.prototype.forEach = arrayForEach;
1385   }
1386
1387   if (!Array.prototype.indexOf) {
1388     Array.prototype.indexOf = arrayIndexOf;
1389   }
1390 }
1391
1392 })();
1393
1394
1395
1396 (function() {
1397 /**
1398 @module ember-metal
1399 */
1400
1401 /*
1402   JavaScript (before ES6) does not have a Map implementation. Objects,
1403   which are often used as dictionaries, may only have Strings as keys.
1404
1405   Because Ember has a way to get a unique identifier for every object
1406   via `Ember.guidFor`, we can implement a performant Map with arbitrary
1407   keys. Because it is commonly used in low-level bookkeeping, Map is
1408   implemented as a pure JavaScript object for performance.
1409
1410   This implementation follows the current iteration of the ES6 proposal for
1411   maps (http://wiki.ecmascript.org/doku.php?id=harmony:simple_maps_and_sets),
1412   with two exceptions. First, because we need our implementation to be pleasant
1413   on older browsers, we do not use the `delete` name (using `remove` instead).
1414   Second, as we do not have the luxury of in-VM iteration, we implement a
1415   forEach method for iteration.
1416
1417   Map is mocked out to look like an Ember object, so you can do
1418   `Ember.Map.create()` for symmetry with other Ember classes.
1419 */
1420 var guidFor = Ember.guidFor,
1421     indexOf = Ember.ArrayPolyfills.indexOf;
1422
1423 var copy = function(obj) {
1424   var output = {};
1425
1426   for (var prop in obj) {
1427     if (obj.hasOwnProperty(prop)) { output[prop] = obj[prop]; }
1428   }
1429
1430   return output;
1431 };
1432
1433 var copyMap = function(original, newObject) {
1434   var keys = original.keys.copy(),
1435       values = copy(original.values);
1436
1437   newObject.keys = keys;
1438   newObject.values = values;
1439
1440   return newObject;
1441 };
1442
1443 /**
1444   This class is used internally by Ember and Ember Data.
1445   Please do not use it at this time. We plan to clean it up
1446   and add many tests soon.
1447
1448   @class OrderedSet
1449   @namespace Ember
1450   @constructor
1451   @private
1452 */
1453 var OrderedSet = Ember.OrderedSet = function() {
1454   this.clear();
1455 };
1456
1457 /**
1458   @method create
1459   @static
1460   @return {Ember.OrderedSet}
1461 */
1462 OrderedSet.create = function() {
1463   return new OrderedSet();
1464 };
1465
1466
1467 OrderedSet.prototype = {
1468   /**
1469     @method clear
1470   */
1471   clear: function() {
1472     this.presenceSet = {};
1473     this.list = [];
1474   },
1475
1476   /**
1477     @method add
1478     @param obj
1479   */
1480   add: function(obj) {
1481     var guid = guidFor(obj),
1482         presenceSet = this.presenceSet,
1483         list = this.list;
1484
1485     if (guid in presenceSet) { return; }
1486
1487     presenceSet[guid] = true;
1488     list.push(obj);
1489   },
1490
1491   /**
1492     @method remove
1493     @param obj
1494   */
1495   remove: function(obj) {
1496     var guid = guidFor(obj),
1497         presenceSet = this.presenceSet,
1498         list = this.list;
1499
1500     delete presenceSet[guid];
1501
1502     var index = indexOf.call(list, obj);
1503     if (index > -1) {
1504       list.splice(index, 1);
1505     }
1506   },
1507
1508   /**
1509     @method isEmpty
1510     @return {Boolean}
1511   */
1512   isEmpty: function() {
1513     return this.list.length === 0;
1514   },
1515
1516   /**
1517     @method has
1518     @param obj
1519     @return {Boolean}
1520   */
1521   has: function(obj) {
1522     var guid = guidFor(obj),
1523         presenceSet = this.presenceSet;
1524
1525     return guid in presenceSet;
1526   },
1527
1528   /**
1529     @method forEach
1530     @param {Function} function
1531     @param target
1532   */
1533   forEach: function(fn, self) {
1534     // allow mutation during iteration
1535     var list = this.list.slice();
1536
1537     for (var i = 0, j = list.length; i < j; i++) {
1538       fn.call(self, list[i]);
1539     }
1540   },
1541
1542   /**
1543     @method toArray
1544     @return {Array}
1545   */
1546   toArray: function() {
1547     return this.list.slice();
1548   },
1549
1550   /**
1551     @method copy
1552     @return {Ember.OrderedSet}
1553   */
1554   copy: function() {
1555     var set = new OrderedSet();
1556
1557     set.presenceSet = copy(this.presenceSet);
1558     set.list = this.list.slice();
1559
1560     return set;
1561   }
1562 };
1563
1564 /**
1565   A Map stores values indexed by keys. Unlike JavaScript's
1566   default Objects, the keys of a Map can be any JavaScript
1567   object.
1568
1569   Internally, a Map has two data structures:
1570
1571   1. `keys`: an OrderedSet of all of the existing keys
1572   2. `values`: a JavaScript Object indexed by the `Ember.guidFor(key)`
1573
1574   When a key/value pair is added for the first time, we
1575   add the key to the `keys` OrderedSet, and create or
1576   replace an entry in `values`. When an entry is deleted,
1577   we delete its entry in `keys` and `values`.
1578
1579   @class Map
1580   @namespace Ember
1581   @private
1582   @constructor
1583 */
1584 var Map = Ember.Map = function() {
1585   this.keys = Ember.OrderedSet.create();
1586   this.values = {};
1587 };
1588
1589 /**
1590   @method create
1591   @static
1592 */
1593 Map.create = function() {
1594   return new Map();
1595 };
1596
1597 Map.prototype = {
1598   /**
1599     Retrieve the value associated with a given key.
1600
1601     @method get
1602     @param {anything} key
1603     @return {anything} the value associated with the key, or `undefined`
1604   */
1605   get: function(key) {
1606     var values = this.values,
1607         guid = guidFor(key);
1608
1609     return values[guid];
1610   },
1611
1612   /**
1613     Adds a value to the map. If a value for the given key has already been
1614     provided, the new value will replace the old value.
1615
1616     @method set
1617     @param {anything} key
1618     @param {anything} value
1619   */
1620   set: function(key, value) {
1621     var keys = this.keys,
1622         values = this.values,
1623         guid = guidFor(key);
1624
1625     keys.add(key);
1626     values[guid] = value;
1627   },
1628
1629   /**
1630     Removes a value from the map for an associated key.
1631
1632     @method remove
1633     @param {anything} key
1634     @return {Boolean} true if an item was removed, false otherwise
1635   */
1636   remove: function(key) {
1637     // don't use ES6 "delete" because it will be annoying
1638     // to use in browsers that are not ES6 friendly;
1639     var keys = this.keys,
1640         values = this.values,
1641         guid = guidFor(key),
1642         value;
1643
1644     if (values.hasOwnProperty(guid)) {
1645       keys.remove(key);
1646       value = values[guid];
1647       delete values[guid];
1648       return true;
1649     } else {
1650       return false;
1651     }
1652   },
1653
1654   /**
1655     Check whether a key is present.
1656
1657     @method has
1658     @param {anything} key
1659     @return {Boolean} true if the item was present, false otherwise
1660   */
1661   has: function(key) {
1662     var values = this.values,
1663         guid = guidFor(key);
1664
1665     return values.hasOwnProperty(guid);
1666   },
1667
1668   /**
1669     Iterate over all the keys and values. Calls the function once
1670     for each key, passing in the key and value, in that order.
1671
1672     The keys are guaranteed to be iterated over in insertion order.
1673
1674     @method forEach
1675     @param {Function} callback
1676     @param {anything} self if passed, the `this` value inside the
1677       callback. By default, `this` is the map.
1678   */
1679   forEach: function(callback, self) {
1680     var keys = this.keys,
1681         values = this.values;
1682
1683     keys.forEach(function(key) {
1684       var guid = guidFor(key);
1685       callback.call(self, key, values[guid]);
1686     });
1687   },
1688
1689   /**
1690     @method copy
1691     @return {Ember.Map}
1692   */
1693   copy: function() {
1694     return copyMap(this, new Map());
1695   }
1696 };
1697
1698 /**
1699   @class MapWithDefault
1700   @namespace Ember
1701   @extends Ember.Map
1702   @private
1703   @constructor
1704   @param [options]
1705     @param {anything} [options.defaultValue]
1706 */
1707 var MapWithDefault = Ember.MapWithDefault = function(options) {
1708   Map.call(this);
1709   this.defaultValue = options.defaultValue;
1710 };
1711
1712 /**
1713   @method create
1714   @static
1715   @param [options]
1716     @param {anything} [options.defaultValue]
1717   @return {Ember.MapWithDefault|Ember.Map} If options are passed, returns 
1718     `Ember.MapWithDefault` otherwise returns `Ember.Map`
1719 */
1720 MapWithDefault.create = function(options) {
1721   if (options) {
1722     return new MapWithDefault(options);
1723   } else {
1724     return new Map();
1725   }
1726 };
1727
1728 MapWithDefault.prototype = Ember.create(Map.prototype);
1729
1730 /**
1731   Retrieve the value associated with a given key.
1732
1733   @method get
1734   @param {anything} key
1735   @return {anything} the value associated with the key, or the default value
1736 */
1737 MapWithDefault.prototype.get = function(key) {
1738   var hasValue = this.has(key);
1739
1740   if (hasValue) {
1741     return Map.prototype.get.call(this, key);
1742   } else {
1743     var defaultValue = this.defaultValue(key);
1744     this.set(key, defaultValue);
1745     return defaultValue;
1746   }
1747 };
1748
1749 /**
1750   @method copy
1751   @return {Ember.MapWithDefault}
1752 */
1753 MapWithDefault.prototype.copy = function() {
1754   return copyMap(this, new MapWithDefault({
1755     defaultValue: this.defaultValue
1756   }));
1757 };
1758
1759 })();
1760
1761
1762
1763 (function() {
1764 /**
1765 @module ember-metal
1766 */
1767
1768 var META_KEY = Ember.META_KEY, get, set;
1769
1770 var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER;
1771
1772 var IS_GLOBAL = /^([A-Z$]|([0-9][A-Z$]))/;
1773 var IS_GLOBAL_PATH = /^([A-Z$]|([0-9][A-Z$])).*[\.\*]/;
1774 var HAS_THIS  = /^this[\.\*]/;
1775 var FIRST_KEY = /^([^\.\*]+)/;
1776
1777 // ..........................................................
1778 // GET AND SET
1779 //
1780 // If we are on a platform that supports accessors we can get use those.
1781 // Otherwise simulate accessors by looking up the property directly on the
1782 // object.
1783
1784 /**
1785   Gets the value of a property on an object. If the property is computed,
1786   the function will be invoked. If the property is not defined but the
1787   object implements the `unknownProperty` method then that will be invoked.
1788
1789   If you plan to run on IE8 and older browsers then you should use this
1790   method anytime you want to retrieve a property on an object that you don't
1791   know for sure is private. (Properties beginning with an underscore '_' 
1792   are considered private.)
1793
1794   On all newer browsers, you only need to use this method to retrieve
1795   properties if the property might not be defined on the object and you want
1796   to respect the `unknownProperty` handler. Otherwise you can ignore this
1797   method.
1798
1799   Note that if the object itself is `undefined`, this method will throw
1800   an error.
1801
1802   @method get
1803   @for Ember
1804   @param {Object} obj The object to retrieve from.
1805   @param {String} keyName The property key to retrieve
1806   @return {Object} the property value or `null`.
1807 */
1808 get = function get(obj, keyName) {
1809   // Helpers that operate with 'this' within an #each
1810   if (keyName === '') {
1811     return obj;
1812   }
1813
1814   if (!keyName && 'string'===typeof obj) {
1815     keyName = obj;
1816     obj = null;
1817   }
1818
1819   if (!obj || keyName.indexOf('.') !== -1) {
1820     Ember.assert("Cannot call get with '"+ keyName +"' on an undefined object.", obj !== undefined);
1821     return getPath(obj, keyName);
1822   }
1823
1824   Ember.assert("You need to provide an object and key to `get`.", !!obj && keyName);
1825
1826   var meta = obj[META_KEY], desc = meta && meta.descs[keyName], ret;
1827   if (desc) {
1828     return desc.get(obj, keyName);
1829   } else {
1830     if (MANDATORY_SETTER && meta && meta.watching[keyName] > 0) {
1831       ret = meta.values[keyName];
1832     } else {
1833       ret = obj[keyName];
1834     }
1835
1836     if (ret === undefined &&
1837         'object' === typeof obj && !(keyName in obj) && 'function' === typeof obj.unknownProperty) {
1838       return obj.unknownProperty(keyName);
1839     }
1840
1841     return ret;
1842   }
1843 };
1844
1845 /**
1846   Sets the value of a property on an object, respecting computed properties
1847   and notifying observers and other listeners of the change. If the
1848   property is not defined but the object implements the `unknownProperty`
1849   method then that will be invoked as well.
1850
1851   If you plan to run on IE8 and older browsers then you should use this
1852   method anytime you want to set a property on an object that you don't
1853   know for sure is private. (Properties beginning with an underscore '_' 
1854   are considered private.)
1855
1856   On all newer browsers, you only need to use this method to set
1857   properties if the property might not be defined on the object and you want
1858   to respect the `unknownProperty` handler. Otherwise you can ignore this
1859   method.
1860
1861   @method set
1862   @for Ember
1863   @param {Object} obj The object to modify.
1864   @param {String} keyName The property key to set
1865   @param {Object} value The value to set
1866   @return {Object} the passed value.
1867 */
1868 set = function set(obj, keyName, value, tolerant) {
1869   if (typeof obj === 'string') {
1870     Ember.assert("Path '" + obj + "' must be global if no obj is given.", IS_GLOBAL.test(obj));
1871     value = keyName;
1872     keyName = obj;
1873     obj = null;
1874   }
1875
1876   if (!obj || keyName.indexOf('.') !== -1) {
1877     return setPath(obj, keyName, value, tolerant);
1878   }
1879
1880   Ember.assert("You need to provide an object and key to `set`.", !!obj && keyName !== undefined);
1881   Ember.assert('calling set on destroyed object', !obj.isDestroyed);
1882
1883   var meta = obj[META_KEY], desc = meta && meta.descs[keyName],
1884       isUnknown, currentValue;
1885   if (desc) {
1886     desc.set(obj, keyName, value);
1887   } else {
1888     isUnknown = 'object' === typeof obj && !(keyName in obj);
1889
1890     // setUnknownProperty is called if `obj` is an object,
1891     // the property does not already exist, and the
1892     // `setUnknownProperty` method exists on the object
1893     if (isUnknown && 'function' === typeof obj.setUnknownProperty) {
1894       obj.setUnknownProperty(keyName, value);
1895     } else if (meta && meta.watching[keyName] > 0) {
1896       if (MANDATORY_SETTER) {
1897         currentValue = meta.values[keyName];
1898       } else {
1899         currentValue = obj[keyName];
1900       }
1901       // only trigger a change if the value has changed
1902       if (value !== currentValue) {
1903         Ember.propertyWillChange(obj, keyName);
1904         if (MANDATORY_SETTER) {
1905           if (currentValue === undefined && !(keyName in obj)) {
1906             Ember.defineProperty(obj, keyName, null, value); // setup mandatory setter
1907           } else {
1908             meta.values[keyName] = value;
1909           }
1910         } else {
1911           obj[keyName] = value;
1912         }
1913         Ember.propertyDidChange(obj, keyName);
1914       }
1915     } else {
1916       obj[keyName] = value;
1917     }
1918   }
1919   return value;
1920 };
1921
1922 // Currently used only by Ember Data tests
1923 if (Ember.config.overrideAccessors) {
1924   Ember.get = get;
1925   Ember.set = set;
1926   Ember.config.overrideAccessors();
1927   get = Ember.get;
1928   set = Ember.set;
1929 }
1930
1931 function firstKey(path) {
1932   return path.match(FIRST_KEY)[0];
1933 }
1934
1935 // assumes path is already normalized
1936 function normalizeTuple(target, path) {
1937   var hasThis  = HAS_THIS.test(path),
1938       isGlobal = !hasThis && IS_GLOBAL_PATH.test(path),
1939       key;
1940
1941   if (!target || isGlobal) target = Ember.lookup;
1942   if (hasThis) path = path.slice(5);
1943
1944   if (target === Ember.lookup) {
1945     key = firstKey(path);
1946     target = get(target, key);
1947     path   = path.slice(key.length+1);
1948   }
1949
1950   // must return some kind of path to be valid else other things will break.
1951   if (!path || path.length===0) throw new Error('Invalid Path');
1952
1953   return [ target, path ];
1954 }
1955
1956 function getPath(root, path) {
1957   var hasThis, parts, tuple, idx, len;
1958
1959   // If there is no root and path is a key name, return that
1960   // property from the global object.
1961   // E.g. get('Ember') -> Ember
1962   if (root === null && path.indexOf('.') === -1) { return get(Ember.lookup, path); }
1963
1964   // detect complicated paths and normalize them
1965   hasThis  = HAS_THIS.test(path);
1966
1967   if (!root || hasThis) {
1968     tuple = normalizeTuple(root, path);
1969     root = tuple[0];
1970     path = tuple[1];
1971     tuple.length = 0;
1972   }
1973
1974   parts = path.split(".");
1975   len = parts.length;
1976   for (idx=0; root && idx<len; idx++) {
1977     root = get(root, parts[idx], true);
1978     if (root && root.isDestroyed) { return undefined; }
1979   }
1980   return root;
1981 }
1982
1983 function setPath(root, path, value, tolerant) {
1984   var keyName;
1985
1986   // get the last part of the path
1987   keyName = path.slice(path.lastIndexOf('.') + 1);
1988
1989   // get the first part of the part
1990   path    = path.slice(0, path.length-(keyName.length+1));
1991
1992   // unless the path is this, look up the first part to
1993   // get the root
1994   if (path !== 'this') {
1995     root = getPath(root, path);
1996   }
1997
1998   if (!keyName || keyName.length === 0) {
1999     throw new Error('You passed an empty path');
2000   }
2001
2002   if (!root) {
2003     if (tolerant) { return; }
2004     else { throw new Error('Object in path '+path+' could not be found or was destroyed.'); }
2005   }
2006
2007   return set(root, keyName, value);
2008 }
2009
2010 /**
2011   @private
2012
2013   Normalizes a target/path pair to reflect that actual target/path that should
2014   be observed, etc. This takes into account passing in global property
2015   paths (i.e. a path beginning with a captial letter not defined on the
2016   target) and * separators.
2017
2018   @method normalizeTuple
2019   @for Ember
2020   @param {Object} target The current target. May be `null`.
2021   @param {String} path A path on the target or a global property path.
2022   @return {Array} a temporary array with the normalized target/path pair.
2023 */
2024 Ember.normalizeTuple = function(target, path) {
2025   return normalizeTuple(target, path);
2026 };
2027
2028 Ember.getWithDefault = function(root, key, defaultValue) {
2029   var value = get(root, key);
2030
2031   if (value === undefined) { return defaultValue; }
2032   return value;
2033 };
2034
2035
2036 Ember.get = get;
2037 Ember.getPath = Ember.deprecateFunc('getPath is deprecated since get now supports paths', Ember.get);
2038
2039 Ember.set = set;
2040 Ember.setPath = Ember.deprecateFunc('setPath is deprecated since set now supports paths', Ember.set);
2041
2042 /**
2043   Error-tolerant form of `Ember.set`. Will not blow up if any part of the
2044   chain is `undefined`, `null`, or destroyed.
2045
2046   This is primarily used when syncing bindings, which may try to update after
2047   an object has been destroyed.
2048
2049   @method trySet
2050   @for Ember
2051   @param {Object} obj The object to modify.
2052   @param {String} keyName The property key to set
2053   @param {Object} value The value to set
2054 */
2055 Ember.trySet = function(root, path, value) {
2056   return set(root, path, value, true);
2057 };
2058 Ember.trySetPath = Ember.deprecateFunc('trySetPath has been renamed to trySet', Ember.trySet);
2059
2060 /**
2061   Returns true if the provided path is global (e.g., `MyApp.fooController.bar`)
2062   instead of local (`foo.bar.baz`).
2063
2064   @method isGlobalPath
2065   @for Ember
2066   @private
2067   @param {String} path
2068   @return Boolean
2069 */
2070 Ember.isGlobalPath = function(path) {
2071   return IS_GLOBAL.test(path);
2072 };
2073
2074
2075 })();
2076
2077
2078
2079 (function() {
2080 /**
2081 @module ember-metal
2082 */
2083
2084 var GUID_KEY = Ember.GUID_KEY,
2085     META_KEY = Ember.META_KEY,
2086     EMPTY_META = Ember.EMPTY_META,
2087     metaFor = Ember.meta,
2088     o_create = Ember.create,
2089     objectDefineProperty = Ember.platform.defineProperty;
2090
2091 var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER;
2092
2093 // ..........................................................
2094 // DESCRIPTOR
2095 //
2096
2097 /**
2098   Objects of this type can implement an interface to responds requests to
2099   get and set. The default implementation handles simple properties.
2100
2101   You generally won't need to create or subclass this directly.
2102
2103   @class Descriptor
2104   @namespace Ember
2105   @private
2106   @constructor
2107 */
2108 var Descriptor = Ember.Descriptor = function() {};
2109
2110 // ..........................................................
2111 // DEFINING PROPERTIES API
2112 //
2113
2114 /**
2115   @private
2116
2117   NOTE: This is a low-level method used by other parts of the API. You almost
2118   never want to call this method directly. Instead you should use
2119   `Ember.mixin()` to define new properties.
2120
2121   Defines a property on an object. This method works much like the ES5
2122   `Object.defineProperty()` method except that it can also accept computed
2123   properties and other special descriptors.
2124
2125   Normally this method takes only three parameters. However if you pass an
2126   instance of `Ember.Descriptor` as the third param then you can pass an
2127   optional value as the fourth parameter. This is often more efficient than
2128   creating new descriptor hashes for each property.
2129
2130   ## Examples
2131
2132   ```javascript
2133   // ES5 compatible mode
2134   Ember.defineProperty(contact, 'firstName', {
2135     writable: true,
2136     configurable: false,
2137     enumerable: true,
2138     value: 'Charles'
2139   });
2140
2141   // define a simple property
2142   Ember.defineProperty(contact, 'lastName', undefined, 'Jolley');
2143
2144   // define a computed property
2145   Ember.defineProperty(contact, 'fullName', Ember.computed(function() {
2146     return this.firstName+' '+this.lastName;
2147   }).property('firstName', 'lastName'));
2148   ```
2149
2150   @method defineProperty
2151   @for Ember
2152   @param {Object} obj the object to define this property on. This may be a prototype.
2153   @param {String} keyName the name of the property
2154   @param {Ember.Descriptor} [desc] an instance of `Ember.Descriptor` (typically a
2155     computed property) or an ES5 descriptor.
2156     You must provide this or `data` but not both.
2157   @param {anything} [data] something other than a descriptor, that will
2158     become the explicit value of this property.
2159 */
2160 Ember.defineProperty = function(obj, keyName, desc, data, meta) {
2161   var descs, existingDesc, watching, value;
2162
2163   if (!meta) meta = metaFor(obj);
2164   descs = meta.descs;
2165   existingDesc = meta.descs[keyName];
2166   watching = meta.watching[keyName] > 0;
2167
2168   if (existingDesc instanceof Ember.Descriptor) {
2169     existingDesc.teardown(obj, keyName);
2170   }
2171
2172   if (desc instanceof Ember.Descriptor) {
2173     value = desc;
2174
2175     descs[keyName] = desc;
2176     if (MANDATORY_SETTER && watching) {
2177       objectDefineProperty(obj, keyName, {
2178         configurable: true,
2179         enumerable: true,
2180         writable: true,
2181         value: undefined // make enumerable
2182       });
2183     } else {
2184       obj[keyName] = undefined; // make enumerable
2185     }
2186     desc.setup(obj, keyName);
2187   } else {
2188     descs[keyName] = undefined; // shadow descriptor in proto
2189     if (desc == null) {
2190       value = data;
2191
2192       if (MANDATORY_SETTER && watching) {
2193         meta.values[keyName] = data;
2194         objectDefineProperty(obj, keyName, {
2195           configurable: true,
2196           enumerable: true,
2197           set: function() {
2198             Ember.assert('Must use Ember.set() to access this property', false);
2199           },
2200           get: function() {
2201             var meta = this[META_KEY];
2202             return meta && meta.values[keyName];
2203           }
2204         });
2205       } else {
2206         obj[keyName] = data;
2207       }
2208     } else {
2209       value = desc;
2210
2211       // compatibility with ES5
2212       objectDefineProperty(obj, keyName, desc);
2213     }
2214   }
2215
2216   // if key is being watched, override chains that
2217   // were initialized with the prototype
2218   if (watching) { Ember.overrideChains(obj, keyName, meta); }
2219
2220   // The `value` passed to the `didDefineProperty` hook is
2221   // either the descriptor or data, whichever was passed.
2222   if (obj.didDefineProperty) { obj.didDefineProperty(obj, keyName, value); }
2223
2224   return this;
2225 };
2226
2227
2228 })();
2229
2230
2231
2232 (function() {
2233 // Ember.tryFinally
2234 /**
2235 @module ember-metal
2236 */
2237
2238 var AFTER_OBSERVERS = ':change';
2239 var BEFORE_OBSERVERS = ':before';
2240
2241 var guidFor = Ember.guidFor;
2242
2243 var deferred = 0;
2244
2245 /*
2246   this.observerSet = {
2247     [senderGuid]: { // variable name: `keySet`
2248       [keyName]: listIndex
2249     }
2250   },
2251   this.observers = [
2252     {
2253       sender: obj,
2254       keyName: keyName,
2255       eventName: eventName,
2256       listeners: [
2257         [target, method, onceFlag, suspendedFlag]
2258       ]
2259     },
2260     ...
2261   ]
2262 */
2263 function ObserverSet() {
2264   this.clear();
2265 }
2266
2267 ObserverSet.prototype.add = function(sender, keyName, eventName) {
2268   var observerSet = this.observerSet,
2269       observers = this.observers,
2270       senderGuid = Ember.guidFor(sender),
2271       keySet = observerSet[senderGuid],
2272       index;
2273
2274   if (!keySet) {
2275     observerSet[senderGuid] = keySet = {};
2276   }
2277   index = keySet[keyName];
2278   if (index === undefined) {
2279     index = observers.push({
2280       sender: sender,
2281       keyName: keyName,
2282       eventName: eventName,
2283       listeners: []
2284     }) - 1;
2285     keySet[keyName] = index;
2286   }
2287   return observers[index].listeners;
2288 };
2289
2290 ObserverSet.prototype.flush = function() {
2291   var observers = this.observers, i, len, observer, sender;
2292   this.clear();
2293   for (i=0, len=observers.length; i < len; ++i) {
2294     observer = observers[i];
2295     sender = observer.sender;
2296     if (sender.isDestroying || sender.isDestroyed) { continue; }
2297     Ember.sendEvent(sender, observer.eventName, [sender, observer.keyName], observer.listeners);
2298   }
2299 };
2300
2301 ObserverSet.prototype.clear = function() {
2302   this.observerSet = {};
2303   this.observers = [];
2304 };
2305
2306 var beforeObserverSet = new ObserverSet(), observerSet = new ObserverSet();
2307
2308 /**
2309   @method beginPropertyChanges
2310   @chainable
2311 */
2312 Ember.beginPropertyChanges = function() {
2313   deferred++;
2314 };
2315
2316 /**
2317   @method endPropertyChanges
2318 */
2319 Ember.endPropertyChanges = function() {
2320   deferred--;
2321   if (deferred<=0) {
2322     beforeObserverSet.clear();
2323     observerSet.flush();
2324   }
2325 };
2326
2327 /**
2328   Make a series of property changes together in an
2329   exception-safe way.
2330
2331   ```javascript
2332   Ember.changeProperties(function() {
2333     obj1.set('foo', mayBlowUpWhenSet);
2334     obj2.set('bar', baz);
2335   });
2336   ```
2337
2338   @method changeProperties
2339   @param {Function} callback
2340   @param [binding]
2341 */
2342 Ember.changeProperties = function(cb, binding){
2343   Ember.beginPropertyChanges();
2344   Ember.tryFinally(cb, Ember.endPropertyChanges, binding);
2345 };
2346
2347 /**
2348   Set a list of properties on an object. These properties are set inside
2349   a single `beginPropertyChanges` and `endPropertyChanges` batch, so
2350   observers will be buffered.
2351
2352   @method setProperties
2353   @param target
2354   @param {Hash} properties
2355   @return target
2356 */
2357 Ember.setProperties = function(self, hash) {
2358   Ember.changeProperties(function(){
2359     for(var prop in hash) {
2360       if (hash.hasOwnProperty(prop)) Ember.set(self, prop, hash[prop]);
2361     }
2362   });
2363   return self;
2364 };
2365
2366
2367 function changeEvent(keyName) {
2368   return keyName+AFTER_OBSERVERS;
2369 }
2370
2371 function beforeEvent(keyName) {
2372   return keyName+BEFORE_OBSERVERS;
2373 }
2374
2375 /**
2376   @method addObserver
2377   @param obj
2378   @param {String} path
2379   @param {Object|Function} targetOrMethod
2380   @param {Function|String} [method]
2381 */
2382 Ember.addObserver = function(obj, path, target, method) {
2383   Ember.addListener(obj, changeEvent(path), target, method);
2384   Ember.watch(obj, path);
2385   return this;
2386 };
2387
2388 Ember.observersFor = function(obj, path) {
2389   return Ember.listenersFor(obj, changeEvent(path));
2390 };
2391
2392 /**
2393   @method removeObserver
2394   @param obj
2395   @param {String} path
2396   @param {Object|Function} targetOrMethod
2397   @param {Function|String} [method]
2398 */
2399 Ember.removeObserver = function(obj, path, target, method) {
2400   Ember.unwatch(obj, path);
2401   Ember.removeListener(obj, changeEvent(path), target, method);
2402   return this;
2403 };
2404
2405 /**
2406   @method addBeforeObserver
2407   @param obj
2408   @param {String} path
2409   @param {Object|Function} targetOrMethod
2410   @param {Function|String} [method]
2411 */
2412 Ember.addBeforeObserver = function(obj, path, target, method) {
2413   Ember.addListener(obj, beforeEvent(path), target, method);
2414   Ember.watch(obj, path);
2415   return this;
2416 };
2417
2418 // Suspend observer during callback.
2419 //
2420 // This should only be used by the target of the observer
2421 // while it is setting the observed path.
2422 Ember._suspendBeforeObserver = function(obj, path, target, method, callback) {
2423   return Ember._suspendListener(obj, beforeEvent(path), target, method, callback);
2424 };
2425
2426 Ember._suspendObserver = function(obj, path, target, method, callback) {
2427   return Ember._suspendListener(obj, changeEvent(path), target, method, callback);
2428 };
2429
2430 var map = Ember.ArrayPolyfills.map;
2431
2432 Ember._suspendBeforeObservers = function(obj, paths, target, method, callback) {
2433   var events = map.call(paths, beforeEvent);
2434   return Ember._suspendListeners(obj, events, target, method, callback);
2435 };
2436
2437 Ember._suspendObservers = function(obj, paths, target, method, callback) {
2438   var events = map.call(paths, changeEvent);
2439   return Ember._suspendListeners(obj, events, target, method, callback);
2440 };
2441
2442 Ember.beforeObserversFor = function(obj, path) {
2443   return Ember.listenersFor(obj, beforeEvent(path));
2444 };
2445
2446 /**
2447   @method removeBeforeObserver
2448   @param obj
2449   @param {String} path
2450   @param {Object|Function} targetOrMethod
2451   @param {Function|String} [method]
2452 */
2453 Ember.removeBeforeObserver = function(obj, path, target, method) {
2454   Ember.unwatch(obj, path);
2455   Ember.removeListener(obj, beforeEvent(path), target, method);
2456   return this;
2457 };
2458
2459 Ember.notifyBeforeObservers = function(obj, keyName) {
2460   if (obj.isDestroying) { return; }
2461
2462   var eventName = beforeEvent(keyName), listeners, listenersDiff;
2463   if (deferred) {
2464     listeners = beforeObserverSet.add(obj, keyName, eventName);
2465     listenersDiff = Ember.listenersDiff(obj, eventName, listeners);
2466     Ember.sendEvent(obj, eventName, [obj, keyName], listenersDiff);
2467   } else {
2468     Ember.sendEvent(obj, eventName, [obj, keyName]);
2469   }
2470 };
2471
2472 Ember.notifyObservers = function(obj, keyName) {
2473   if (obj.isDestroying) { return; }
2474
2475   var eventName = changeEvent(keyName), listeners;
2476   if (deferred) {
2477     listeners = observerSet.add(obj, keyName, eventName);
2478     Ember.listenersUnion(obj, eventName, listeners);
2479   } else {
2480     Ember.sendEvent(obj, eventName, [obj, keyName]);
2481   }
2482 };
2483
2484 })();
2485
2486
2487
2488 (function() {
2489 /**
2490 @module ember-metal
2491 */
2492
2493 var guidFor = Ember.guidFor, // utils.js
2494     metaFor = Ember.meta, // utils.js
2495     get = Ember.get, // accessors.js
2496     set = Ember.set, // accessors.js
2497     normalizeTuple = Ember.normalizeTuple, // accessors.js
2498     GUID_KEY = Ember.GUID_KEY, // utils.js
2499     META_KEY = Ember.META_KEY, // utils.js
2500     // circular reference observer depends on Ember.watch
2501     // we should move change events to this file or its own property_events.js
2502     notifyObservers = Ember.notifyObservers, // observer.js
2503     forEach = Ember.ArrayPolyfills.forEach, // array.js
2504     FIRST_KEY = /^([^\.\*]+)/,
2505     IS_PATH = /[\.\*]/;
2506
2507 var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER,
2508 o_defineProperty = Ember.platform.defineProperty;
2509
2510 function firstKey(path) {
2511   return path.match(FIRST_KEY)[0];
2512 }
2513
2514 // returns true if the passed path is just a keyName
2515 function isKeyName(path) {
2516   return path==='*' || !IS_PATH.test(path);
2517 }
2518
2519 // ..........................................................
2520 // DEPENDENT KEYS
2521 //
2522
2523 function iterDeps(method, obj, depKey, seen, meta) {
2524
2525   var guid = guidFor(obj);
2526   if (!seen[guid]) seen[guid] = {};
2527   if (seen[guid][depKey]) return;
2528   seen[guid][depKey] = true;
2529
2530   var deps = meta.deps;
2531   deps = deps && deps[depKey];
2532   if (deps) {
2533     for(var key in deps) {
2534       var desc = meta.descs[key];
2535       if (desc && desc._suspended === obj) continue;
2536       method(obj, key);
2537     }
2538   }
2539 }
2540
2541
2542 var WILL_SEEN, DID_SEEN;
2543
2544 // called whenever a property is about to change to clear the cache of any dependent keys (and notify those properties of changes, etc...)
2545 function dependentKeysWillChange(obj, depKey, meta) {
2546   if (obj.isDestroying) { return; }
2547
2548   var seen = WILL_SEEN, top = !seen;
2549   if (top) { seen = WILL_SEEN = {}; }
2550   iterDeps(propertyWillChange, obj, depKey, seen, meta);
2551   if (top) { WILL_SEEN = null; }
2552 }
2553
2554 // called whenever a property has just changed to update dependent keys
2555 function dependentKeysDidChange(obj, depKey, meta) {
2556   if (obj.isDestroying) { return; }
2557
2558   var seen = DID_SEEN, top = !seen;
2559   if (top) { seen = DID_SEEN = {}; }
2560   iterDeps(propertyDidChange, obj, depKey, seen, meta);
2561   if (top) { DID_SEEN = null; }
2562 }
2563
2564 // ..........................................................
2565 // CHAIN
2566 //
2567
2568 function addChainWatcher(obj, keyName, node) {
2569   if (!obj || ('object' !== typeof obj)) { return; } // nothing to do
2570
2571   var m = metaFor(obj), nodes = m.chainWatchers;
2572
2573   if (!m.hasOwnProperty('chainWatchers')) {
2574     nodes = m.chainWatchers = {};
2575   }
2576
2577   if (!nodes[keyName]) { nodes[keyName] = []; }
2578   nodes[keyName].push(node);
2579   Ember.watch(obj, keyName);
2580 }
2581
2582 function removeChainWatcher(obj, keyName, node) {
2583   if (!obj || 'object' !== typeof obj) { return; } // nothing to do
2584
2585   var m = metaFor(obj, false);
2586   if (!m.hasOwnProperty('chainWatchers')) { return; } // nothing to do
2587
2588   var nodes = m.chainWatchers;
2589
2590   if (nodes[keyName]) {
2591     nodes = nodes[keyName];
2592     for (var i = 0, l = nodes.length; i < l; i++) {
2593       if (nodes[i] === node) { nodes.splice(i, 1); }
2594     }
2595   }
2596   Ember.unwatch(obj, keyName);
2597 }
2598
2599 var pendingQueue = [];
2600
2601 // attempts to add the pendingQueue chains again. If some of them end up
2602 // back in the queue and reschedule is true, schedules a timeout to try
2603 // again.
2604 function flushPendingChains() {
2605   if (pendingQueue.length === 0) { return; } // nothing to do
2606
2607   var queue = pendingQueue;
2608   pendingQueue = [];
2609
2610   forEach.call(queue, function(q) { q[0].add(q[1]); });
2611
2612   Ember.warn('Watching an undefined global, Ember expects watched globals to be setup by the time the run loop is flushed, check for typos', pendingQueue.length === 0);
2613 }
2614
2615 function isProto(pvalue) {
2616   return metaFor(pvalue, false).proto === pvalue;
2617 }
2618
2619 // A ChainNode watches a single key on an object. If you provide a starting
2620 // value for the key then the node won't actually watch it. For a root node
2621 // pass null for parent and key and object for value.
2622 var ChainNode = function(parent, key, value) {
2623   var obj;
2624   this._parent = parent;
2625   this._key    = key;
2626
2627   // _watching is true when calling get(this._parent, this._key) will
2628   // return the value of this node.
2629   //
2630   // It is false for the root of a chain (because we have no parent)
2631   // and for global paths (because the parent node is the object with
2632   // the observer on it)
2633   this._watching = value===undefined;
2634
2635   this._value  = value;
2636   this._paths = {};
2637   if (this._watching) {
2638     this._object = parent.value();
2639     if (this._object) { addChainWatcher(this._object, this._key, this); }
2640   }
2641
2642   // Special-case: the EachProxy relies on immediate evaluation to
2643   // establish its observers.
2644   //
2645   // TODO: Replace this with an efficient callback that the EachProxy
2646   // can implement.
2647   if (this._parent && this._parent._key === '@each') {
2648     this.value();
2649   }
2650 };
2651
2652 var ChainNodePrototype = ChainNode.prototype;
2653
2654 ChainNodePrototype.value = function() {
2655   if (this._value === undefined && this._watching) {
2656     var obj = this._parent.value();
2657     this._value = (obj && !isProto(obj)) ? get(obj, this._key) : undefined;
2658   }
2659   return this._value;
2660 };
2661
2662 ChainNodePrototype.destroy = function() {
2663   if (this._watching) {
2664     var obj = this._object;
2665     if (obj) { removeChainWatcher(obj, this._key, this); }
2666     this._watching = false; // so future calls do nothing
2667   }
2668 };
2669
2670 // copies a top level object only
2671 ChainNodePrototype.copy = function(obj) {
2672   var ret = new ChainNode(null, null, obj),
2673       paths = this._paths, path;
2674   for (path in paths) {
2675     if (paths[path] <= 0) { continue; } // this check will also catch non-number vals.
2676     ret.add(path);
2677   }
2678   return ret;
2679 };
2680
2681 // called on the root node of a chain to setup watchers on the specified
2682 // path.
2683 ChainNodePrototype.add = function(path) {
2684   var obj, tuple, key, src, paths;
2685
2686   paths = this._paths;
2687   paths[path] = (paths[path] || 0) + 1;
2688
2689   obj = this.value();
2690   tuple = normalizeTuple(obj, path);
2691
2692   // the path was a local path
2693   if (tuple[0] && tuple[0] === obj) {
2694     path = tuple[1];
2695     key  = firstKey(path);
2696     path = path.slice(key.length+1);
2697
2698   // global path, but object does not exist yet.
2699   // put into a queue and try to connect later.
2700   } else if (!tuple[0]) {
2701     pendingQueue.push([this, path]);
2702     tuple.length = 0;
2703     return;
2704
2705   // global path, and object already exists
2706   } else {
2707     src  = tuple[0];
2708     key  = path.slice(0, 0-(tuple[1].length+1));
2709     path = tuple[1];
2710   }
2711
2712   tuple.length = 0;
2713   this.chain(key, path, src);
2714 };
2715
2716 // called on the root node of a chain to teardown watcher on the specified
2717 // path
2718 ChainNodePrototype.remove = function(path) {
2719   var obj, tuple, key, src, paths;
2720
2721   paths = this._paths;
2722   if (paths[path] > 0) { paths[path]--; }
2723
2724   obj = this.value();
2725   tuple = normalizeTuple(obj, path);
2726   if (tuple[0] === obj) {
2727     path = tuple[1];
2728     key  = firstKey(path);
2729     path = path.slice(key.length+1);
2730   } else {
2731     src  = tuple[0];
2732     key  = path.slice(0, 0-(tuple[1].length+1));
2733     path = tuple[1];
2734   }
2735
2736   tuple.length = 0;
2737   this.unchain(key, path);
2738 };
2739
2740 ChainNodePrototype.count = 0;
2741
2742 ChainNodePrototype.chain = function(key, path, src) {
2743   var chains = this._chains, node;
2744   if (!chains) { chains = this._chains = {}; }
2745
2746   node = chains[key];
2747   if (!node) { node = chains[key] = new ChainNode(this, key, src); }
2748   node.count++; // count chains...
2749
2750   // chain rest of path if there is one
2751   if (path && path.length>0) {
2752     key = firstKey(path);
2753     path = path.slice(key.length+1);
2754     node.chain(key, path); // NOTE: no src means it will observe changes...
2755   }
2756 };
2757
2758 ChainNodePrototype.unchain = function(key, path) {
2759   var chains = this._chains, node = chains[key];
2760
2761   // unchain rest of path first...
2762   if (path && path.length>1) {
2763     key  = firstKey(path);
2764     path = path.slice(key.length+1);
2765     node.unchain(key, path);
2766   }
2767
2768   // delete node if needed.
2769   node.count--;
2770   if (node.count<=0) {
2771     delete chains[node._key];
2772     node.destroy();
2773   }
2774
2775 };
2776
2777 ChainNodePrototype.willChange = function() {
2778   var chains = this._chains;
2779   if (chains) {
2780     for(var key in chains) {
2781       if (!chains.hasOwnProperty(key)) { continue; }
2782       chains[key].willChange();
2783     }
2784   }
2785
2786   if (this._parent) { this._parent.chainWillChange(this, this._key, 1); }
2787 };
2788
2789 ChainNodePrototype.chainWillChange = function(chain, path, depth) {
2790   if (this._key) { path = this._key + '.' + path; }
2791
2792   if (this._parent) {
2793     this._parent.chainWillChange(this, path, depth+1);
2794   } else {
2795     if (depth > 1) { Ember.propertyWillChange(this.value(), path); }
2796     path = 'this.' + path;
2797     if (this._paths[path] > 0) { Ember.propertyWillChange(this.value(), path); }
2798   }
2799 };
2800
2801 ChainNodePrototype.chainDidChange = function(chain, path, depth) {
2802   if (this._key) { path = this._key + '.' + path; }
2803   if (this._parent) {
2804     this._parent.chainDidChange(this, path, depth+1);
2805   } else {
2806     if (depth > 1) { Ember.propertyDidChange(this.value(), path); }
2807     path = 'this.' + path;
2808     if (this._paths[path] > 0) { Ember.propertyDidChange(this.value(), path); }
2809   }
2810 };
2811
2812 ChainNodePrototype.didChange = function(suppressEvent) {
2813   // invalidate my own value first.
2814   if (this._watching) {
2815     var obj = this._parent.value();
2816     if (obj !== this._object) {
2817       removeChainWatcher(this._object, this._key, this);
2818       this._object = obj;
2819       addChainWatcher(obj, this._key, this);
2820     }
2821     this._value  = undefined;
2822
2823     // Special-case: the EachProxy relies on immediate evaluation to
2824     // establish its observers.
2825     if (this._parent && this._parent._key === '@each')
2826       this.value();
2827   }
2828
2829   // then notify chains...
2830   var chains = this._chains;
2831   if (chains) {
2832     for(var key in chains) {
2833       if (!chains.hasOwnProperty(key)) { continue; }
2834       chains[key].didChange(suppressEvent);
2835     }
2836   }
2837
2838   if (suppressEvent) { return; }
2839
2840   // and finally tell parent about my path changing...
2841   if (this._parent) { this._parent.chainDidChange(this, this._key, 1); }
2842 };
2843
2844 // get the chains for the current object. If the current object has
2845 // chains inherited from the proto they will be cloned and reconfigured for
2846 // the current object.
2847 function chainsFor(obj) {
2848   var m = metaFor(obj), ret = m.chains;
2849   if (!ret) {
2850     ret = m.chains = new ChainNode(null, null, obj);
2851   } else if (ret.value() !== obj) {
2852     ret = m.chains = ret.copy(obj);
2853   }
2854   return ret;
2855 }
2856
2857 Ember.overrideChains = function(obj, keyName, m) {
2858   chainsDidChange(obj, keyName, m, true);
2859 };
2860
2861 function chainsWillChange(obj, keyName, m, arg) {
2862   if (!m.hasOwnProperty('chainWatchers')) { return; } // nothing to do
2863
2864   var nodes = m.chainWatchers;
2865
2866   nodes = nodes[keyName];
2867   if (!nodes) { return; }
2868
2869   for(var i = 0, l = nodes.length; i < l; i++) {
2870     nodes[i].willChange(arg);
2871   }
2872 }
2873
2874 function chainsDidChange(obj, keyName, m, arg) {
2875   if (!m.hasOwnProperty('chainWatchers')) { return; } // nothing to do
2876
2877   var nodes = m.chainWatchers;
2878
2879   nodes = nodes[keyName];
2880   if (!nodes) { return; }
2881
2882   // looping in reverse because the chainWatchers array can be modified inside didChange
2883   for (var i = nodes.length - 1; i >= 0; i--) {
2884     nodes[i].didChange(arg);
2885   }
2886 }
2887
2888 // ..........................................................
2889 // WATCH
2890 //
2891
2892 /**
2893   @private
2894
2895   Starts watching a property on an object. Whenever the property changes,
2896   invokes `Ember.propertyWillChange` and `Ember.propertyDidChange`. This is the
2897   primitive used by observers and dependent keys; usually you will never call
2898   this method directly but instead use higher level methods like
2899   `Ember.addObserver()`
2900
2901   @method watch
2902   @for Ember
2903   @param obj
2904   @param {String} keyName
2905 */
2906 Ember.watch = function(obj, keyName) {
2907   // can't watch length on Array - it is special...
2908   if (keyName === 'length' && Ember.typeOf(obj) === 'array') { return this; }
2909
2910   var m = metaFor(obj), watching = m.watching, desc;
2911
2912   // activate watching first time
2913   if (!watching[keyName]) {
2914     watching[keyName] = 1;
2915     if (isKeyName(keyName)) {
2916       desc = m.descs[keyName];
2917       if (desc && desc.willWatch) { desc.willWatch(obj, keyName); }
2918
2919       if ('function' === typeof obj.willWatchProperty) {
2920         obj.willWatchProperty(keyName);
2921       }
2922
2923       if (MANDATORY_SETTER && keyName in obj) {
2924         m.values[keyName] = obj[keyName];
2925         o_defineProperty(obj, keyName, {
2926           configurable: true,
2927           enumerable: true,
2928           set: function() {
2929             Ember.assert('Must use Ember.set() to access this property', false);
2930           },
2931           get: function() {
2932             var meta = this[META_KEY];
2933             return meta && meta.values[keyName];
2934           }
2935         });
2936       }
2937     } else {
2938       chainsFor(obj).add(keyName);
2939     }
2940
2941   }  else {
2942     watching[keyName] = (watching[keyName] || 0) + 1;
2943   }
2944   return this;
2945 };
2946
2947 Ember.isWatching = function isWatching(obj, key) {
2948   var meta = obj[META_KEY];
2949   return (meta && meta.watching[key]) > 0;
2950 };
2951
2952 Ember.watch.flushPending = flushPendingChains;
2953
2954 Ember.unwatch = function(obj, keyName) {
2955   // can't watch length on Array - it is special...
2956   if (keyName === 'length' && Ember.typeOf(obj) === 'array') { return this; }
2957
2958   var m = metaFor(obj), watching = m.watching, desc;
2959
2960   if (watching[keyName] === 1) {
2961     watching[keyName] = 0;
2962
2963     if (isKeyName(keyName)) {
2964       desc = m.descs[keyName];
2965       if (desc && desc.didUnwatch) { desc.didUnwatch(obj, keyName); }
2966
2967       if ('function' === typeof obj.didUnwatchProperty) {
2968         obj.didUnwatchProperty(keyName);
2969       }
2970
2971       if (MANDATORY_SETTER && keyName in obj) {
2972         o_defineProperty(obj, keyName, {
2973           configurable: true,
2974           enumerable: true,
2975           writable: true,
2976           value: m.values[keyName]
2977         });
2978         delete m.values[keyName];
2979       }
2980     } else {
2981       chainsFor(obj).remove(keyName);
2982     }
2983
2984   } else if (watching[keyName]>1) {
2985     watching[keyName]--;
2986   }
2987
2988   return this;
2989 };
2990
2991 /**
2992   @private
2993
2994   Call on an object when you first beget it from another object. This will
2995   setup any chained watchers on the object instance as needed. This method is
2996   safe to call multiple times.
2997
2998   @method rewatch
2999   @for Ember
3000   @param obj
3001 */
3002 Ember.rewatch = function(obj) {
3003   var m = metaFor(obj, false), chains = m.chains;
3004
3005   // make sure the object has its own guid.
3006   if (GUID_KEY in obj && !obj.hasOwnProperty(GUID_KEY)) {
3007     Ember.generateGuid(obj, 'ember');
3008   }
3009
3010   // make sure any chained watchers update.
3011   if (chains && chains.value() !== obj) {
3012     m.chains = chains.copy(obj);
3013   }
3014
3015   return this;
3016 };
3017
3018 Ember.finishChains = function(obj) {
3019   var m = metaFor(obj, false), chains = m.chains;
3020   if (chains) {
3021     if (chains.value() !== obj) {
3022       m.chains = chains = chains.copy(obj);
3023     }
3024     chains.didChange(true);
3025   }
3026 };
3027
3028 // ..........................................................
3029 // PROPERTY CHANGES
3030 //
3031
3032 /**
3033   This function is called just before an object property is about to change.
3034   It will notify any before observers and prepare caches among other things.
3035
3036   Normally you will not need to call this method directly but if for some
3037   reason you can't directly watch a property you can invoke this method
3038   manually along with `Ember.propertyDidChange()` which you should call just
3039   after the property value changes.
3040
3041   @method propertyWillChange
3042   @for Ember
3043   @param {Object} obj The object with the property that will change
3044   @param {String} keyName The property key (or path) that will change.
3045   @return {void}
3046 */
3047 function propertyWillChange(obj, keyName, value) {
3048   var m = metaFor(obj, false),
3049       watching = m.watching[keyName] > 0 || keyName === 'length',
3050       proto = m.proto,
3051       desc = m.descs[keyName];
3052
3053   if (!watching) { return; }
3054   if (proto === obj) { return; }
3055   if (desc && desc.willChange) { desc.willChange(obj, keyName); }
3056   dependentKeysWillChange(obj, keyName, m);
3057   chainsWillChange(obj, keyName, m);
3058   Ember.notifyBeforeObservers(obj, keyName);
3059 }
3060
3061 Ember.propertyWillChange = propertyWillChange;
3062
3063 /**
3064   This function is called just after an object property has changed.
3065   It will notify any observers and clear caches among other things.
3066
3067   Normally you will not need to call this method directly but if for some
3068   reason you can't directly watch a property you can invoke this method
3069   manually along with `Ember.propertyWilLChange()` which you should call just
3070   before the property value changes.
3071
3072   @method propertyDidChange
3073   @for Ember
3074   @param {Object} obj The object with the property that will change
3075   @param {String} keyName The property key (or path) that will change.
3076   @return {void}
3077 */
3078 function propertyDidChange(obj, keyName) {
3079   var m = metaFor(obj, false),
3080       watching = m.watching[keyName] > 0 || keyName === 'length',
3081       proto = m.proto,
3082       desc = m.descs[keyName];
3083
3084   if (proto === obj) { return; }
3085
3086   // shouldn't this mean that we're watching this key?
3087   if (desc && desc.didChange) { desc.didChange(obj, keyName); }
3088   if (!watching && keyName !== 'length') { return; }
3089
3090   dependentKeysDidChange(obj, keyName, m);
3091   chainsDidChange(obj, keyName, m);
3092   Ember.notifyObservers(obj, keyName);
3093 }
3094
3095 Ember.propertyDidChange = propertyDidChange;
3096
3097 var NODE_STACK = [];
3098
3099 /**
3100   Tears down the meta on an object so that it can be garbage collected.
3101   Multiple calls will have no effect.
3102
3103   @method destroy
3104   @for Ember
3105   @param {Object} obj  the object to destroy
3106   @return {void}
3107 */
3108 Ember.destroy = function (obj) {
3109   var meta = obj[META_KEY], node, nodes, key, nodeObject;
3110   if (meta) {
3111     obj[META_KEY] = null;
3112     // remove chainWatchers to remove circular references that would prevent GC
3113     node = meta.chains;
3114     if (node) {
3115       NODE_STACK.push(node);
3116       // process tree
3117       while (NODE_STACK.length > 0) {
3118         node = NODE_STACK.pop();
3119         // push children
3120         nodes = node._chains;
3121         if (nodes) {
3122           for (key in nodes) {
3123             if (nodes.hasOwnProperty(key)) {
3124               NODE_STACK.push(nodes[key]);
3125             }
3126           }
3127         }
3128         // remove chainWatcher in node object
3129         if (node._watching) {
3130           nodeObject = node._object;
3131           if (nodeObject) {
3132             removeChainWatcher(nodeObject, node._key, node);
3133           }
3134         }
3135       }
3136     }
3137   }
3138 };
3139
3140 })();
3141
3142
3143
3144 (function() {
3145 /**
3146 @module ember-metal
3147 */
3148
3149 Ember.warn("The CP_DEFAULT_CACHEABLE flag has been removed and computed properties are always cached by default. Use `volatile` if you don't want caching.", Ember.ENV.CP_DEFAULT_CACHEABLE !== false);
3150
3151
3152 var get = Ember.get,
3153     set = Ember.set,
3154     metaFor = Ember.meta,
3155     guidFor = Ember.guidFor,
3156     a_slice = [].slice,
3157     o_create = Ember.create,
3158     META_KEY = Ember.META_KEY,
3159     watch = Ember.watch,
3160     unwatch = Ember.unwatch;
3161
3162 // ..........................................................
3163 // DEPENDENT KEYS
3164 //
3165
3166 // data structure:
3167 //  meta.deps = {
3168 //   'depKey': {
3169 //     'keyName': count,
3170 //   }
3171 //  }
3172
3173 /*
3174   This function returns a map of unique dependencies for a
3175   given object and key.
3176 */
3177 function keysForDep(obj, depsMeta, depKey) {
3178   var keys = depsMeta[depKey];
3179   if (!keys) {
3180     // if there are no dependencies yet for a the given key
3181     // create a new empty list of dependencies for the key
3182     keys = depsMeta[depKey] = {};
3183   } else if (!depsMeta.hasOwnProperty(depKey)) {
3184     // otherwise if the dependency list is inherited from
3185     // a superclass, clone the hash
3186     keys = depsMeta[depKey] = o_create(keys);
3187   }
3188   return keys;
3189 }
3190
3191 /* return obj[META_KEY].deps */
3192 function metaForDeps(obj, meta) {
3193   var deps = meta.deps;
3194   // If the current object has no dependencies...
3195   if (!deps) {
3196     // initialize the dependencies with a pointer back to
3197     // the current object
3198     deps = meta.deps = {};
3199   } else if (!meta.hasOwnProperty('deps')) {
3200     // otherwise if the dependencies are inherited from the
3201     // object's superclass, clone the deps
3202     deps = meta.deps = o_create(deps);
3203   }
3204   return deps;
3205 }
3206
3207 function addDependentKeys(desc, obj, keyName, meta) {
3208   // the descriptor has a list of dependent keys, so
3209   // add all of its dependent keys.
3210   var depKeys = desc._dependentKeys, depsMeta, idx, len, depKey, keys;
3211   if (!depKeys) return;
3212
3213   depsMeta = metaForDeps(obj, meta);
3214
3215   for(idx = 0, len = depKeys.length; idx < len; idx++) {
3216     depKey = depKeys[idx];
3217     // Lookup keys meta for depKey
3218     keys = keysForDep(obj, depsMeta, depKey);
3219     // Increment the number of times depKey depends on keyName.
3220     keys[keyName] = (keys[keyName] || 0) + 1;
3221     // Watch the depKey
3222     watch(obj, depKey);
3223   }
3224 }
3225
3226 function removeDependentKeys(desc, obj, keyName, meta) {
3227   // the descriptor has a list of dependent keys, so
3228   // add all of its dependent keys.
3229   var depKeys = desc._dependentKeys, depsMeta, idx, len, depKey, keys;
3230   if (!depKeys) return;
3231
3232   depsMeta = metaForDeps(obj, meta);
3233
3234   for(idx = 0, len = depKeys.length; idx < len; idx++) {
3235     depKey = depKeys[idx];
3236     // Lookup keys meta for depKey
3237     keys = keysForDep(obj, depsMeta, depKey);
3238     // Increment the number of times depKey depends on keyName.
3239     keys[keyName] = (keys[keyName] || 0) - 1;
3240     // Watch the depKey
3241     unwatch(obj, depKey);
3242   }
3243 }
3244
3245 // ..........................................................
3246 // COMPUTED PROPERTY
3247 //
3248
3249 /**
3250   @class ComputedProperty
3251   @namespace Ember
3252   @extends Ember.Descriptor
3253   @constructor
3254 */
3255 function ComputedProperty(func, opts) {
3256   this.func = func;
3257   this._cacheable = (opts && opts.cacheable !== undefined) ? opts.cacheable : true;
3258   this._dependentKeys = opts && opts.dependentKeys;
3259 }
3260
3261 Ember.ComputedProperty = ComputedProperty;
3262 ComputedProperty.prototype = new Ember.Descriptor();
3263
3264 var ComputedPropertyPrototype = ComputedProperty.prototype;
3265
3266 /**
3267   Call on a computed property to set it into cacheable mode. When in this
3268   mode the computed property will automatically cache the return value of
3269   your function until one of the dependent keys changes.
3270
3271   ```javascript
3272   MyApp.president = Ember.Object.create({
3273     fullName: function() {
3274       return this.get('firstName') + ' ' + this.get('lastName');
3275
3276       // After calculating the value of this function, Ember will
3277       // return that value without re-executing this function until
3278       // one of the dependent properties change.
3279     }.property('firstName', 'lastName')
3280   });
3281   ```
3282
3283   Properties are cacheable by default.
3284
3285   @method cacheable
3286   @param {Boolean} aFlag optional set to `false` to disable caching
3287   @chainable
3288 */
3289 ComputedPropertyPrototype.cacheable = function(aFlag) {
3290   this._cacheable = aFlag !== false;
3291   return this;
3292 };
3293
3294 /**
3295   Call on a computed property to set it into non-cached mode. When in this
3296   mode the computed property will not automatically cache the return value.
3297
3298   ```javascript
3299   MyApp.outsideService = Ember.Object.create({
3300     value: function() {
3301       return OutsideService.getValue();
3302     }.property().volatile()
3303   });
3304   ```
3305
3306   @method volatile
3307   @chainable
3308 */
3309 ComputedPropertyPrototype.volatile = function() {
3310   return this.cacheable(false);
3311 };
3312
3313 /**
3314   Sets the dependent keys on this computed property. Pass any number of
3315   arguments containing key paths that this computed property depends on.
3316
3317   ```javascript
3318   MyApp.president = Ember.Object.create({
3319     fullName: Ember.computed(function() {
3320       return this.get('firstName') + ' ' + this.get('lastName');
3321
3322       // Tell Ember that this computed property depends on firstName
3323       // and lastName
3324     }).property('firstName', 'lastName')
3325   });
3326   ```
3327
3328   @method property
3329   @param {String} path* zero or more property paths
3330   @chainable
3331 */
3332 ComputedPropertyPrototype.property = function() {
3333   var args = [];
3334   for (var i = 0, l = arguments.length; i < l; i++) {
3335     args.push(arguments[i]);
3336   }
3337   this._dependentKeys = args;
3338   return this;
3339 };
3340
3341 /**
3342   In some cases, you may want to annotate computed properties with additional
3343   metadata about how they function or what values they operate on. For example,
3344   computed property functions may close over variables that are then no longer
3345   available for introspection.
3346
3347   You can pass a hash of these values to a computed property like this:
3348
3349   ```
3350   person: function() {
3351     var personId = this.get('personId');
3352     return App.Person.create({ id: personId });
3353   }.property().meta({ type: App.Person })
3354   ```
3355
3356   The hash that you pass to the `meta()` function will be saved on the
3357   computed property descriptor under the `_meta` key. Ember runtime
3358   exposes a public API for retrieving these values from classes,
3359   via the `metaForProperty()` function.
3360
3361   @method meta
3362   @param {Hash} meta
3363   @chainable
3364 */
3365
3366 ComputedPropertyPrototype.meta = function(meta) {
3367   if (arguments.length === 0) {
3368     return this._meta || {};
3369   } else {
3370     this._meta = meta;
3371     return this;
3372   }
3373 };
3374
3375 /* impl descriptor API */
3376 ComputedPropertyPrototype.willWatch = function(obj, keyName) {
3377   // watch already creates meta for this instance
3378   var meta = obj[META_KEY];
3379   Ember.assert('watch should have setup meta to be writable', meta.source === obj);
3380   if (!(keyName in meta.cache)) {
3381     addDependentKeys(this, obj, keyName, meta);
3382   }
3383 };
3384
3385 ComputedPropertyPrototype.didUnwatch = function(obj, keyName) {
3386   var meta = obj[META_KEY];
3387   Ember.assert('unwatch should have setup meta to be writable', meta.source === obj);
3388   if (!(keyName in meta.cache)) {
3389     // unwatch already creates meta for this instance
3390     removeDependentKeys(this, obj, keyName, meta);
3391   }
3392 };
3393
3394 /* impl descriptor API */
3395 ComputedPropertyPrototype.didChange = function(obj, keyName) {
3396   // _suspended is set via a CP.set to ensure we don't clear
3397   // the cached value set by the setter
3398   if (this._cacheable && this._suspended !== obj) {
3399     var meta = metaFor(obj);
3400     if (keyName in meta.cache) {
3401       delete meta.cache[keyName];
3402       if (!meta.watching[keyName]) {
3403         removeDependentKeys(this, obj, keyName, meta);
3404       }
3405     }
3406   }
3407 };
3408
3409 /* impl descriptor API */
3410 ComputedPropertyPrototype.get = function(obj, keyName) {
3411   var ret, cache, meta;
3412   if (this._cacheable) {
3413     meta = metaFor(obj);
3414     cache = meta.cache;
3415     if (keyName in cache) { return cache[keyName]; }
3416     ret = cache[keyName] = this.func.call(obj, keyName);
3417     if (!meta.watching[keyName]) {
3418       addDependentKeys(this, obj, keyName, meta);
3419     }
3420   } else {
3421     ret = this.func.call(obj, keyName);
3422   }
3423   return ret;
3424 };
3425
3426 /* impl descriptor API */
3427 ComputedPropertyPrototype.set = function(obj, keyName, value) {
3428   var cacheable = this._cacheable,
3429       func = this.func,
3430       meta = metaFor(obj, cacheable),
3431       watched = meta.watching[keyName],
3432       oldSuspended = this._suspended,
3433       hadCachedValue = false,
3434       cache = meta.cache,
3435       cachedValue, ret;
3436
3437   this._suspended = obj;
3438
3439   try {
3440     if (cacheable && cache.hasOwnProperty(keyName)) {
3441       cachedValue = cache[keyName];
3442       hadCachedValue = true;
3443     }
3444
3445     // Check if the CP has been wrapped
3446     if (func.wrappedFunction) { func = func.wrappedFunction; }
3447
3448     // For backwards-compatibility with computed properties
3449     // that check for arguments.length === 2 to determine if
3450     // they are being get or set, only pass the old cached
3451     // value if the computed property opts into a third
3452     // argument.
3453     if (func.length === 3) {
3454       ret = func.call(obj, keyName, value, cachedValue);
3455     } else if (func.length === 2) {
3456       ret = func.call(obj, keyName, value);
3457     } else {
3458       Ember.defineProperty(obj, keyName, null, cachedValue);
3459       Ember.set(obj, keyName, value);
3460       return;
3461     }
3462
3463     if (hadCachedValue && cachedValue === ret) { return; }
3464
3465     if (watched) { Ember.propertyWillChange(obj, keyName); }
3466
3467     if (hadCachedValue) {
3468       delete cache[keyName];
3469     }
3470
3471     if (cacheable) {
3472       if (!watched && !hadCachedValue) {
3473         addDependentKeys(this, obj, keyName, meta);
3474       }
3475       cache[keyName] = ret;
3476     }
3477
3478     if (watched) { Ember.propertyDidChange(obj, keyName); }
3479   } finally {
3480     this._suspended = oldSuspended;
3481   }
3482   return ret;
3483 };
3484
3485 /* called when property is defined */
3486 ComputedPropertyPrototype.setup = function(obj, keyName) {
3487   var meta = obj[META_KEY];
3488   if (meta && meta.watching[keyName]) {
3489     addDependentKeys(this, obj, keyName, metaFor(obj));
3490   }
3491 };
3492
3493 /* called before property is overridden */
3494 ComputedPropertyPrototype.teardown = function(obj, keyName) {
3495   var meta = metaFor(obj);
3496
3497   if (meta.watching[keyName] || keyName in meta.cache) {
3498     removeDependentKeys(this, obj, keyName, meta);
3499   }
3500
3501   if (this._cacheable) { delete meta.cache[keyName]; }
3502
3503   return null; // no value to restore
3504 };
3505
3506
3507 /**
3508   This helper returns a new property descriptor that wraps the passed
3509   computed property function. You can use this helper to define properties
3510   with mixins or via `Ember.defineProperty()`.
3511
3512   The function you pass will be used to both get and set property values.
3513   The function should accept two parameters, key and value. If value is not
3514   undefined you should set the value first. In either case return the
3515   current value of the property.
3516
3517   @method computed
3518   @for Ember
3519   @param {Function} func The computed property function.
3520   @return {Ember.ComputedProperty} property descriptor instance
3521 */
3522 Ember.computed = function(func) {
3523   var args;
3524
3525   if (arguments.length > 1) {
3526     args = a_slice.call(arguments, 0, -1);
3527     func = a_slice.call(arguments, -1)[0];
3528   }
3529
3530   var cp = new ComputedProperty(func);
3531
3532   if (args) {
3533     cp.property.apply(cp, args);
3534   }
3535
3536   return cp;
3537 };
3538
3539 /**
3540   Returns the cached value for a property, if one exists.
3541   This can be useful for peeking at the value of a computed
3542   property that is generated lazily, without accidentally causing
3543   it to be created.
3544
3545   @method cacheFor
3546   @for Ember
3547   @param {Object} obj the object whose property you want to check
3548   @param {String} key the name of the property whose cached value you want
3549     to return
3550 */
3551 Ember.cacheFor = function cacheFor(obj, key) {
3552   var cache = metaFor(obj, false).cache;
3553
3554   if (cache && key in cache) {
3555     return cache[key];
3556   }
3557 };
3558
3559 /**
3560   @method computed.not
3561   @for Ember
3562   @param {String} dependentKey
3563 */
3564 Ember.computed.not = function(dependentKey) {
3565   return Ember.computed(dependentKey, function(key) {
3566     return !get(this, dependentKey);
3567   });
3568 };
3569
3570 /**
3571   @method computed.empty
3572   @for Ember
3573   @param {String} dependentKey
3574 */
3575 Ember.computed.empty = function(dependentKey) {
3576   return Ember.computed(dependentKey, function(key) {
3577     var val = get(this, dependentKey);
3578     return val === undefined || val === null || val === '' || (Ember.isArray(val) && get(val, 'length') === 0);
3579   });
3580 };
3581
3582 /**
3583   @method computed.bool
3584   @for Ember
3585   @param {String} dependentKey
3586 */
3587 Ember.computed.bool = function(dependentKey) {
3588   return Ember.computed(dependentKey, function(key) {
3589     return !!get(this, dependentKey);
3590   });
3591 };
3592
3593 /**
3594   @method computed.alias
3595   @for Ember
3596   @param {String} dependentKey
3597 */
3598 Ember.computed.alias = function(dependentKey) {
3599   return Ember.computed(dependentKey, function(key, value){
3600     if (arguments.length === 1) {
3601       return get(this, dependentKey);
3602     } else {
3603       set(this, dependentKey, value);
3604       return value;
3605     }
3606   });
3607 };
3608
3609 })();
3610
3611
3612
3613 (function() {
3614 /**
3615 @module ember-metal
3616 */
3617
3618 var o_create = Ember.create,
3619     metaFor = Ember.meta,
3620     metaPath = Ember.metaPath,
3621     META_KEY = Ember.META_KEY;
3622
3623 /*
3624   The event system uses a series of nested hashes to store listeners on an
3625   object. When a listener is registered, or when an event arrives, these
3626   hashes are consulted to determine which target and action pair to invoke.
3627
3628   The hashes are stored in the object's meta hash, and look like this:
3629
3630       // Object's meta hash
3631       {
3632         listeners: {       // variable name: `listenerSet`
3633           "foo:changed": [ // variable name: `actions`
3634             [target, method, onceFlag, suspendedFlag]
3635           ]
3636         }
3637       }
3638
3639 */
3640
3641 function indexOf(array, target, method) {
3642   var index = -1;
3643   for (var i = 0, l = array.length; i < l; i++) {
3644     if (target === array[i][0] && method === array[i][1]) { index = i; break; }
3645   }
3646   return index;
3647 }
3648
3649 function actionsFor(obj, eventName) {
3650   var meta = metaFor(obj, true),
3651       actions;
3652
3653   if (!meta.listeners) { meta.listeners = {}; }
3654
3655   if (!meta.hasOwnProperty('listeners')) {
3656     // setup inherited copy of the listeners object
3657     meta.listeners = o_create(meta.listeners);
3658   }
3659
3660   actions = meta.listeners[eventName];
3661
3662   // if there are actions, but the eventName doesn't exist in our listeners, then copy them from the prototype
3663   if (actions && !meta.listeners.hasOwnProperty(eventName)) {
3664     actions = meta.listeners[eventName] = meta.listeners[eventName].slice();
3665   } else if (!actions) {
3666     actions = meta.listeners[eventName] = [];
3667   }
3668
3669   return actions;
3670 }
3671
3672 function actionsUnion(obj, eventName, otherActions) {
3673   var meta = obj[META_KEY],
3674       actions = meta && meta.listeners && meta.listeners[eventName];
3675
3676   if (!actions) { return; }
3677   for (var i = actions.length - 1; i >= 0; i--) {
3678     var target = actions[i][0],
3679         method = actions[i][1],
3680         once = actions[i][2],
3681         suspended = actions[i][3],
3682         actionIndex = indexOf(otherActions, target, method);
3683
3684     if (actionIndex === -1) {
3685       otherActions.push([target, method, once, suspended]);
3686     }
3687   }
3688 }
3689
3690 function actionsDiff(obj, eventName, otherActions) {
3691   var meta = obj[META_KEY],
3692       actions = meta && meta.listeners && meta.listeners[eventName],
3693       diffActions = [];
3694
3695   if (!actions) { return; }
3696   for (var i = actions.length - 1; i >= 0; i--) {
3697     var target = actions[i][0],
3698         method = actions[i][1],
3699         once = actions[i][2],
3700         suspended = actions[i][3],
3701         actionIndex = indexOf(otherActions, target, method);
3702
3703     if (actionIndex !== -1) { continue; }
3704
3705     otherActions.push([target, method, once, suspended]);
3706     diffActions.push([target, method, once, suspended]);
3707   }
3708
3709   return diffActions;
3710 }
3711
3712 /**
3713   Add an event listener
3714
3715   @method addListener
3716   @for Ember
3717   @param obj
3718   @param {String} eventName
3719   @param {Object|Function} targetOrMethod A target object or a function
3720   @param {Function|String} method A function or the name of a function to be called on `target`
3721 */
3722 function addListener(obj, eventName, target, method, once) {
3723   Ember.assert("You must pass at least an object and event name to Ember.addListener", !!obj && !!eventName);
3724
3725   if (!method && 'function' === typeof target) {
3726     method = target;
3727     target = null;
3728   }
3729
3730   var actions = actionsFor(obj, eventName),
3731       actionIndex = indexOf(actions, target, method);
3732
3733   if (actionIndex !== -1) { return; }
3734
3735   actions.push([target, method, once, undefined]);
3736
3737   if ('function' === typeof obj.didAddListener) {
3738     obj.didAddListener(eventName, target, method);
3739   }
3740 }
3741
3742 /**
3743   Remove an event listener
3744
3745   Arguments should match those passed to {{#crossLink "Ember/addListener"}}{{/crossLink}}
3746
3747   @method removeListener
3748   @for Ember
3749   @param obj
3750   @param {String} eventName
3751   @param {Object|Function} targetOrMethod A target object or a function
3752   @param {Function|String} method A function or the name of a function to be called on `target`
3753 */
3754 function removeListener(obj, eventName, target, method) {
3755   Ember.assert("You must pass at least an object and event name to Ember.removeListener", !!obj && !!eventName);
3756
3757   if (!method && 'function' === typeof target) {
3758     method = target;
3759     target = null;
3760   }
3761
3762   function _removeListener(target, method, once) {
3763     var actions = actionsFor(obj, eventName),
3764         actionIndex = indexOf(actions, target, method);
3765
3766     // action doesn't exist, give up silently
3767     if (actionIndex === -1) { return; }
3768
3769     actions.splice(actionIndex, 1);
3770
3771     if ('function' === typeof obj.didRemoveListener) {
3772       obj.didRemoveListener(eventName, target, method);
3773     }
3774   }
3775
3776   if (method) {
3777     _removeListener(target, method);
3778   } else {
3779     var meta = obj[META_KEY],
3780         actions = meta && meta.listeners && meta.listeners[eventName];
3781
3782     if (!actions) { return; }
3783     for (var i = actions.length - 1; i >= 0; i--) {
3784       _removeListener(actions[i][0], actions[i][1]);
3785     }
3786   }
3787 }
3788
3789 /**
3790   @private
3791
3792   Suspend listener during callback.
3793
3794   This should only be used by the target of the event listener
3795   when it is taking an action that would cause the event, e.g.
3796   an object might suspend its property change listener while it is
3797   setting that property.
3798
3799   @method suspendListener
3800   @for Ember
3801   @param obj
3802   @param {String} eventName
3803   @param {Object|Function} targetOrMethod A target object or a function
3804   @param {Function|String} method A function or the name of a function to be called on `target`
3805   @param {Function} callback
3806 */
3807 function suspendListener(obj, eventName, target, method, callback) {
3808   if (!method && 'function' === typeof target) {
3809     method = target;
3810     target = null;
3811   }
3812
3813   var actions = actionsFor(obj, eventName),
3814       actionIndex = indexOf(actions, target, method),
3815       action;
3816
3817   if (actionIndex !== -1) {
3818     action = actions[actionIndex].slice(); // copy it, otherwise we're modifying a shared object
3819     action[3] = true; // mark the action as suspended
3820     actions[actionIndex] = action; // replace the shared object with our copy
3821   }
3822
3823   function tryable()   { return callback.call(target); }
3824   function finalizer() { if (action) { action[3] = undefined; } }
3825
3826   return Ember.tryFinally(tryable, finalizer);
3827 }
3828
3829 /**
3830   @private
3831
3832   Suspend listener during callback.
3833
3834   This should only be used by the target of the event listener
3835   when it is taking an action that would cause the event, e.g.
3836   an object might suspend its property change listener while it is
3837   setting that property.
3838
3839   @method suspendListener
3840   @for Ember
3841   @param obj
3842   @param {Array} eventName Array of event names
3843   @param {Object|Function} targetOrMethod A target object or a function
3844   @param {Function|String} method A function or the name of a function to be called on `target`
3845   @param {Function} callback
3846 */
3847 function suspendListeners(obj, eventNames, target, method, callback) {
3848   if (!method && 'function' === typeof target) {
3849     method = target;
3850     target = null;
3851   }
3852
3853   var suspendedActions = [],
3854       eventName, actions, action, i, l;
3855
3856   for (i=0, l=eventNames.length; i<l; i++) {
3857     eventName = eventNames[i];
3858     actions = actionsFor(obj, eventName);
3859     var actionIndex = indexOf(actions, target, method);
3860
3861     if (actionIndex !== -1) {
3862       action = actions[actionIndex].slice();
3863       action[3] = true;
3864       actions[actionIndex] = action;
3865       suspendedActions.push(action);
3866     }
3867   }
3868
3869   function tryable() { return callback.call(target); }
3870
3871   function finalizer() {
3872     for (i = 0, l = suspendedActions.length; i < l; i++) {
3873       suspendedActions[i][3] = undefined;
3874     }
3875   }
3876
3877   return Ember.tryFinally(tryable, finalizer);
3878 }
3879
3880 /**
3881   @private
3882
3883   Return a list of currently watched events
3884
3885   @method watchedEvents
3886   @for Ember
3887   @param obj
3888 */
3889 function watchedEvents(obj) {
3890   var listeners = obj[META_KEY].listeners, ret = [];
3891
3892   if (listeners) {
3893     for(var eventName in listeners) {
3894       if (listeners[eventName]) { ret.push(eventName); }
3895     }
3896   }
3897   return ret;
3898 }
3899
3900 /**
3901   @method sendEvent
3902   @for Ember
3903   @param obj
3904   @param {String} eventName
3905   @param {Array} params
3906   @return true
3907 */
3908 function sendEvent(obj, eventName, params, actions) {
3909   // first give object a chance to handle it
3910   if (obj !== Ember && 'function' === typeof obj.sendEvent) {
3911     obj.sendEvent(eventName, params);
3912   }
3913
3914   if (!actions) {
3915     var meta = obj[META_KEY];
3916     actions = meta && meta.listeners && meta.listeners[eventName];
3917   }
3918
3919   if (!actions) { return; }
3920
3921   for (var i = actions.length - 1; i >= 0; i--) { // looping in reverse for once listeners
3922     if (!actions[i] || actions[i][3] === true) { continue; }
3923
3924     var target = actions[i][0],
3925         method = actions[i][1],
3926         once = actions[i][2];
3927
3928     if (once) { removeListener(obj, eventName, target, method); }
3929     if (!target) { target = obj; }
3930     if ('string' === typeof method) { method = target[method]; }
3931     if (params) {
3932       method.apply(target, params);
3933     } else {
3934       method.apply(target);
3935     }
3936   }
3937   return true;
3938 }
3939
3940 /**
3941   @private
3942   @method hasListeners
3943   @for Ember
3944   @param obj
3945   @param {String} eventName
3946 */
3947 function hasListeners(obj, eventName) {
3948   var meta = obj[META_KEY],
3949       actions = meta && meta.listeners && meta.listeners[eventName];
3950
3951   return !!(actions && actions.length);
3952 }
3953
3954 /**
3955   @private
3956   @method listenersFor
3957   @for Ember
3958   @param obj
3959   @param {String} eventName
3960 */
3961 function listenersFor(obj, eventName) {
3962   var ret = [];
3963   var meta = obj[META_KEY],
3964       actions = meta && meta.listeners && meta.listeners[eventName];
3965
3966   if (!actions) { return ret; }
3967
3968   for (var i = 0, l = actions.length; i < l; i++) {
3969     var target = actions[i][0],
3970         method = actions[i][1];
3971     ret.push([target, method]);
3972   }
3973
3974   return ret;
3975 }
3976
3977 Ember.addListener = addListener;
3978 Ember.removeListener = removeListener;
3979 Ember._suspendListener = suspendListener;
3980 Ember._suspendListeners = suspendListeners;
3981 Ember.sendEvent = sendEvent;
3982 Ember.hasListeners = hasListeners;
3983 Ember.watchedEvents = watchedEvents;
3984 Ember.listenersFor = listenersFor;
3985 Ember.listenersDiff = actionsDiff;
3986 Ember.listenersUnion = actionsUnion;
3987
3988 })();
3989
3990
3991
3992 (function() {
3993 // Ember.Logger
3994 // Ember.watch.flushPending
3995 // Ember.beginPropertyChanges, Ember.endPropertyChanges
3996 // Ember.guidFor, Ember.tryFinally
3997
3998 /**
3999 @module ember-metal
4000 */
4001
4002 // ..........................................................
4003 // HELPERS
4004 //
4005
4006 var slice = [].slice,
4007     forEach = Ember.ArrayPolyfills.forEach;
4008
4009 // invokes passed params - normalizing so you can pass target/func,
4010 // target/string or just func
4011 function invoke(target, method, args, ignore) {
4012
4013   if (method === undefined) {
4014     method = target;
4015     target = undefined;
4016   }
4017
4018   if ('string' === typeof method) { method = target[method]; }
4019   if (args && ignore > 0) {
4020     args = args.length > ignore ? slice.call(args, ignore) : null;
4021   }
4022
4023   return Ember.handleErrors(function() {
4024     // IE8's Function.prototype.apply doesn't accept undefined/null arguments.
4025     return method.apply(target || this, args || []);
4026   }, this);
4027 }
4028
4029
4030 // ..........................................................
4031 // RUNLOOP
4032 //
4033
4034 var timerMark; // used by timers...
4035
4036 /**
4037 Ember RunLoop (Private)
4038
4039 @class RunLoop
4040 @namespace Ember
4041 @private
4042 @constructor
4043 */
4044 var RunLoop = function(prev) {
4045   this._prev = prev || null;
4046   this.onceTimers = {};
4047 };
4048
4049 RunLoop.prototype = {
4050   /**
4051     @method end
4052   */
4053   end: function() {
4054     this.flush();
4055   },
4056
4057   /**
4058     @method prev
4059   */
4060   prev: function() {
4061     return this._prev;
4062   },
4063
4064   // ..........................................................
4065   // Delayed Actions
4066   //
4067
4068   /**
4069     @method schedule
4070     @param {String} queueName
4071     @param target
4072     @param method
4073   */
4074   schedule: function(queueName, target, method) {
4075     var queues = this._queues, queue;
4076     if (!queues) { queues = this._queues = {}; }
4077     queue = queues[queueName];
4078     if (!queue) { queue = queues[queueName] = []; }
4079
4080     var args = arguments.length > 3 ? slice.call(arguments, 3) : null;
4081     queue.push({ target: target, method: method, args: args });
4082     return this;
4083   },
4084
4085   /**
4086     @method flush
4087     @param {String} queueName
4088   */
4089   flush: function(queueName) {
4090     var queueNames, idx, len, queue, log;
4091
4092     if (!this._queues) { return this; } // nothing to do
4093
4094     function iter(item) {
4095       invoke(item.target, item.method, item.args);
4096     }
4097
4098     function tryable() {
4099       forEach.call(queue, iter);
4100     }
4101
4102     Ember.watch.flushPending(); // make sure all chained watchers are setup
4103
4104     if (queueName) {
4105       while (this._queues && (queue = this._queues[queueName])) {
4106         this._queues[queueName] = null;
4107
4108         // the sync phase is to allow property changes to propagate. don't
4109         // invoke observers until that is finished.
4110         if (queueName === 'sync') {
4111           log = Ember.LOG_BINDINGS;
4112           if (log) { Ember.Logger.log('Begin: Flush Sync Queue'); }
4113
4114           Ember.beginPropertyChanges();
4115
4116           Ember.tryFinally(tryable, Ember.endPropertyChanges);
4117
4118           if (log) { Ember.Logger.log('End: Flush Sync Queue'); }
4119
4120         } else {
4121           forEach.call(queue, iter);
4122         }
4123       }
4124
4125     } else {
4126       queueNames = Ember.run.queues;
4127       len = queueNames.length;
4128       idx = 0;
4129
4130       outerloop:
4131       while (idx < len) {
4132         queueName = queueNames[idx];
4133         queue = this._queues && this._queues[queueName];
4134         delete this._queues[queueName];
4135
4136         if (queue) {
4137           // the sync phase is to allow property changes to propagate. don't
4138           // invoke observers until that is finished.
4139           if (queueName === 'sync') {
4140             log = Ember.LOG_BINDINGS;
4141             if (log) { Ember.Logger.log('Begin: Flush Sync Queue'); }
4142
4143             Ember.beginPropertyChanges();
4144
4145             Ember.tryFinally(tryable, Ember.endPropertyChanges);
4146
4147             if (log) { Ember.Logger.log('End: Flush Sync Queue'); }
4148           } else {
4149             forEach.call(queue, iter);
4150           }
4151         }
4152
4153         // Loop through prior queues
4154         for (var i = 0; i <= idx; i++) {
4155           if (this._queues && this._queues[queueNames[i]]) {
4156             // Start over at the first queue with contents
4157             idx = i;
4158             continue outerloop;
4159           }
4160         }
4161
4162         idx++;
4163       }
4164     }
4165
4166     timerMark = null;
4167
4168     return this;
4169   }
4170
4171 };
4172
4173 Ember.RunLoop = RunLoop;
4174
4175 // ..........................................................
4176 // Ember.run - this is ideally the only public API the dev sees
4177 //
4178
4179 /**
4180   Runs the passed target and method inside of a RunLoop, ensuring any
4181   deferred actions including bindings and views updates are flushed at the
4182   end.
4183
4184   Normally you should not need to invoke this method yourself. However if
4185   you are implementing raw event handlers when interfacing with other
4186   libraries or plugins, you should probably wrap all of your code inside this
4187   call.
4188
4189   ```javascript
4190   Ember.run(function(){
4191     // code to be execute within a RunLoop 
4192   });
4193   ```
4194
4195   @class run
4196   @namespace Ember
4197   @static
4198   @constructor
4199   @param {Object} [target] target of method to call
4200   @param {Function|String} method Method to invoke.
4201     May be a function or a string. If you pass a string
4202     then it will be looked up on the passed target.
4203   @param {Object} [args*] Any additional arguments you wish to pass to the method.
4204   @return {Object} return value from invoking the passed function.
4205 */
4206 Ember.run = function(target, method) {
4207   var loop,
4208   args = arguments;
4209   run.begin();
4210
4211   function tryable() {
4212     if (target || method) {
4213       return invoke(target, method, args, 2);
4214     }
4215   }
4216
4217   return Ember.tryFinally(tryable, run.end);
4218 };
4219
4220 var run = Ember.run;
4221
4222
4223 /**
4224   Begins a new RunLoop. Any deferred actions invoked after the begin will
4225   be buffered until you invoke a matching call to `Ember.run.end()`. This is
4226   an lower-level way to use a RunLoop instead of using `Ember.run()`.
4227
4228   ```javascript
4229   Ember.run.begin();
4230   // code to be execute within a RunLoop 
4231   Ember.run.end();
4232   ```
4233
4234   @method begin
4235   @return {void}
4236 */
4237 Ember.run.begin = function() {
4238   run.currentRunLoop = new RunLoop(run.currentRunLoop);
4239 };
4240
4241 /**
4242   Ends a RunLoop. This must be called sometime after you call
4243   `Ember.run.begin()` to flush any deferred actions. This is a lower-level way
4244   to use a RunLoop instead of using `Ember.run()`.
4245
4246   ```javascript
4247   Ember.run.begin();
4248   // code to be execute within a RunLoop 
4249   Ember.run.end();
4250   ```
4251
4252   @method end
4253   @return {void}
4254 */
4255 Ember.run.end = function() {
4256   Ember.assert('must have a current run loop', run.currentRunLoop);
4257
4258   function tryable()   { run.currentRunLoop.end();  }
4259   function finalizer() { run.currentRunLoop = run.currentRunLoop.prev(); }
4260
4261   Ember.tryFinally(tryable, finalizer);
4262 };
4263
4264 /**
4265   Array of named queues. This array determines the order in which queues
4266   are flushed at the end of the RunLoop. You can define your own queues by
4267   simply adding the queue name to this array. Normally you should not need
4268   to inspect or modify this property.
4269
4270   @property queues
4271   @type Array
4272   @default ['sync', 'actions', 'destroy', 'timers']
4273 */
4274 Ember.run.queues = ['sync', 'actions', 'destroy', 'timers'];
4275
4276 /**
4277   Adds the passed target/method and any optional arguments to the named
4278   queue to be executed at the end of the RunLoop. If you have not already
4279   started a RunLoop when calling this method one will be started for you
4280   automatically.
4281
4282   At the end of a RunLoop, any methods scheduled in this way will be invoked.
4283   Methods will be invoked in an order matching the named queues defined in
4284   the `run.queues` property.
4285
4286   ```javascript
4287   Ember.run.schedule('timers', this, function(){
4288     // this will be executed at the end of the RunLoop, when timers are run
4289     console.log("scheduled on timers queue");
4290   });
4291
4292   Ember.run.schedule('sync', this, function(){
4293     // this will be executed at the end of the RunLoop, when bindings are synced
4294     console.log("scheduled on sync queue");
4295   });
4296
4297   // Note the functions will be run in order based on the run queues order. Output would be:
4298   //   scheduled on sync queue
4299   //   scheduled on timers queue
4300   ```
4301
4302   @method schedule
4303   @param {String} queue The name of the queue to schedule against.
4304     Default queues are 'sync' and 'actions'
4305   @param {Object} [target] target object to use as the context when invoking a method.
4306   @param {String|Function} method The method to invoke. If you pass a string it
4307     will be resolved on the target object at the time the scheduled item is
4308     invoked allowing you to change the target function.
4309   @param {Object} [arguments*] Optional arguments to be passed to the queued method.
4310   @return {void}
4311 */
4312 Ember.run.schedule = function(queue, target, method) {
4313   var loop = run.autorun();
4314   loop.schedule.apply(loop, arguments);
4315 };
4316
4317 var scheduledAutorun;
4318 function autorun() {
4319   scheduledAutorun = null;
4320   if (run.currentRunLoop) { run.end(); }
4321 }
4322
4323 // Used by global test teardown
4324 Ember.run.hasScheduledTimers = function() {
4325   return !!(scheduledAutorun || scheduledLater || scheduledNext);
4326 };
4327
4328 // Used by global test teardown
4329 Ember.run.cancelTimers = function () {
4330   if (scheduledAutorun) {
4331     clearTimeout(scheduledAutorun);
4332     scheduledAutorun = null;
4333   }
4334   if (scheduledLater) {
4335     clearTimeout(scheduledLater);
4336     scheduledLater = null;
4337   }
4338   if (scheduledNext) {
4339     clearTimeout(scheduledNext);
4340     scheduledNext = null;
4341   }
4342   timers = {};
4343 };
4344
4345 /**
4346   Begins a new RunLoop if necessary and schedules a timer to flush the
4347   RunLoop at a later time. This method is used by parts of Ember to
4348   ensure the RunLoop always finishes. You normally do not need to call this
4349   method directly. Instead use `Ember.run()`
4350
4351   @method autorun
4352   @example
4353     Ember.run.autorun();
4354   @return {Ember.RunLoop} the new current RunLoop
4355 */
4356 Ember.run.autorun = function() {
4357   if (!run.currentRunLoop) {
4358     Ember.assert("You have turned on testing mode, which disabled the run-loop's autorun. You will need to wrap any code with asynchronous side-effects in an Ember.run", !Ember.testing);
4359
4360     run.begin();
4361
4362     if (!scheduledAutorun) {
4363       scheduledAutorun = setTimeout(autorun, 1);
4364     }
4365   }
4366
4367   return run.currentRunLoop;
4368 };
4369
4370 /**
4371   Immediately flushes any events scheduled in the 'sync' queue. Bindings
4372   use this queue so this method is a useful way to immediately force all
4373   bindings in the application to sync.
4374
4375   You should call this method anytime you need any changed state to propagate
4376   throughout the app immediately without repainting the UI.
4377
4378   ```javascript
4379   Ember.run.sync();
4380   ```
4381
4382   @method sync
4383   @return {void}
4384 */
4385 Ember.run.sync = function() {
4386   run.autorun();
4387   run.currentRunLoop.flush('sync');
4388 };
4389
4390 // ..........................................................
4391 // TIMERS
4392 //
4393
4394 var timers = {}; // active timers...
4395
4396 var scheduledLater;
4397 function invokeLaterTimers() {
4398   scheduledLater = null;
4399   var now = (+ new Date()), earliest = -1;
4400   for (var key in timers) {
4401     if (!timers.hasOwnProperty(key)) { continue; }
4402     var timer = timers[key];
4403     if (timer && timer.expires) {
4404       if (now >= timer.expires) {
4405         delete timers[key];
4406         invoke(timer.target, timer.method, timer.args, 2);
4407       } else {
4408         if (earliest<0 || (timer.expires < earliest)) earliest=timer.expires;
4409       }
4410     }
4411   }
4412
4413   // schedule next timeout to fire...
4414   if (earliest > 0) { scheduledLater = setTimeout(invokeLaterTimers, earliest-(+ new Date())); }
4415 }
4416
4417 /**
4418   Invokes the passed target/method and optional arguments after a specified
4419   period if time. The last parameter of this method must always be a number
4420   of milliseconds.
4421
4422   You should use this method whenever you need to run some action after a
4423   period of time instead of using `setTimeout()`. This method will ensure that
4424   items that expire during the same script execution cycle all execute
4425   together, which is often more efficient than using a real setTimeout.
4426
4427   ```javascript
4428   Ember.run.later(myContext, function(){
4429     // code here will execute within a RunLoop in about 500ms with this == myContext
4430   }, 500);
4431   ```
4432
4433   @method later
4434   @param {Object} [target] target of method to invoke
4435   @param {Function|String} method The method to invoke.
4436     If you pass a string it will be resolved on the
4437     target at the time the method is invoked.
4438   @param {Object} [args*] Optional arguments to pass to the timeout.
4439   @param {Number} wait
4440     Number of milliseconds to wait.
4441   @return {String} a string you can use to cancel the timer in
4442     {{#crossLink "Ember/run.cancel"}}{{/crossLink}} later.
4443 */
4444 Ember.run.later = function(target, method) {
4445   var args, expires, timer, guid, wait;
4446
4447   // setTimeout compatibility...
4448   if (arguments.length===2 && 'function' === typeof target) {
4449     wait   = method;
4450     method = target;
4451     target = undefined;
4452     args   = [target, method];
4453   } else {
4454     args = slice.call(arguments);
4455     wait = args.pop();
4456   }
4457
4458   expires = (+ new Date()) + wait;
4459   timer   = { target: target, method: method, expires: expires, args: args };
4460   guid    = Ember.guidFor(timer);
4461   timers[guid] = timer;
4462   run.once(timers, invokeLaterTimers);
4463   return guid;
4464 };
4465
4466 function invokeOnceTimer(guid, onceTimers) {
4467   if (onceTimers[this.tguid]) { delete onceTimers[this.tguid][this.mguid]; }
4468   if (timers[guid]) { invoke(this.target, this.method, this.args); }
4469   delete timers[guid];
4470 }
4471
4472 function scheduleOnce(queue, target, method, args) {
4473   var tguid = Ember.guidFor(target),
4474     mguid = Ember.guidFor(method),
4475     onceTimers = run.autorun().onceTimers,
4476     guid = onceTimers[tguid] && onceTimers[tguid][mguid],
4477     timer;
4478
4479   if (guid && timers[guid]) {
4480     timers[guid].args = args; // replace args
4481   } else {
4482     timer = {
4483       target: target,
4484       method: method,
4485       args:   args,
4486       tguid:  tguid,
4487       mguid:  mguid
4488     };
4489
4490     guid  = Ember.guidFor(timer);
4491     timers[guid] = timer;
4492     if (!onceTimers[tguid]) { onceTimers[tguid] = {}; }
4493     onceTimers[tguid][mguid] = guid; // so it isn't scheduled more than once
4494
4495     run.schedule(queue, timer, invokeOnceTimer, guid, onceTimers);
4496   }
4497
4498   return guid;
4499 }
4500
4501 /**
4502   Schedules an item to run one time during the current RunLoop. Calling
4503   this method with the same target/method combination will have no effect.
4504
4505   Note that although you can pass optional arguments these will not be
4506   considered when looking for duplicates. New arguments will replace previous
4507   calls.
4508
4509   ```javascript
4510   Ember.run(function(){
4511     var doFoo = function() { foo(); }
4512     Ember.run.once(myContext, doFoo);
4513     Ember.run.once(myContext, doFoo);
4514     // doFoo will only be executed once at the end of the RunLoop
4515   });
4516   ```
4517
4518   @method once
4519   @param {Object} [target] target of method to invoke
4520   @param {Function|String} method The method to invoke.
4521     If you pass a string it will be resolved on the
4522     target at the time the method is invoked.
4523   @param {Object} [args*] Optional arguments to pass to the timeout.
4524   @return {Object} timer
4525 */
4526 Ember.run.once = function(target, method) {
4527   return scheduleOnce('actions', target, method, slice.call(arguments, 2));
4528 };
4529
4530 Ember.run.scheduleOnce = function(queue, target, method, args) {
4531   return scheduleOnce(queue, target, method, slice.call(arguments, 3));
4532 };
4533
4534 var scheduledNext;
4535 function invokeNextTimers() {
4536   scheduledNext = null;
4537   for(var key in timers) {
4538     if (!timers.hasOwnProperty(key)) { continue; }
4539     var timer = timers[key];
4540     if (timer.next) {
4541       delete timers[key];
4542       invoke(timer.target, timer.method, timer.args, 2);
4543     }
4544   }
4545 }
4546
4547 /**
4548   Schedules an item to run after control has been returned to the system.
4549   This is often equivalent to calling `setTimeout(function() {}, 1)`.
4550
4551   ```javascript
4552   Ember.run.next(myContext, function(){
4553     // code to be executed in the next RunLoop, which will be scheduled after the current one
4554   });
4555   ```
4556
4557   @method next
4558   @param {Object} [target] target of method to invoke
4559   @param {Function|String} method The method to invoke.
4560     If you pass a string it will be resolved on the
4561     target at the time the method is invoked.
4562   @param {Object} [args*] Optional arguments to pass to the timeout.
4563   @return {Object} timer
4564 */
4565 Ember.run.next = function(target, method) {
4566   var guid,
4567       timer = {
4568         target: target,
4569         method: method,
4570         args: slice.call(arguments),
4571         next: true
4572       };
4573
4574   guid = Ember.guidFor(timer);
4575   timers[guid] = timer;
4576
4577   if (!scheduledNext) { scheduledNext = setTimeout(invokeNextTimers, 1); }
4578   return guid;
4579 };
4580
4581 /**
4582   Cancels a scheduled item. Must be a value returned by `Ember.run.later()`,
4583   `Ember.run.once()`, or `Ember.run.next()`.
4584
4585   ```javascript
4586   var runNext = Ember.run.next(myContext, function(){
4587     // will not be executed
4588   });
4589   Ember.run.cancel(runNext);
4590
4591   var runLater = Ember.run.later(myContext, function(){
4592     // will not be executed
4593   }, 500);
4594   Ember.run.cancel(runLater);
4595
4596   var runOnce = Ember.run.once(myContext, function(){
4597     // will not be executed
4598   });
4599   Ember.run.cancel(runOnce);
4600   ```
4601
4602   @method cancel
4603   @param {Object} timer Timer object to cancel
4604   @return {void}
4605 */
4606 Ember.run.cancel = function(timer) {
4607   delete timers[timer];
4608 };
4609
4610 })();
4611
4612
4613
4614 (function() {
4615 // Ember.Logger
4616 // get, set, trySet
4617 // guidFor, isArray, meta
4618 // addObserver, removeObserver
4619 // Ember.run.schedule
4620 /**
4621 @module ember-metal
4622 */
4623
4624 // ..........................................................
4625 // CONSTANTS
4626 //
4627
4628 /**
4629   Debug parameter you can turn on. This will log all bindings that fire to
4630   the console. This should be disabled in production code. Note that you
4631   can also enable this from the console or temporarily.
4632
4633   @property LOG_BINDINGS
4634   @for Ember
4635   @type Boolean
4636   @default false
4637 */
4638 Ember.LOG_BINDINGS = false || !!Ember.ENV.LOG_BINDINGS;
4639
4640 var get     = Ember.get,
4641     set     = Ember.set,
4642     guidFor = Ember.guidFor,
4643     isGlobalPath = Ember.isGlobalPath;
4644
4645
4646 function getWithGlobals(obj, path) {
4647   return get(isGlobalPath(path) ? Ember.lookup : obj, path);
4648 }
4649
4650 // ..........................................................
4651 // BINDING
4652 //
4653
4654 var Binding = function(toPath, fromPath) {
4655   this._direction = 'fwd';
4656   this._from = fromPath;
4657   this._to   = toPath;
4658   this._directionMap = Ember.Map.create();
4659 };
4660
4661 /**
4662 @class Binding
4663 @namespace Ember
4664 */
4665
4666 Binding.prototype = {
4667   /**
4668     This copies the Binding so it can be connected to another object.
4669
4670     @method copy
4671     @return {Ember.Binding}
4672   */
4673   copy: function () {
4674     var copy = new Binding(this._to, this._from);
4675     if (this._oneWay) { copy._oneWay = true; }
4676     return copy;
4677   },
4678
4679   // ..........................................................
4680   // CONFIG
4681   //
4682
4683   /**
4684     This will set `from` property path to the specified value. It will not
4685     attempt to resolve this property path to an actual object until you
4686     connect the binding.
4687
4688     The binding will search for the property path starting at the root object
4689     you pass when you `connect()` the binding. It follows the same rules as
4690     `get()` - see that method for more information.
4691
4692     @method from
4693     @param {String} propertyPath the property path to connect to
4694     @return {Ember.Binding} `this`
4695   */
4696   from: function(path) {
4697     this._from = path;
4698     return this;
4699   },
4700
4701   /**
4702     This will set the `to` property path to the specified value. It will not
4703     attempt to resolve this property path to an actual object until you
4704     connect the binding.
4705
4706     The binding will search for the property path starting at the root object
4707     you pass when you `connect()` the binding. It follows the same rules as
4708     `get()` - see that method for more information.
4709
4710     @method to
4711     @param {String|Tuple} propertyPath A property path or tuple
4712     @return {Ember.Binding} `this`
4713   */
4714   to: function(path) {
4715     this._to = path;
4716     return this;
4717   },
4718
4719   /**
4720     Configures the binding as one way. A one-way binding will relay changes
4721     on the `from` side to the `to` side, but not the other way around. This
4722     means that if you change the `to` side directly, the `from` side may have
4723     a different value.
4724
4725     @method oneWay
4726     @return {Ember.Binding} `this`
4727   */
4728   oneWay: function() {
4729     this._oneWay = true;
4730     return this;
4731   },
4732
4733   toString: function() {
4734     var oneWay = this._oneWay ? '[oneWay]' : '';
4735     return "Ember.Binding<" + guidFor(this) + ">(" + this._from + " -> " + this._to + ")" + oneWay;
4736   },
4737
4738   // ..........................................................
4739   // CONNECT AND SYNC
4740   //
4741
4742   /**
4743     Attempts to connect this binding instance so that it can receive and relay
4744     changes. This method will raise an exception if you have not set the
4745     from/to properties yet.
4746
4747     @method connect
4748     @param {Object} obj The root object for this binding.
4749     @return {Ember.Binding} `this`
4750   */
4751   connect: function(obj) {
4752     Ember.assert('Must pass a valid object to Ember.Binding.connect()', !!obj);
4753
4754     var fromPath = this._from, toPath = this._to;
4755     Ember.trySet(obj, toPath, getWithGlobals(obj, fromPath));
4756
4757     // add an observer on the object to be notified when the binding should be updated
4758     Ember.addObserver(obj, fromPath, this, this.fromDidChange);
4759
4760     // if the binding is a two-way binding, also set up an observer on the target
4761     if (!this._oneWay) { Ember.addObserver(obj, toPath, this, this.toDidChange); }
4762
4763     this._readyToSync = true;
4764
4765     return this;
4766   },
4767
4768   /**
4769     Disconnects the binding instance. Changes will no longer be relayed. You
4770     will not usually need to call this method.
4771
4772     @method disconnect
4773     @param {Object} obj The root object you passed when connecting the binding.
4774     @return {Ember.Binding} `this`
4775   */
4776   disconnect: function(obj) {
4777     Ember.assert('Must pass a valid object to Ember.Binding.disconnect()', !!obj);
4778
4779     var twoWay = !this._oneWay;
4780
4781     // remove an observer on the object so we're no longer notified of
4782     // changes that should update bindings.
4783     Ember.removeObserver(obj, this._from, this, this.fromDidChange);
4784
4785     // if the binding is two-way, remove the observer from the target as well
4786     if (twoWay) { Ember.removeObserver(obj, this._to, this, this.toDidChange); }
4787
4788     this._readyToSync = false; // disable scheduled syncs...
4789     return this;
4790   },
4791
4792   // ..........................................................
4793   // PRIVATE
4794   //
4795
4796   /* called when the from side changes */
4797   fromDidChange: function(target) {
4798     this._scheduleSync(target, 'fwd');
4799   },
4800
4801   /* called when the to side changes */
4802   toDidChange: function(target) {
4803     this._scheduleSync(target, 'back');
4804   },
4805
4806   _scheduleSync: function(obj, dir) {
4807     var directionMap = this._directionMap;
4808     var existingDir = directionMap.get(obj);
4809
4810     // if we haven't scheduled the binding yet, schedule it
4811     if (!existingDir) {
4812       Ember.run.schedule('sync', this, this._sync, obj);
4813       directionMap.set(obj, dir);
4814     }
4815
4816     // If both a 'back' and 'fwd' sync have been scheduled on the same object,
4817     // default to a 'fwd' sync so that it remains deterministic.
4818     if (existingDir === 'back' && dir === 'fwd') {
4819       directionMap.set(obj, 'fwd');
4820     }
4821   },
4822
4823   _sync: function(obj) {
4824     var log = Ember.LOG_BINDINGS;
4825
4826     // don't synchronize destroyed objects or disconnected bindings
4827     if (obj.isDestroyed || !this._readyToSync) { return; }
4828
4829     // get the direction of the binding for the object we are
4830     // synchronizing from
4831     var directionMap = this._directionMap;
4832     var direction = directionMap.get(obj);
4833
4834     var fromPath = this._from, toPath = this._to;
4835
4836     directionMap.remove(obj);
4837
4838     // if we're synchronizing from the remote object...
4839     if (direction === 'fwd') {
4840       var fromValue = getWithGlobals(obj, this._from);
4841       if (log) {
4842         Ember.Logger.log(' ', this.toString(), '->', fromValue, obj);
4843       }
4844       if (this._oneWay) {
4845         Ember.trySet(obj, toPath, fromValue);
4846       } else {
4847         Ember._suspendObserver(obj, toPath, this, this.toDidChange, function () {
4848           Ember.trySet(obj, toPath, fromValue);
4849         });
4850       }
4851     // if we're synchronizing *to* the remote object
4852     } else if (direction === 'back') {
4853       var toValue = get(obj, this._to);
4854       if (log) {
4855         Ember.Logger.log(' ', this.toString(), '<-', toValue, obj);
4856       }
4857       Ember._suspendObserver(obj, fromPath, this, this.fromDidChange, function () {
4858         Ember.trySet(Ember.isGlobalPath(fromPath) ? Ember.lookup : obj, fromPath, toValue);
4859       });
4860     }
4861   }
4862
4863 };
4864
4865 function mixinProperties(to, from) {
4866   for (var key in from) {
4867     if (from.hasOwnProperty(key)) {
4868       to[key] = from[key];
4869     }
4870   }
4871 }
4872
4873 mixinProperties(Binding, {
4874
4875   /**
4876     See {{#crossLink "Ember.Binding/from"}}{{/crossLink}}
4877
4878     @method from
4879     @static
4880   */
4881   from: function() {
4882     var C = this, binding = new C();
4883     return binding.from.apply(binding, arguments);
4884   },
4885
4886   /**
4887     See {{#crossLink "Ember.Binding/to"}}{{/crossLink}}
4888
4889     @method to
4890     @static
4891   */
4892   to: function() {
4893     var C = this, binding = new C();
4894     return binding.to.apply(binding, arguments);
4895   },
4896
4897   /**
4898     Creates a new Binding instance and makes it apply in a single direction.
4899     A one-way binding will relay changes on the `from` side object (supplied
4900     as the `from` argument) the `to` side, but not the other way around.
4901     This means that if you change the "to" side directly, the "from" side may have
4902     a different value.
4903
4904     See {{#crossLink "Binding/oneWay"}}{{/crossLink}}
4905
4906     @method oneWay
4907     @param {String} from from path.
4908     @param {Boolean} [flag] (Optional) passing nothing here will make the
4909       binding `oneWay`. You can instead pass `false` to disable `oneWay`, making the
4910       binding two way again.
4911   */
4912   oneWay: function(from, flag) {
4913     var C = this, binding = new C(null, from);
4914     return binding.oneWay(flag);
4915   }
4916
4917 });
4918
4919 /**
4920   An `Ember.Binding` connects the properties of two objects so that whenever
4921   the value of one property changes, the other property will be changed also.
4922
4923   ## Automatic Creation of Bindings with `/^*Binding/`-named Properties
4924
4925   You do not usually create Binding objects directly but instead describe
4926   bindings in your class or object definition using automatic binding
4927   detection.
4928
4929   Properties ending in a `Binding` suffix will be converted to `Ember.Binding`
4930   instances. The value of this property should be a string representing a path
4931   to another object or a custom binding instanced created using Binding helpers
4932   (see "Customizing Your Bindings"):
4933
4934   ```
4935   valueBinding: "MyApp.someController.title"
4936   ```
4937
4938   This will create a binding from `MyApp.someController.title` to the `value`
4939   property of your object instance automatically. Now the two values will be
4940   kept in sync.
4941
4942   ## One Way Bindings
4943
4944   One especially useful binding customization you can use is the `oneWay()`
4945   helper. This helper tells Ember that you are only interested in
4946   receiving changes on the object you are binding from. For example, if you
4947   are binding to a preference and you want to be notified if the preference
4948   has changed, but your object will not be changing the preference itself, you
4949   could do:
4950
4951   ```
4952   bigTitlesBinding: Ember.Binding.oneWay("MyApp.preferencesController.bigTitles")
4953   ```
4954
4955   This way if the value of `MyApp.preferencesController.bigTitles` changes the
4956   `bigTitles` property of your object will change also. However, if you
4957   change the value of your `bigTitles` property, it will not update the
4958   `preferencesController`.
4959
4960   One way bindings are almost twice as fast to setup and twice as fast to
4961   execute because the binding only has to worry about changes to one side.
4962
4963   You should consider using one way bindings anytime you have an object that
4964   may be created frequently and you do not intend to change a property; only
4965   to monitor it for changes. (such as in the example above).
4966
4967   ## Adding Bindings Manually
4968
4969   All of the examples above show you how to configure a custom binding, but the
4970   result of these customizations will be a binding template, not a fully active
4971   Binding instance. The binding will actually become active only when you
4972   instantiate the object the binding belongs to. It is useful however, to
4973   understand what actually happens when the binding is activated.
4974
4975   For a binding to function it must have at least a `from` property and a `to`
4976   property. The `from` property path points to the object/key that you want to
4977   bind from while the `to` path points to the object/key you want to bind to.
4978
4979   When you define a custom binding, you are usually describing the property
4980   you want to bind from (such as `MyApp.someController.value` in the examples
4981   above). When your object is created, it will automatically assign the value
4982   you want to bind `to` based on the name of your binding key. In the
4983   examples above, during init, Ember objects will effectively call
4984   something like this on your binding:
4985
4986   ```javascript
4987   binding = Ember.Binding.from(this.valueBinding).to("value");
4988   ```
4989
4990   This creates a new binding instance based on the template you provide, and
4991   sets the to path to the `value` property of the new object. Now that the
4992   binding is fully configured with a `from` and a `to`, it simply needs to be
4993   connected to become active. This is done through the `connect()` method:
4994
4995   ```javascript
4996   binding.connect(this);
4997   ```
4998
4999   Note that when you connect a binding you pass the object you want it to be
5000   connected to. This object will be used as the root for both the from and
5001   to side of the binding when inspecting relative paths. This allows the
5002   binding to be automatically inherited by subclassed objects as well.
5003
5004   Now that the binding is connected, it will observe both the from and to side
5005   and relay changes.
5006
5007   If you ever needed to do so (you almost never will, but it is useful to
5008   understand this anyway), you could manually create an active binding by
5009   using the `Ember.bind()` helper method. (This is the same method used by
5010   to setup your bindings on objects):
5011
5012   ```javascript
5013   Ember.bind(MyApp.anotherObject, "value", "MyApp.someController.value");
5014   ```
5015
5016   Both of these code fragments have the same effect as doing the most friendly
5017   form of binding creation like so:
5018
5019   ```javascript
5020   MyApp.anotherObject = Ember.Object.create({
5021     valueBinding: "MyApp.someController.value",
5022
5023     // OTHER CODE FOR THIS OBJECT...
5024   });
5025   ```
5026
5027   Ember's built in binding creation method makes it easy to automatically
5028   create bindings for you. You should always use the highest-level APIs
5029   available, even if you understand how it works underneath.
5030
5031   @class Binding
5032   @namespace Ember
5033   @since Ember 0.9
5034 */
5035 Ember.Binding = Binding;
5036
5037
5038 /**
5039   Global helper method to create a new binding. Just pass the root object
5040   along with a `to` and `from` path to create and connect the binding.
5041
5042   @method bind
5043   @for Ember
5044   @param {Object} obj The root object of the transform.
5045   @param {String} to The path to the 'to' side of the binding.
5046     Must be relative to obj.
5047   @param {String} from The path to the 'from' side of the binding.
5048     Must be relative to obj or a global path.
5049   @return {Ember.Binding} binding instance
5050 */
5051 Ember.bind = function(obj, to, from) {
5052   return new Ember.Binding(to, from).connect(obj);
5053 };
5054
5055 /**
5056   @method oneWay
5057   @for Ember
5058   @param {Object} obj The root object of the transform.
5059   @param {String} to The path to the 'to' side of the binding.
5060     Must be relative to obj.
5061   @param {String} from The path to the 'from' side of the binding.
5062     Must be relative to obj or a global path.
5063   @return {Ember.Binding} binding instance
5064 */
5065 Ember.oneWay = function(obj, to, from) {
5066   return new Ember.Binding(to, from).oneWay().connect(obj);
5067 };
5068
5069 })();
5070
5071
5072
5073 (function() {
5074 /**
5075 @module ember-metal
5076 */
5077
5078 var Mixin, REQUIRED, Alias,
5079     a_map = Ember.ArrayPolyfills.map,
5080     a_indexOf = Ember.ArrayPolyfills.indexOf,
5081     a_forEach = Ember.ArrayPolyfills.forEach,
5082     a_slice = [].slice,
5083     EMPTY_META = {}, // dummy for non-writable meta
5084     o_create = Ember.create,
5085     defineProperty = Ember.defineProperty,
5086     guidFor = Ember.guidFor;
5087
5088 function mixinsMeta(obj) {
5089   var m = Ember.meta(obj, true), ret = m.mixins;
5090   if (!ret) {
5091     ret = m.mixins = {};
5092   } else if (!m.hasOwnProperty('mixins')) {
5093     ret = m.mixins = o_create(ret);
5094   }
5095   return ret;
5096 }
5097
5098 function initMixin(mixin, args) {
5099   if (args && args.length > 0) {
5100     mixin.mixins = a_map.call(args, function(x) {
5101       if (x instanceof Mixin) { return x; }
5102
5103       // Note: Manually setup a primitive mixin here. This is the only
5104       // way to actually get a primitive mixin. This way normal creation
5105       // of mixins will give you combined mixins...
5106       var mixin = new Mixin();
5107       mixin.properties = x;
5108       return mixin;
5109     });
5110   }
5111   return mixin;
5112 }
5113
5114 function isMethod(obj) {
5115   return 'function' === typeof obj &&
5116          obj.isMethod !== false &&
5117          obj !== Boolean && obj !== Object && obj !== Number && obj !== Array && obj !== Date && obj !== String;
5118 }
5119
5120 var CONTINUE = {};
5121
5122 function mixinProperties(mixinsMeta, mixin) {
5123   var guid;
5124
5125   if (mixin instanceof Mixin) {
5126     guid = guidFor(mixin);
5127     if (mixinsMeta[guid]) { return CONTINUE; }
5128     mixinsMeta[guid] = mixin;
5129     return mixin.properties;
5130   } else {
5131     return mixin; // apply anonymous mixin properties
5132   }
5133 }
5134
5135 function concatenatedProperties(props, values, base) {
5136   var concats;
5137
5138   // reset before adding each new mixin to pickup concats from previous
5139   concats = values.concatenatedProperties || base.concatenatedProperties;
5140   if (props.concatenatedProperties) {
5141     concats = concats ? concats.concat(props.concatenatedProperties) : props.concatenatedProperties;
5142   }
5143
5144   return concats;
5145 }
5146
5147 function giveDescriptorSuper(meta, key, property, values, descs) {
5148   var superProperty;
5149
5150   // Computed properties override methods, and do not call super to them
5151   if (values[key] === undefined) {
5152     // Find the original descriptor in a parent mixin
5153     superProperty = descs[key];
5154   }
5155
5156   // If we didn't find the original descriptor in a parent mixin, find
5157   // it on the original object.
5158   superProperty = superProperty || meta.descs[key];
5159
5160   if (!superProperty || !(superProperty instanceof Ember.ComputedProperty)) {
5161     return property;
5162   }
5163
5164   // Since multiple mixins may inherit from the same parent, we need
5165   // to clone the computed property so that other mixins do not receive
5166   // the wrapped version.
5167   property = o_create(property);
5168   property.func = Ember.wrap(property.func, superProperty.func);
5169
5170   return property;
5171 }
5172
5173 function giveMethodSuper(obj, key, method, values, descs) {
5174   var superMethod;
5175
5176   // Methods overwrite computed properties, and do not call super to them.
5177   if (descs[key] === undefined) {
5178     // Find the original method in a parent mixin
5179     superMethod = values[key];
5180   }
5181
5182   // If we didn't find the original value in a parent mixin, find it in
5183   // the original object
5184   superMethod = superMethod || obj[key];
5185
5186   // Only wrap the new method if the original method was a function
5187   if ('function' !== typeof superMethod) {
5188     return method;
5189   }
5190
5191   return Ember.wrap(method, superMethod);
5192 }
5193
5194 function applyConcatenatedProperties(obj, key, value, values) {
5195   var baseValue = values[key] || obj[key];
5196
5197   if (baseValue) {
5198     if ('function' === typeof baseValue.concat) {
5199       return baseValue.concat(value);
5200     } else {
5201       return Ember.makeArray(baseValue).concat(value);
5202     }
5203   } else {
5204     return Ember.makeArray(value);
5205   }
5206 }
5207
5208 function addNormalizedProperty(base, key, value, meta, descs, values, concats) {
5209   if (value instanceof Ember.Descriptor) {
5210     if (value === REQUIRED && descs[key]) { return CONTINUE; }
5211
5212     // Wrap descriptor function to implement
5213     // _super() if needed
5214     if (value.func) {
5215       value = giveDescriptorSuper(meta, key, value, values, descs);
5216     }
5217
5218     descs[key]  = value;
5219     values[key] = undefined;
5220   } else {
5221     // impl super if needed...
5222     if (isMethod(value)) {
5223       value = giveMethodSuper(base, key, value, values, descs);
5224     } else if ((concats && a_indexOf.call(concats, key) >= 0) || key === 'concatenatedProperties') {
5225       value = applyConcatenatedProperties(base, key, value, values);
5226     }
5227
5228     descs[key] = undefined;
5229     values[key] = value;
5230   }
5231 }
5232
5233 function mergeMixins(mixins, m, descs, values, base) {
5234   var mixin, props, key, concats, meta;
5235
5236   function removeKeys(keyName) {
5237     delete descs[keyName];
5238     delete values[keyName];
5239   }
5240
5241   for(var i=0, l=mixins.length; i<l; i++) {
5242     mixin = mixins[i];
5243     Ember.assert('Expected hash or Mixin instance, got ' + Object.prototype.toString.call(mixin), typeof mixin === 'object' && mixin !== null && Object.prototype.toString.call(mixin) !== '[object Array]');
5244
5245     props = mixinProperties(m, mixin);
5246     if (props === CONTINUE) { continue; }
5247
5248     if (props) {
5249       meta = Ember.meta(base);
5250       concats = concatenatedProperties(props, values, base);
5251
5252       for (key in props) {
5253         if (!props.hasOwnProperty(key)) { continue; }
5254         addNormalizedProperty(base, key, props[key], meta, descs, values, concats);
5255       }
5256
5257       // manually copy toString() because some JS engines do not enumerate it
5258       if (props.hasOwnProperty('toString')) { base.toString = props.toString; }
5259     } else if (mixin.mixins) {
5260       mergeMixins(mixin.mixins, m, descs, values, base);
5261       if (mixin._without) { a_forEach.call(mixin._without, removeKeys); }
5262     }
5263   }
5264 }
5265
5266 function writableReq(obj) {
5267   var m = Ember.meta(obj), req = m.required;
5268   if (!req || !m.hasOwnProperty('required')) {
5269     req = m.required = req ? o_create(req) : {};
5270   }
5271   return req;
5272 }
5273
5274 var IS_BINDING = Ember.IS_BINDING = /^.+Binding$/;
5275
5276 function detectBinding(obj, key, value, m) {
5277   if (IS_BINDING.test(key)) {
5278     var bindings = m.bindings;
5279     if (!bindings) {
5280       bindings = m.bindings = {};
5281     } else if (!m.hasOwnProperty('bindings')) {
5282       bindings = m.bindings = o_create(m.bindings);
5283     }
5284     bindings[key] = value;
5285   }
5286 }
5287
5288 function connectBindings(obj, m) {
5289   // TODO Mixin.apply(instance) should disconnect binding if exists
5290   var bindings = m.bindings, key, binding, to;
5291   if (bindings) {
5292     for (key in bindings) {
5293       binding = bindings[key];
5294       if (binding) {
5295         to = key.slice(0, -7); // strip Binding off end
5296         if (binding instanceof Ember.Binding) {
5297           binding = binding.copy(); // copy prototypes' instance
5298           binding.to(to);
5299         } else { // binding is string path
5300           binding = new Ember.Binding(to, binding);
5301         }
5302         binding.connect(obj);
5303         obj[key] = binding;
5304       }
5305     }
5306     // mark as applied
5307     m.bindings = {};
5308   }
5309 }
5310
5311 function finishPartial(obj, m) {
5312   connectBindings(obj, m || Ember.meta(obj));
5313   return obj;
5314 }
5315
5316 function followAlias(obj, desc, m, descs, values) {
5317   var altKey = desc.methodName, value;
5318   if (descs[altKey] || values[altKey]) {
5319     value = values[altKey];
5320     desc  = descs[altKey];
5321   } else if (m.descs[altKey]) {
5322     desc  = m.descs[altKey];
5323     value = undefined;
5324   } else {
5325     desc = undefined;
5326     value = obj[altKey];
5327   }
5328
5329   return { desc: desc, value: value };
5330 }
5331
5332 function updateObservers(obj, key, observer, observerKey, method) {
5333   if ('function' !== typeof observer) { return; }
5334
5335   var paths = observer[observerKey];
5336
5337   if (paths) {
5338     for (var i=0, l=paths.length; i<l; i++) {
5339       Ember[method](obj, paths[i], null, key);
5340     }
5341   }
5342 }
5343
5344 function replaceObservers(obj, key, observer) {
5345   var prevObserver = obj[key];
5346
5347   updateObservers(obj, key, prevObserver, '__ember_observesBefore__', 'removeBeforeObserver');
5348   updateObservers(obj, key, prevObserver, '__ember_observes__', 'removeObserver');
5349
5350   updateObservers(obj, key, observer, '__ember_observesBefore__', 'addBeforeObserver');
5351   updateObservers(obj, key, observer, '__ember_observes__', 'addObserver');
5352 }
5353
5354 function applyMixin(obj, mixins, partial) {
5355   var descs = {}, values = {}, m = Ember.meta(obj),
5356       key, value, desc;
5357
5358   // Go through all mixins and hashes passed in, and:
5359   //
5360   // * Handle concatenated properties
5361   // * Set up _super wrapping if necessary
5362   // * Set up computed property descriptors
5363   // * Copying `toString` in broken browsers
5364   mergeMixins(mixins, mixinsMeta(obj), descs, values, obj);
5365
5366   for(key in values) {
5367     if (key === 'contructor' || !values.hasOwnProperty(key)) { continue; }
5368
5369     desc = descs[key];
5370     value = values[key];
5371
5372     if (desc === REQUIRED) { continue; }
5373
5374     while (desc && desc instanceof Alias) {
5375       var followed = followAlias(obj, desc, m, descs, values);
5376       desc = followed.desc;
5377       value = followed.value;
5378     }
5379
5380     if (desc === undefined && value === undefined) { continue; }
5381
5382     replaceObservers(obj, key, value);
5383     detectBinding(obj, key, value, m);
5384     defineProperty(obj, key, desc, value, m);
5385   }
5386
5387   if (!partial) { // don't apply to prototype
5388     finishPartial(obj, m);
5389   }
5390
5391   return obj;
5392 }
5393
5394 /**
5395   @method mixin
5396   @for Ember
5397   @param obj
5398   @param mixins*
5399   @return obj
5400 */
5401 Ember.mixin = function(obj) {
5402   var args = a_slice.call(arguments, 1);
5403   applyMixin(obj, args, false);
5404   return obj;
5405 };
5406
5407 /**
5408   The `Ember.Mixin` class allows you to create mixins, whose properties can be
5409   added to other classes. For instance,
5410
5411   ```javascript
5412   App.Editable = Ember.Mixin.create({
5413     edit: function() {
5414       console.log('starting to edit');
5415       this.set('isEditing', true);
5416     },
5417     isEditing: false
5418   });
5419
5420   // Mix mixins into classes by passing them as the first arguments to
5421   // .extend or .create.
5422   App.CommentView = Ember.View.extend(App.Editable, {
5423     template: Ember.Handlebars.compile('{{#if isEditing}}...{{else}}...{{/if}}')
5424   });
5425
5426   commentView = App.CommentView.create();
5427   commentView.edit(); // outputs 'starting to edit'
5428   ```
5429
5430   Note that Mixins are created with `Ember.Mixin.create`, not
5431   `Ember.Mixin.extend`.
5432
5433   @class Mixin
5434   @namespace Ember
5435 */
5436 Ember.Mixin = function() { return initMixin(this, arguments); };
5437
5438 Mixin = Ember.Mixin;
5439
5440 Mixin._apply = applyMixin;
5441
5442 Mixin.applyPartial = function(obj) {
5443   var args = a_slice.call(arguments, 1);
5444   return applyMixin(obj, args, true);
5445 };
5446
5447 Mixin.finishPartial = finishPartial;
5448
5449 Ember.anyUnprocessedMixins = false;
5450
5451 /**
5452   @method create
5453   @static
5454   @param arguments*
5455 */
5456 Mixin.create = function() {
5457   Ember.anyUnprocessedMixins = true;
5458   var M = this;
5459   return initMixin(new M(), arguments);
5460 };
5461
5462 var MixinPrototype = Mixin.prototype;
5463
5464 /**
5465   @method reopen
5466   @param arguments*
5467 */
5468 MixinPrototype.reopen = function() {
5469   var mixin, tmp;
5470
5471   if (this.properties) {
5472     mixin = Mixin.create();
5473     mixin.properties = this.properties;
5474     delete this.properties;
5475     this.mixins = [mixin];
5476   } else if (!this.mixins) {
5477     this.mixins = [];
5478   }
5479
5480   var len = arguments.length, mixins = this.mixins, idx;
5481
5482   for(idx=0; idx < len; idx++) {
5483     mixin = arguments[idx];
5484     Ember.assert('Expected hash or Mixin instance, got ' + Object.prototype.toString.call(mixin), typeof mixin === 'object' && mixin !== null && Object.prototype.toString.call(mixin) !== '[object Array]');
5485
5486     if (mixin instanceof Mixin) {
5487       mixins.push(mixin);
5488     } else {
5489       tmp = Mixin.create();
5490       tmp.properties = mixin;
5491       mixins.push(tmp);
5492     }
5493   }
5494
5495   return this;
5496 };
5497
5498 /**
5499   @method apply
5500   @param obj
5501   @return applied object
5502 */
5503 MixinPrototype.apply = function(obj) {
5504   return applyMixin(obj, [this], false);
5505 };
5506
5507 MixinPrototype.applyPartial = function(obj) {
5508   return applyMixin(obj, [this], true);
5509 };
5510
5511 function _detect(curMixin, targetMixin, seen) {
5512   var guid = guidFor(curMixin);
5513
5514   if (seen[guid]) { return false; }
5515   seen[guid] = true;
5516
5517   if (curMixin === targetMixin) { return true; }
5518   var mixins = curMixin.mixins, loc = mixins ? mixins.length : 0;
5519   while (--loc >= 0) {
5520     if (_detect(mixins[loc], targetMixin, seen)) { return true; }
5521   }
5522   return false;
5523 }
5524
5525 /**
5526   @method detect
5527   @param obj
5528   @return {Boolean}
5529 */
5530 MixinPrototype.detect = function(obj) {
5531   if (!obj) { return false; }
5532   if (obj instanceof Mixin) { return _detect(obj, this, {}); }
5533   var mixins = Ember.meta(obj, false).mixins;
5534   if (mixins) {
5535     return !!mixins[guidFor(this)];
5536   }
5537   return false;
5538 };
5539
5540 MixinPrototype.without = function() {
5541   var ret = new Mixin(this);
5542   ret._without = a_slice.call(arguments);
5543   return ret;
5544 };
5545
5546 function _keys(ret, mixin, seen) {
5547   if (seen[guidFor(mixin)]) { return; }
5548   seen[guidFor(mixin)] = true;
5549
5550   if (mixin.properties) {
5551     var props = mixin.properties;
5552     for (var key in props) {
5553       if (props.hasOwnProperty(key)) { ret[key] = true; }
5554     }
5555   } else if (mixin.mixins) {
5556     a_forEach.call(mixin.mixins, function(x) { _keys(ret, x, seen); });
5557   }
5558 }
5559
5560 MixinPrototype.keys = function() {
5561   var keys = {}, seen = {}, ret = [];
5562   _keys(keys, this, seen);
5563   for(var key in keys) {
5564     if (keys.hasOwnProperty(key)) { ret.push(key); }
5565   }
5566   return ret;
5567 };
5568
5569 // returns the mixins currently applied to the specified object
5570 // TODO: Make Ember.mixin
5571 Mixin.mixins = function(obj) {
5572   var mixins = Ember.meta(obj, false).mixins, ret = [];
5573
5574   if (!mixins) { return ret; }
5575
5576   for (var key in mixins) {
5577     var mixin = mixins[key];
5578
5579     // skip primitive mixins since these are always anonymous
5580     if (!mixin.properties) { ret.push(mixin); }
5581   }
5582
5583   return ret;
5584 };
5585
5586 REQUIRED = new Ember.Descriptor();
5587 REQUIRED.toString = function() { return '(Required Property)'; };
5588
5589 /**
5590   Denotes a required property for a mixin
5591
5592   @method required
5593   @for Ember
5594 */
5595 Ember.required = function() {
5596   return REQUIRED;
5597 };
5598
5599 Alias = function(methodName) {
5600   this.methodName = methodName;
5601 };
5602 Alias.prototype = new Ember.Descriptor();
5603
5604 /**
5605   Makes a property or method available via an additional name.
5606
5607   ```javascript
5608   App.PaintSample = Ember.Object.extend({
5609     color: 'red',
5610     colour: Ember.alias('color'),
5611     name: function(){
5612       return "Zed";
5613     },
5614     moniker: Ember.alias("name")
5615   });
5616
5617   var paintSample = App.PaintSample.create()
5618   paintSample.get('colour');  // 'red'
5619   paintSample.moniker();      // 'Zed'
5620   ```
5621
5622   @method alias
5623   @for Ember
5624   @param {String} methodName name of the method or property to alias
5625   @return {Ember.Descriptor}
5626   @deprecated Use `Ember.aliasMethod` or `Ember.computed.alias` instead
5627 */
5628 Ember.alias = function(methodName) {
5629   return new Alias(methodName);
5630 };
5631
5632 Ember.deprecateFunc("Ember.alias is deprecated. Please use Ember.aliasMethod or Ember.computed.alias instead.", Ember.alias);
5633
5634 /**
5635   Makes a method available via an additional name.
5636
5637   ```javascript
5638   App.Person = Ember.Object.extend({
5639     name: function(){
5640       return 'Tomhuda Katzdale';
5641     },
5642     moniker: Ember.aliasMethod('name')
5643   });
5644
5645   var goodGuy = App.Person.create()
5646   ```
5647
5648   @method aliasMethod
5649   @for Ember
5650   @param {String} methodName name of the method to alias
5651   @return {Ember.Descriptor}
5652 */
5653 Ember.aliasMethod = function(methodName) {
5654   return new Alias(methodName);
5655 };
5656
5657 // ..........................................................
5658 // OBSERVER HELPER
5659 //
5660
5661 /**
5662   @method observer
5663   @for Ember
5664   @param {Function} func
5665   @param {String} propertyNames*
5666   @return func
5667 */
5668 Ember.observer = function(func) {
5669   var paths = a_slice.call(arguments, 1);
5670   func.__ember_observes__ = paths;
5671   return func;
5672 };
5673
5674 // If observers ever become asynchronous, Ember.immediateObserver
5675 // must remain synchronous.
5676 /**
5677   @method immediateObserver
5678   @for Ember
5679   @param {Function} func
5680   @param {String} propertyNames*
5681   @return func
5682 */
5683 Ember.immediateObserver = function() {
5684   for (var i=0, l=arguments.length; i<l; i++) {
5685     var arg = arguments[i];
5686     Ember.assert("Immediate observers must observe internal properties only, not properties on other objects.", typeof arg !== "string" || arg.indexOf('.') === -1);
5687   }
5688
5689   return Ember.observer.apply(this, arguments);
5690 };
5691
5692 /**
5693   @method beforeObserver
5694   @for Ember
5695   @param {Function} func
5696   @param {String} propertyNames*
5697   @return func
5698 */
5699 Ember.beforeObserver = function(func) {
5700   var paths = a_slice.call(arguments, 1);
5701   func.__ember_observesBefore__ = paths;
5702   return func;
5703 };
5704
5705 })();
5706
5707
5708
5709 (function() {
5710 /**
5711 Ember Metal
5712
5713 @module ember
5714 @submodule ember-metal
5715 */
5716
5717 })();
5718
5719 (function() {
5720 define("rsvp",
5721   [],
5722   function() {
5723     "use strict";
5724     var browserGlobal = (typeof window !== 'undefined') ? window : {};
5725
5726     var MutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
5727     var RSVP, async;
5728
5729     if (typeof process !== 'undefined' &&
5730       {}.toString.call(process) === '[object process]') {
5731       async = function(callback, binding) {
5732         process.nextTick(function() {
5733           callback.call(binding);
5734         });
5735       };
5736     } else if (MutationObserver) {
5737       var queue = [];
5738
5739       var observer = new MutationObserver(function() {
5740         var toProcess = queue.slice();
5741         queue = [];
5742
5743         toProcess.forEach(function(tuple) {
5744           var callback = tuple[0], binding = tuple[1];
5745           callback.call(binding);
5746         });
5747       });
5748
5749       var element = document.createElement('div');
5750       observer.observe(element, { attributes: true });
5751
5752       // Chrome Memory Leak: https://bugs.webkit.org/show_bug.cgi?id=93661
5753       window.addEventListener('unload', function(){
5754         observer.disconnect();
5755         observer = null;
5756       });
5757
5758       async = function(callback, binding) {
5759         queue.push([callback, binding]);
5760         element.setAttribute('drainQueue', 'drainQueue');
5761       };
5762     } else {
5763       async = function(callback, binding) {
5764         setTimeout(function() {
5765           callback.call(binding);
5766         }, 1);
5767       };
5768     }
5769
5770     var Event = function(type, options) {
5771       this.type = type;
5772
5773       for (var option in options) {
5774         if (!options.hasOwnProperty(option)) { continue; }
5775
5776         this[option] = options[option];
5777       }
5778     };
5779
5780     var indexOf = function(callbacks, callback) {
5781       for (var i=0, l=callbacks.length; i<l; i++) {
5782         if (callbacks[i][0] === callback) { return i; }
5783       }
5784
5785       return -1;
5786     };
5787
5788     var callbacksFor = function(object) {
5789       var callbacks = object._promiseCallbacks;
5790
5791       if (!callbacks) {
5792         callbacks = object._promiseCallbacks = {};
5793       }
5794
5795       return callbacks;
5796     };
5797
5798     var EventTarget = {
5799       mixin: function(object) {
5800         object.on = this.on;
5801         object.off = this.off;
5802         object.trigger = this.trigger;
5803         return object;
5804       },
5805
5806       on: function(eventNames, callback, binding) {
5807         var allCallbacks = callbacksFor(this), callbacks, eventName;
5808         eventNames = eventNames.split(/\s+/);
5809         binding = binding || this;
5810
5811         while (eventName = eventNames.shift()) {
5812           callbacks = allCallbacks[eventName];
5813
5814           if (!callbacks) {
5815             callbacks = allCallbacks[eventName] = [];
5816           }
5817
5818           if (indexOf(callbacks, callback) === -1) {
5819             callbacks.push([callback, binding]);
5820           }
5821         }
5822       },
5823
5824       off: function(eventNames, callback) {
5825         var allCallbacks = callbacksFor(this), callbacks, eventName, index;
5826         eventNames = eventNames.split(/\s+/);
5827
5828         while (eventName = eventNames.shift()) {
5829           if (!callback) {
5830             allCallbacks[eventName] = [];
5831             continue;
5832           }
5833
5834           callbacks = allCallbacks[eventName];
5835
5836           index = indexOf(callbacks, callback);
5837
5838           if (index !== -1) { callbacks.splice(index, 1); }
5839         }
5840       },
5841
5842       trigger: function(eventName, options) {
5843         var allCallbacks = callbacksFor(this),
5844             callbacks, callbackTuple, callback, binding, event;
5845
5846         if (callbacks = allCallbacks[eventName]) {
5847           for (var i=0, l=callbacks.length; i<l; i++) {
5848             callbackTuple = callbacks[i];
5849             callback = callbackTuple[0];
5850             binding = callbackTuple[1];
5851
5852             if (typeof options !== 'object') {
5853               options = { detail: options };
5854             }
5855
5856             event = new Event(eventName, options);
5857             callback.call(binding, event);
5858           }
5859         }
5860       }
5861     };
5862
5863     var Promise = function() {
5864       this.on('promise:resolved', function(event) {
5865         this.trigger('success', { detail: event.detail });
5866       }, this);
5867
5868       this.on('promise:failed', function(event) {
5869         this.trigger('error', { detail: event.detail });
5870       }, this);
5871     };
5872
5873     var noop = function() {};
5874
5875     var invokeCallback = function(type, promise, callback, event) {
5876       var hasCallback = typeof callback === 'function',
5877           value, error, succeeded, failed;
5878
5879       if (hasCallback) {
5880         try {
5881           value = callback(event.detail);
5882           succeeded = true;
5883         } catch(e) {
5884           failed = true;
5885           error = e;
5886         }
5887       } else {
5888         value = event.detail;
5889         succeeded = true;
5890       }
5891
5892       if (value && typeof value.then === 'function') {
5893         value.then(function(value) {
5894           promise.resolve(value);
5895         }, function(error) {
5896           promise.reject(error);
5897         });
5898       } else if (hasCallback && succeeded) {
5899         promise.resolve(value);
5900       } else if (failed) {
5901         promise.reject(error);
5902       } else {
5903         promise[type](value);
5904       }
5905     };
5906
5907     Promise.prototype = {
5908       then: function(done, fail) {
5909         var thenPromise = new Promise();
5910
5911         if (this.isResolved) {
5912           RSVP.async(function() {
5913             invokeCallback('resolve', thenPromise, done, { detail: this.resolvedValue });
5914           }, this);
5915         }
5916
5917         if (this.isRejected) {
5918           RSVP.async(function() {
5919             invokeCallback('reject', thenPromise, fail, { detail: this.rejectedValue });
5920           }, this);
5921         }
5922
5923         this.on('promise:resolved', function(event) {
5924           invokeCallback('resolve', thenPromise, done, event);
5925         });
5926
5927         this.on('promise:failed', function(event) {
5928           invokeCallback('reject', thenPromise, fail, event);
5929         });
5930
5931         return thenPromise;
5932       },
5933
5934       resolve: function(value) {
5935         resolve(this, value);
5936
5937         this.resolve = noop;
5938         this.reject = noop;
5939       },
5940
5941       reject: function(value) {
5942         reject(this, value);
5943
5944         this.resolve = noop;
5945         this.reject = noop;
5946       }
5947     };
5948
5949     function resolve(promise, value) {
5950       RSVP.async(function() {
5951         promise.trigger('promise:resolved', { detail: value });
5952         promise.isResolved = true;
5953         promise.resolvedValue = value;
5954       });
5955     }
5956
5957     function reject(promise, value) {
5958       RSVP.async(function() {
5959         promise.trigger('promise:failed', { detail: value });
5960         promise.isRejected = true;
5961         promise.rejectedValue = value;
5962       });
5963     }
5964
5965     EventTarget.mixin(Promise.prototype);
5966
5967     RSVP = { async: async, Promise: Promise, Event: Event, EventTarget: EventTarget };
5968     return RSVP;
5969   });
5970
5971 })();
5972
5973 (function() {
5974 define("container",
5975   [],
5976   function() {
5977
5978     var objectCreate = Object.create || function(parent) {
5979       function F() {}
5980       F.prototype = parent;
5981       return new F();
5982     };
5983
5984     function InheritingDict(parent) {
5985       this.parent = parent;
5986       this.dict = {};
5987     }
5988
5989     InheritingDict.prototype = {
5990       get: function(key) {
5991         var dict = this.dict;
5992
5993         if (dict.hasOwnProperty(key)) {
5994           return dict[key];
5995         }
5996
5997         if (this.parent) {
5998           return this.parent.get(key);
5999         }
6000       },
6001
6002       set: function(key, value) {
6003         this.dict[key] = value;
6004       },
6005
6006       has: function(key) {
6007         var dict = this.dict;
6008
6009         if (dict.hasOwnProperty(key)) {
6010           return true;
6011         }
6012
6013         if (this.parent) {
6014           return this.parent.has(key);
6015         }
6016
6017         return false;
6018       },
6019
6020       eachLocal: function(callback, binding) {
6021         var dict = this.dict;
6022
6023         for (var prop in dict) {
6024           if (dict.hasOwnProperty(prop)) {
6025             callback.call(binding, prop, dict[prop]);
6026           }
6027         }
6028       }
6029     };
6030
6031     function Container(parent) {
6032       this.parent = parent;
6033       this.children = [];
6034
6035       this.resolver = parent && parent.resolver || function() {};
6036       this.registry = new InheritingDict(parent && parent.registry);
6037       this.cache = new InheritingDict(parent && parent.cache);
6038       this.typeInjections = {};
6039       this.injections = {};
6040       this.options = {};
6041       this.typeOptions = {};
6042     }
6043
6044     Container.prototype = {
6045       child: function() {
6046         var container = new Container(this);
6047         this.children.push(container);
6048         return container;
6049       },
6050
6051       set: function(object, key, value) {
6052         object[key] = value;
6053       },
6054
6055       register: function(type, name, factory, options) {
6056         this.registry.set(type + ":" + name, factory);
6057         this.options[type + ":" + name] = options || {};
6058       },
6059
6060       resolve: function(fullName) {
6061         return this.resolver(fullName) || this.registry.get(fullName);
6062       },
6063
6064       lookup: function(fullName) {
6065         if (this.cache.has(fullName)) {
6066           return this.cache.get(fullName);
6067         }
6068
6069         var value = instantiate(this, fullName);
6070
6071         if (!value) { return; }
6072
6073         if (isSingleton(this, fullName)) {
6074           this.cache.set(fullName, value);
6075         }
6076
6077         return value;
6078       },
6079
6080       has: function(fullName) {
6081         if (this.cache.has(fullName)) {
6082           return true;
6083         }
6084
6085         return !!factoryFor(this, fullName);
6086       },
6087
6088       optionsForType: function(type, options) {
6089         if (this.parent) { illegalChildOperation('optionsForType'); }
6090
6091         this.typeOptions[type] = options;
6092       },
6093
6094       typeInjection: function(type, property, fullName) {
6095         if (this.parent) { illegalChildOperation('typeInjection'); }
6096
6097         var injections = this.typeInjections[type] = this.typeInjections[type] || [];
6098         injections.push({ property: property, fullName: fullName });
6099       },
6100
6101       injection: function(factoryName, property, injectionName) {
6102         if (this.parent) { illegalChildOperation('injection'); }
6103
6104         var injections = this.injections[factoryName] = this.injections[factoryName] || [];
6105         injections.push({ property: property, fullName: injectionName });
6106       },
6107
6108       destroy: function() {
6109         this.isDestroyed = true;
6110
6111         for (var i=0, l=this.children.length; i<l; i++) {
6112           this.children[i].destroy();
6113         }
6114
6115         this.children = [];
6116
6117         eachDestroyable(this, function(item) {
6118           item.isDestroying = true;
6119         });
6120
6121         eachDestroyable(this, function(item) {
6122           item.destroy();
6123         });
6124
6125         delete this.parent;
6126         this.isDestroyed = true;
6127       },
6128
6129       reset: function() {
6130         for (var i=0, l=this.children.length; i<l; i++) {
6131           resetCache(this.children[i]);
6132         }
6133         resetCache(this);
6134       }
6135     };
6136
6137     function illegalChildOperation(operation) {
6138       throw new Error(operation + " is not currently supported on child containers");
6139     }
6140
6141     function isSingleton(container, fullName) {
6142       var singleton = option(container, fullName, 'singleton');
6143
6144       return singleton !== false;
6145     }
6146
6147     function buildInjections(container, injections) {
6148       var hash = {};
6149
6150       if (!injections) { return hash; }
6151
6152       var injection, lookup;
6153
6154       for (var i=0, l=injections.length; i<l; i++) {
6155         injection = injections[i];
6156         lookup = container.lookup(injection.fullName);
6157         hash[injection.property] = lookup;
6158       }
6159
6160       return hash;
6161     }
6162
6163     function option(container, fullName, optionName) {
6164       var options = container.options[fullName];
6165
6166       if (options && options[optionName] !== undefined) {
6167         return options[optionName];
6168       }
6169
6170       var type = fullName.split(":")[0];
6171       options = container.typeOptions[type];
6172
6173       if (options) {
6174         return options[optionName];
6175       }
6176     }
6177
6178     function factoryFor(container, fullName) {
6179       return container.resolve(fullName);
6180     }
6181
6182     function instantiate(container, fullName) {
6183       var factory = factoryFor(container, fullName);
6184
6185       var splitName = fullName.split(":"),
6186           type = splitName[0], name = splitName[1],
6187           value;
6188
6189       if (option(container, fullName, 'instantiate') === false) {
6190         return factory;
6191       }
6192
6193       if (factory) {
6194         var injections = [];
6195         injections = injections.concat(container.typeInjections[type] || []);
6196         injections = injections.concat(container.injections[fullName] || []);
6197
6198         var hash = buildInjections(container, injections);
6199         hash.container = container;
6200
6201         value = factory.create(hash);
6202
6203         return value;
6204       }
6205     }
6206
6207     function eachDestroyable(container, callback) {
6208       container.cache.eachLocal(function(key, value) {
6209         if (option(container, key, 'instantiate') === false) { return; }
6210         callback(value);
6211       });
6212     }
6213
6214     function resetCache(container) {
6215       container.cache.eachLocal(function(key, value) {
6216         if (option(container, key, 'instantiate') === false) { return; }
6217         value.destroy();
6218       });
6219       container.cache.dict = {};
6220     }
6221
6222     return Container;
6223 });
6224
6225 })();
6226
6227 (function() {
6228 /*globals ENV */
6229 /**
6230 @module ember
6231 @submodule ember-runtime
6232 */
6233
6234 var indexOf = Ember.EnumerableUtils.indexOf;
6235
6236 // ........................................
6237 // TYPING & ARRAY MESSAGING
6238 //
6239
6240 var TYPE_MAP = {};
6241 var t = "Boolean Number String Function Array Date RegExp Object".split(" ");
6242 Ember.ArrayPolyfills.forEach.call(t, function(name) {
6243   TYPE_MAP[ "[object " + name + "]" ] = name.toLowerCase();
6244 });
6245
6246 var toString = Object.prototype.toString;
6247
6248 /**
6249   Returns a consistent type for the passed item.
6250
6251   Use this instead of the built-in `typeof` to get the type of an item.
6252   It will return the same result across all browsers and includes a bit
6253   more detail. Here is what will be returned:
6254
6255       | Return Value  | Meaning                                              |
6256       |---------------|------------------------------------------------------|
6257       | 'string'      | String primitive                                     |
6258       | 'number'      | Number primitive                                     |
6259       | 'boolean'     | Boolean primitive                                    |
6260       | 'null'        | Null value                                           |
6261       | 'undefined'   | Undefined value                                      |
6262       | 'function'    | A function                                           |
6263       | 'array'       | An instance of Array                                 |
6264       | 'class'       | A Ember class (created using Ember.Object.extend())  |
6265       | 'instance'    | A Ember object instance                              |
6266       | 'error'       | An instance of the Error object                      |
6267       | 'object'      | A JavaScript object not inheriting from Ember.Object |
6268
6269   Examples:
6270
6271   ```javascript
6272   Ember.typeOf();                       // 'undefined'
6273   Ember.typeOf(null);                   // 'null'
6274   Ember.typeOf(undefined);              // 'undefined'
6275   Ember.typeOf('michael');              // 'string'
6276   Ember.typeOf(101);                    // 'number'
6277   Ember.typeOf(true);                   // 'boolean'
6278   Ember.typeOf(Ember.makeArray);        // 'function'
6279   Ember.typeOf([1,2,90]);               // 'array'
6280   Ember.typeOf(Ember.Object.extend());  // 'class'
6281   Ember.typeOf(Ember.Object.create());  // 'instance'
6282   Ember.typeOf(new Error('teamocil'));  // 'error'
6283
6284   // "normal" JavaScript object
6285   Ember.typeOf({a: 'b'});              // 'object'
6286   ```
6287
6288   @method typeOf
6289   @for Ember
6290   @param item {Object} the item to check
6291   @return {String} the type
6292 */
6293 Ember.typeOf = function(item) {
6294   var ret;
6295
6296   ret = (item === null || item === undefined) ? String(item) : TYPE_MAP[toString.call(item)] || 'object';
6297
6298   if (ret === 'function') {
6299     if (Ember.Object && Ember.Object.detect(item)) ret = 'class';
6300   } else if (ret === 'object') {
6301     if (item instanceof Error) ret = 'error';
6302     else if (Ember.Object && item instanceof Ember.Object) ret = 'instance';
6303     else ret = 'object';
6304   }
6305
6306   return ret;
6307 };
6308
6309 /**
6310   Returns true if the passed value is null or undefined. This avoids errors
6311   from JSLint complaining about use of ==, which can be technically
6312   confusing.
6313
6314   ```javascript
6315   Ember.isNone();              // true
6316   Ember.isNone(null);          // true
6317   Ember.isNone(undefined);     // true
6318   Ember.isNone('');            // false
6319   Ember.isNone([]);            // false
6320   Ember.isNone(function(){});  // false
6321   ```
6322
6323   @method isNone
6324   @for Ember
6325   @param {Object} obj Value to test
6326   @return {Boolean}
6327 */
6328 Ember.isNone = function(obj) {
6329   return obj === null || obj === undefined;
6330 };
6331 Ember.none = Ember.deprecateFunc("Ember.none is deprecated. Please use Ember.isNone instead.", Ember.isNone);
6332
6333 /**
6334   Verifies that a value is `null` or an empty string, empty array,
6335   or empty function.
6336
6337   Constrains the rules on `Ember.isNone` by returning false for empty
6338   string and empty arrays.
6339
6340   ```javascript
6341   Ember.isEmpty();                // true
6342   Ember.isEmpty(null);            // true
6343   Ember.isEmpty(undefined);       // true
6344   Ember.isEmpty('');              // true
6345   Ember.isEmpty([]);              // true
6346   Ember.isEmpty('Adam Hawkins');  // false
6347   Ember.isEmpty([0,1,2]);         // false
6348   ```
6349
6350   @method isEmpty
6351   @for Ember
6352   @param {Object} obj Value to test
6353   @return {Boolean}
6354 */
6355 Ember.isEmpty = function(obj) {
6356   return obj === null || obj === undefined || (obj.length === 0 && typeof obj !== 'function') || (typeof obj === 'object' && Ember.get(obj, 'length') === 0);
6357 };
6358 Ember.empty = Ember.deprecateFunc("Ember.empty is deprecated. Please use Ember.isEmpty instead.", Ember.isEmpty) ;
6359
6360 /**
6361  This will compare two javascript values of possibly different types.
6362  It will tell you which one is greater than the other by returning:
6363
6364   - -1 if the first is smaller than the second,
6365   - 0 if both are equal,
6366   - 1 if the first is greater than the second.
6367
6368  The order is calculated based on `Ember.ORDER_DEFINITION`, if types are different.
6369  In case they have the same type an appropriate comparison for this type is made.
6370
6371   ```javascript
6372   Ember.compare('hello', 'hello');  // 0
6373   Ember.compare('abc', 'dfg');      // -1
6374   Ember.compare(2, 1);              // 1
6375   ```javascript
6376
6377  @method compare
6378  @for Ember
6379  @param {Object} v First value to compare
6380  @param {Object} w Second value to compare
6381  @return {Number} -1 if v < w, 0 if v = w and 1 if v > w.
6382 */
6383 Ember.compare = function compare(v, w) {
6384   if (v === w) { return 0; }
6385
6386   var type1 = Ember.typeOf(v);
6387   var type2 = Ember.typeOf(w);
6388
6389   var Comparable = Ember.Comparable;
6390   if (Comparable) {
6391     if (type1==='instance' && Comparable.detect(v.constructor)) {
6392       return v.constructor.compare(v, w);
6393     }
6394
6395     if (type2 === 'instance' && Comparable.detect(w.constructor)) {
6396       return 1-w.constructor.compare(w, v);
6397     }
6398   }
6399
6400   // If we haven't yet generated a reverse-mapping of Ember.ORDER_DEFINITION,
6401   // do so now.
6402   var mapping = Ember.ORDER_DEFINITION_MAPPING;
6403   if (!mapping) {
6404     var order = Ember.ORDER_DEFINITION;
6405     mapping = Ember.ORDER_DEFINITION_MAPPING = {};
6406     var idx, len;
6407     for (idx = 0, len = order.length; idx < len;  ++idx) {
6408       mapping[order[idx]] = idx;
6409     }
6410
6411     // We no longer need Ember.ORDER_DEFINITION.
6412     delete Ember.ORDER_DEFINITION;
6413   }
6414
6415   var type1Index = mapping[type1];
6416   var type2Index = mapping[type2];
6417
6418   if (type1Index < type2Index) { return -1; }
6419   if (type1Index > type2Index) { return 1; }
6420
6421   // types are equal - so we have to check values now
6422   switch (type1) {
6423     case 'boolean':
6424     case 'number':
6425       if (v < w) { return -1; }
6426       if (v > w) { return 1; }
6427       return 0;
6428
6429     case 'string':
6430       var comp = v.localeCompare(w);
6431       if (comp < 0) { return -1; }
6432       if (comp > 0) { return 1; }
6433       return 0;
6434
6435     case 'array':
6436       var vLen = v.length;
6437       var wLen = w.length;
6438       var l = Math.min(vLen, wLen);
6439       var r = 0;
6440       var i = 0;
6441       while (r === 0 && i < l) {
6442         r = compare(v[i],w[i]);
6443         i++;
6444       }
6445       if (r !== 0) { return r; }
6446
6447       // all elements are equal now
6448       // shorter array should be ordered first
6449       if (vLen < wLen) { return -1; }
6450       if (vLen > wLen) { return 1; }
6451       // arrays are equal now
6452       return 0;
6453
6454     case 'instance':
6455       if (Ember.Comparable && Ember.Comparable.detect(v)) {
6456         return v.compare(v, w);
6457       }
6458       return 0;
6459
6460     case 'date':
6461       var vNum = v.getTime();
6462       var wNum = w.getTime();
6463       if (vNum < wNum) { return -1; }
6464       if (vNum > wNum) { return 1; }
6465       return 0;
6466
6467     default:
6468       return 0;
6469   }
6470 };
6471
6472 function _copy(obj, deep, seen, copies) {
6473   var ret, loc, key;
6474
6475   // primitive data types are immutable, just return them.
6476   if ('object' !== typeof obj || obj===null) return obj;
6477
6478   // avoid cyclical loops
6479   if (deep && (loc=indexOf(seen, obj))>=0) return copies[loc];
6480
6481   Ember.assert('Cannot clone an Ember.Object that does not implement Ember.Copyable', !(obj instanceof Ember.Object) || (Ember.Copyable && Ember.Copyable.detect(obj)));
6482
6483   // IMPORTANT: this specific test will detect a native array only. Any other
6484   // object will need to implement Copyable.
6485   if (Ember.typeOf(obj) === 'array') {
6486     ret = obj.slice();
6487     if (deep) {
6488       loc = ret.length;
6489       while(--loc>=0) ret[loc] = _copy(ret[loc], deep, seen, copies);
6490     }
6491   } else if (Ember.Copyable && Ember.Copyable.detect(obj)) {
6492     ret = obj.copy(deep, seen, copies);
6493   } else {
6494     ret = {};
6495     for(key in obj) {
6496       if (!obj.hasOwnProperty(key)) continue;
6497
6498       // Prevents browsers that don't respect non-enumerability from
6499       // copying internal Ember properties
6500       if (key.substring(0,2) === '__') continue;
6501
6502       ret[key] = deep ? _copy(obj[key], deep, seen, copies) : obj[key];
6503     }
6504   }
6505
6506   if (deep) {
6507     seen.push(obj);
6508     copies.push(ret);
6509   }
6510
6511   return ret;
6512 }
6513
6514 /**
6515   Creates a clone of the passed object. This function can take just about
6516   any type of object and create a clone of it, including primitive values
6517   (which are not actually cloned because they are immutable).
6518
6519   If the passed object implements the `clone()` method, then this function
6520   will simply call that method and return the result.
6521
6522   @method copy
6523   @for Ember
6524   @param {Object} object The object to clone
6525   @param {Boolean} deep If true, a deep copy of the object is made
6526   @return {Object} The cloned object
6527 */
6528 Ember.copy = function(obj, deep) {
6529   // fast paths
6530   if ('object' !== typeof obj || obj===null) return obj; // can't copy primitives
6531   if (Ember.Copyable && Ember.Copyable.detect(obj)) return obj.copy(deep);
6532   return _copy(obj, deep, deep ? [] : null, deep ? [] : null);
6533 };
6534
6535 /**
6536   Convenience method to inspect an object. This method will attempt to
6537   convert the object into a useful string description.
6538
6539   It is a pretty simple implementation. If you want something more robust,
6540   use something like JSDump: https://github.com/NV/jsDump
6541
6542   @method inspect
6543   @for Ember
6544   @param {Object} obj The object you want to inspect.
6545   @return {String} A description of the object
6546 */
6547 Ember.inspect = function(obj) {
6548   if (typeof obj !== 'object' || obj === null) {
6549     return obj + '';
6550   }
6551
6552   var v, ret = [];
6553   for(var key in obj) {
6554     if (obj.hasOwnProperty(key)) {
6555       v = obj[key];
6556       if (v === 'toString') { continue; } // ignore useless items
6557       if (Ember.typeOf(v) === 'function') { v = "function() { ... }"; }
6558       ret.push(key + ": " + v);
6559     }
6560   }
6561   return "{" + ret.join(", ") + "}";
6562 };
6563
6564 /**
6565   Compares two objects, returning true if they are logically equal. This is
6566   a deeper comparison than a simple triple equal. For sets it will compare the
6567   internal objects. For any other object that implements `isEqual()` it will
6568   respect that method.
6569
6570   ```javascript
6571   Ember.isEqual('hello', 'hello');  // true
6572   Ember.isEqual(1, 2);              // false
6573   Ember.isEqual([4,2], [4,2]);      // false
6574   ```
6575
6576   @method isEqual
6577   @for Ember
6578   @param {Object} a first object to compare
6579   @param {Object} b second object to compare
6580   @return {Boolean}
6581 */
6582 Ember.isEqual = function(a, b) {
6583   if (a && 'function'===typeof a.isEqual) return a.isEqual(b);
6584   return a === b;
6585 };
6586
6587 // Used by Ember.compare
6588 Ember.ORDER_DEFINITION = Ember.ENV.ORDER_DEFINITION || [
6589   'undefined',
6590   'null',
6591   'boolean',
6592   'number',
6593   'string',
6594   'array',
6595   'object',
6596   'instance',
6597   'function',
6598   'class',
6599   'date'
6600 ];
6601
6602 /**
6603   Returns all of the keys defined on an object or hash. This is useful
6604   when inspecting objects for debugging. On browsers that support it, this
6605   uses the native `Object.keys` implementation.
6606
6607   @method keys
6608   @for Ember
6609   @param {Object} obj
6610   @return {Array} Array containing keys of obj
6611 */
6612 Ember.keys = Object.keys;
6613
6614 if (!Ember.keys) {
6615   Ember.keys = function(obj) {
6616     var ret = [];
6617     for(var key in obj) {
6618       if (obj.hasOwnProperty(key)) { ret.push(key); }
6619     }
6620     return ret;
6621   };
6622 }
6623
6624 // ..........................................................
6625 // ERROR
6626 //
6627
6628 var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
6629
6630 /**
6631   A subclass of the JavaScript Error object for use in Ember.
6632
6633   @class Error
6634   @namespace Ember
6635   @extends Error
6636   @constructor
6637 */
6638 Ember.Error = function() {
6639   var tmp = Error.prototype.constructor.apply(this, arguments);
6640
6641   // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
6642   for (var idx = 0; idx < errorProps.length; idx++) {
6643     this[errorProps[idx]] = tmp[errorProps[idx]];
6644   }
6645 };
6646
6647 Ember.Error.prototype = Ember.create(Error.prototype);
6648
6649 })();
6650
6651
6652
6653 (function() {
6654 /**
6655 @module ember
6656 @submodule ember-runtime
6657 */
6658
6659 var STRING_DASHERIZE_REGEXP = (/[ _]/g);
6660 var STRING_DASHERIZE_CACHE = {};
6661 var STRING_DECAMELIZE_REGEXP = (/([a-z])([A-Z])/g);
6662 var STRING_CAMELIZE_REGEXP = (/(\-|_|\.|\s)+(.)?/g);
6663 var STRING_UNDERSCORE_REGEXP_1 = (/([a-z\d])([A-Z]+)/g);
6664 var STRING_UNDERSCORE_REGEXP_2 = (/\-|\s+/g);
6665
6666 /**
6667   Defines the hash of localized strings for the current language. Used by
6668   the `Ember.String.loc()` helper. To localize, add string values to this
6669   hash.
6670
6671   @property STRINGS
6672   @for Ember
6673   @type Hash
6674 */
6675 Ember.STRINGS = {};
6676
6677 /**
6678   Defines string helper methods including string formatting and localization.
6679   Unless `Ember.EXTEND_PROTOTYPES.String` is `false` these methods will also be
6680   added to the `String.prototype` as well.
6681
6682   @class String
6683   @namespace Ember
6684   @static
6685 */
6686 Ember.String = {
6687
6688   /**
6689     Apply formatting options to the string. This will look for occurrences
6690     of "%@" in your string and substitute them with the arguments you pass into
6691     this method. If you want to control the specific order of replacement,
6692     you can add a number after the key as well to indicate which argument
6693     you want to insert.
6694
6695     Ordered insertions are most useful when building loc strings where values
6696     you need to insert may appear in different orders.
6697
6698     ```javascript
6699     "Hello %@ %@".fmt('John', 'Doe');     // "Hello John Doe"
6700     "Hello %@2, %@1".fmt('John', 'Doe');  // "Hello Doe, John"
6701     ```
6702
6703     @method fmt
6704     @param {Object...} [args]
6705     @return {String} formatted string
6706   */
6707   fmt: function(str, formats) {
6708     // first, replace any ORDERED replacements.
6709     var idx  = 0; // the current index for non-numerical replacements
6710     return str.replace(/%@([0-9]+)?/g, function(s, argIndex) {
6711       argIndex = (argIndex) ? parseInt(argIndex,0) - 1 : idx++ ;
6712       s = formats[argIndex];
6713       return ((s === null) ? '(null)' : (s === undefined) ? '' : s).toString();
6714     }) ;
6715   },
6716
6717   /**
6718     Formats the passed string, but first looks up the string in the localized
6719     strings hash. This is a convenient way to localize text. See
6720     `Ember.String.fmt()` for more information on formatting.
6721
6722     Note that it is traditional but not required to prefix localized string
6723     keys with an underscore or other character so you can easily identify
6724     localized strings.
6725
6726     ```javascript
6727     Ember.STRINGS = {
6728       '_Hello World': 'Bonjour le monde',
6729       '_Hello %@ %@': 'Bonjour %@ %@'
6730     };
6731
6732     Ember.String.loc("_Hello World");  // 'Bonjour le monde';
6733     Ember.String.loc("_Hello %@ %@", ["John", "Smith"]);  // "Bonjour John Smith";
6734     ```
6735
6736     @method loc
6737     @param {String} str The string to format
6738     @param {Array} formats Optional array of parameters to interpolate into string.
6739     @return {String} formatted string
6740   */
6741   loc: function(str, formats) {
6742     str = Ember.STRINGS[str] || str;
6743     return Ember.String.fmt(str, formats) ;
6744   },
6745
6746   /**
6747     Splits a string into separate units separated by spaces, eliminating any
6748     empty strings in the process. This is a convenience method for split that
6749     is mostly useful when applied to the `String.prototype`.
6750
6751     ```javascript
6752     Ember.String.w("alpha beta gamma").forEach(function(key) {
6753       console.log(key);
6754     });
6755
6756     // > alpha
6757     // > beta
6758     // > gamma
6759     ```
6760
6761     @method w
6762     @param {String} str The string to split
6763     @return {String} split string
6764   */
6765   w: function(str) { return str.split(/\s+/); },
6766
6767   /**
6768     Converts a camelized string into all lower case separated by underscores.
6769
6770     ```javascript
6771     'innerHTML'.decamelize();           // 'inner_html'
6772     'action_name'.decamelize();        // 'action_name'
6773     'css-class-name'.decamelize();     // 'css-class-name'
6774     'my favorite items'.decamelize();  // 'my favorite items'
6775     ```
6776
6777     @method decamelize
6778     @param {String} str The string to decamelize.
6779     @return {String} the decamelized string.
6780   */
6781   decamelize: function(str) {
6782     return str.replace(STRING_DECAMELIZE_REGEXP, '$1_$2').toLowerCase();
6783   },
6784
6785   /**
6786     Replaces underscores or spaces with dashes.
6787
6788     ```javascript
6789     'innerHTML'.dasherize();          // 'inner-html'
6790     'action_name'.dasherize();        // 'action-name'
6791     'css-class-name'.dasherize();     // 'css-class-name'
6792     'my favorite items'.dasherize();  // 'my-favorite-items'
6793     ```
6794
6795     @method dasherize
6796     @param {String} str The string to dasherize.
6797     @return {String} the dasherized string.
6798   */
6799   dasherize: function(str) {
6800     var cache = STRING_DASHERIZE_CACHE,
6801         ret   = cache[str];
6802
6803     if (ret) {
6804       return ret;
6805     } else {
6806       ret = Ember.String.decamelize(str).replace(STRING_DASHERIZE_REGEXP,'-');
6807       cache[str] = ret;
6808     }
6809
6810     return ret;
6811   },
6812
6813   /**
6814     Returns the lowerCaseCamel form of a string.
6815
6816     ```javascript
6817     'innerHTML'.camelize();          // 'innerHTML'
6818     'action_name'.camelize();        // 'actionName'
6819     'css-class-name'.camelize();     // 'cssClassName'
6820     'my favorite items'.camelize();  // 'myFavoriteItems'
6821     ```
6822
6823     @method camelize
6824     @param {String} str The string to camelize.
6825     @return {String} the camelized string.
6826   */
6827   camelize: function(str) {
6828     return str.replace(STRING_CAMELIZE_REGEXP, function(match, separator, chr) {
6829       return chr ? chr.toUpperCase() : '';
6830     });
6831   },
6832
6833   /**
6834     Returns the UpperCamelCase form of a string.
6835
6836     ```javascript
6837     'innerHTML'.classify();          // 'InnerHTML'
6838     'action_name'.classify();        // 'ActionName'
6839     'css-class-name'.classify();     // 'CssClassName'
6840     'my favorite items'.classify();  // 'MyFavoriteItems'
6841     ``` 
6842
6843     @method classify
6844     @param {String} str the string to classify
6845     @return {String} the classified string
6846   */
6847   classify: function(str) {
6848     var parts = str.split("."),
6849         out = [];
6850
6851     for (var i=0, l=parts.length; i<l; i++) {
6852       var camelized = Ember.String.camelize(parts[i]);
6853       out.push(camelized.charAt(0).toUpperCase() + camelized.substr(1));
6854     }
6855
6856     return out.join(".");
6857   },
6858
6859   /**
6860     More general than decamelize. Returns the lower\_case\_and\_underscored
6861     form of a string.
6862
6863     ```javascript
6864     'innerHTML'.underscore();          // 'inner_html'
6865     'action_name'.underscore();        // 'action_name'
6866     'css-class-name'.underscore();     // 'css_class_name'
6867     'my favorite items'.underscore();  // 'my_favorite_items'
6868     ```
6869
6870     @method underscore
6871     @param {String} str The string to underscore.
6872     @return {String} the underscored string.
6873   */
6874   underscore: function(str) {
6875     return str.replace(STRING_UNDERSCORE_REGEXP_1, '$1_$2').
6876       replace(STRING_UNDERSCORE_REGEXP_2, '_').toLowerCase();
6877   },
6878
6879   /**
6880     Returns the Capitalized form of a string
6881
6882        'innerHTML'.capitalize()         => 'InnerHTML'
6883        'action_name'.capitalize()       => 'Action_name'
6884        'css-class-name'.capitalize()    => 'Css-class-name'
6885        'my favorite items'.capitalize() => 'My favorite items'
6886
6887     @method capitalize
6888     @param {String} str
6889     @return {String}
6890   */
6891   capitalize: function(str) {
6892     return str.charAt(0).toUpperCase() + str.substr(1);
6893   }
6894
6895 };
6896
6897 })();
6898
6899
6900
6901 (function() {
6902 /**
6903 @module ember
6904 @submodule ember-runtime
6905 */
6906
6907
6908
6909 var fmt = Ember.String.fmt,
6910     w   = Ember.String.w,
6911     loc = Ember.String.loc,
6912     camelize = Ember.String.camelize,
6913     decamelize = Ember.String.decamelize,
6914     dasherize = Ember.String.dasherize,
6915     underscore = Ember.String.underscore,
6916     capitalize = Ember.String.capitalize,
6917     classify = Ember.String.classify;
6918
6919 if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {
6920
6921   /**
6922     See {{#crossLink "Ember.String/fmt"}}{{/crossLink}}
6923
6924     @method fmt
6925     @for String
6926   */
6927   String.prototype.fmt = function() {
6928     return fmt(this, arguments);
6929   };
6930
6931   /**
6932     See {{#crossLink "Ember.String/w"}}{{/crossLink}}
6933
6934     @method w
6935     @for String
6936   */
6937   String.prototype.w = function() {
6938     return w(this);
6939   };
6940
6941   /**
6942     See {{#crossLink "Ember.String/loc"}}{{/crossLink}}
6943
6944     @method loc
6945     @for String
6946   */
6947   String.prototype.loc = function() {
6948     return loc(this, arguments);
6949   };
6950
6951   /**
6952     See {{#crossLink "Ember.String/camelize"}}{{/crossLink}}
6953
6954     @method camelize
6955     @for String
6956   */
6957   String.prototype.camelize = function() {
6958     return camelize(this);
6959   };
6960
6961   /**
6962     See {{#crossLink "Ember.String/decamelize"}}{{/crossLink}}
6963
6964     @method decamelize
6965     @for String
6966   */
6967   String.prototype.decamelize = function() {
6968     return decamelize(this);
6969   };
6970
6971   /**
6972     See {{#crossLink "Ember.String/dasherize"}}{{/crossLink}}
6973
6974     @method dasherize
6975     @for String
6976   */
6977   String.prototype.dasherize = function() {
6978     return dasherize(this);
6979   };
6980
6981   /**
6982     See {{#crossLink "Ember.String/underscore"}}{{/crossLink}}
6983
6984     @method underscore
6985     @for String
6986   */
6987   String.prototype.underscore = function() {
6988     return underscore(this);
6989   };
6990
6991   /**
6992     See {{#crossLink "Ember.String/classify"}}{{/crossLink}}
6993
6994     @method classify
6995     @for String
6996   */
6997   String.prototype.classify = function() {
6998     return classify(this);
6999   };
7000
7001   /**
7002     See {{#crossLink "Ember.String/capitalize"}}{{/crossLink}}
7003
7004     @method capitalize
7005     @for String
7006   */
7007   String.prototype.capitalize = function() {
7008     return capitalize(this);
7009   };
7010
7011 }
7012
7013
7014 })();
7015
7016
7017
7018 (function() {
7019 /**
7020 @module ember
7021 @submodule ember-runtime
7022 */
7023
7024 var a_slice = Array.prototype.slice;
7025
7026 if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Function) {
7027
7028   /**
7029     The `property` extension of Javascript's Function prototype is available
7030     when `Ember.EXTEND_PROTOTYPES` or `Ember.EXTEND_PROTOTYPES.Function` is
7031     `true`, which is the default.
7032
7033     Computed properties allow you to treat a function like a property:
7034
7035     ```javascript
7036     MyApp.president = Ember.Object.create({
7037       firstName: "Barack",
7038       lastName: "Obama",
7039
7040       fullName: function() {
7041         return this.get('firstName') + ' ' + this.get('lastName');
7042
7043         // Call this flag to mark the function as a property
7044       }.property()
7045     });
7046
7047     MyApp.president.get('fullName');    // "Barack Obama"
7048     ```
7049
7050     Treating a function like a property is useful because they can work with
7051     bindings, just like any other property.
7052
7053     Many computed properties have dependencies on other properties. For
7054     example, in the above example, the `fullName` property depends on
7055     `firstName` and `lastName` to determine its value. You can tell Ember
7056     about these dependencies like this:
7057
7058     ```javascript
7059     MyApp.president = Ember.Object.create({
7060       firstName: "Barack",
7061       lastName: "Obama",
7062
7063       fullName: function() {
7064         return this.get('firstName') + ' ' + this.get('lastName');
7065
7066         // Tell Ember.js that this computed property depends on firstName
7067         // and lastName
7068       }.property('firstName', 'lastName')
7069     });
7070     ```
7071
7072     Make sure you list these dependencies so Ember knows when to update
7073     bindings that connect to a computed property. Changing a dependency
7074     will not immediately trigger an update of the computed property, but
7075     will instead clear the cache so that it is updated when the next `get`
7076     is called on the property.
7077
7078     See {{#crossLink "Ember.ComputedProperty"}}{{/crossLink}},
7079       {{#crossLink "Ember/computed"}}{{/crossLink}}
7080
7081     @method property
7082     @for Function
7083   */
7084   Function.prototype.property = function() {
7085     var ret = Ember.computed(this);
7086     return ret.property.apply(ret, arguments);
7087   };
7088
7089   /**
7090     The `observes` extension of Javascript's Function prototype is available
7091     when `Ember.EXTEND_PROTOTYPES` or `Ember.EXTEND_PROTOTYPES.Function` is
7092     true, which is the default.
7093
7094     You can observe property changes simply by adding the `observes`
7095     call to the end of your method declarations in classes that you write.
7096     For example:
7097
7098     ```javascript
7099     Ember.Object.create({
7100       valueObserver: function() {
7101         // Executes whenever the "value" property changes
7102       }.observes('value')
7103     });
7104     ```
7105
7106     See {{#crossLink "Ember.Observable/observes"}}{{/crossLink}}
7107
7108     @method observes
7109     @for Function
7110   */
7111   Function.prototype.observes = function() {
7112     this.__ember_observes__ = a_slice.call(arguments);
7113     return this;
7114   };
7115
7116   /**
7117     The `observesBefore` extension of Javascript's Function prototype is
7118     available when `Ember.EXTEND_PROTOTYPES` or
7119     `Ember.EXTEND_PROTOTYPES.Function` is true, which is the default.
7120
7121     You can get notified when a property changes is about to happen by
7122     by adding the `observesBefore` call to the end of your method
7123     declarations in classes that you write. For example:
7124
7125     ```javascript
7126     Ember.Object.create({
7127       valueObserver: function() {
7128         // Executes whenever the "value" property is about to change
7129       }.observesBefore('value')
7130     });
7131     ```
7132
7133     See {{#crossLink "Ember.Observable/observesBefore"}}{{/crossLink}}
7134
7135     @method observesBefore
7136     @for Function
7137   */
7138   Function.prototype.observesBefore = function() {
7139     this.__ember_observesBefore__ = a_slice.call(arguments);
7140     return this;
7141   };
7142
7143 }
7144
7145
7146 })();
7147
7148
7149
7150 (function() {
7151
7152 })();
7153
7154
7155
7156 (function() {
7157 /**
7158 @module ember
7159 @submodule ember-runtime
7160 */
7161
7162 // ..........................................................
7163 // HELPERS
7164 //
7165
7166 var get = Ember.get, set = Ember.set;
7167 var a_slice = Array.prototype.slice;
7168 var a_indexOf = Ember.EnumerableUtils.indexOf;
7169
7170 var contexts = [];
7171
7172 function popCtx() {
7173   return contexts.length===0 ? {} : contexts.pop();
7174 }
7175
7176 function pushCtx(ctx) {
7177   contexts.push(ctx);
7178   return null;
7179 }
7180
7181 function iter(key, value) {
7182   var valueProvided = arguments.length === 2;
7183
7184   function i(item) {
7185     var cur = get(item, key);
7186     return valueProvided ? value===cur : !!cur;
7187   }
7188   return i ;
7189 }
7190
7191 /**
7192   This mixin defines the common interface implemented by enumerable objects
7193   in Ember. Most of these methods follow the standard Array iteration
7194   API defined up to JavaScript 1.8 (excluding language-specific features that
7195   cannot be emulated in older versions of JavaScript).
7196
7197   This mixin is applied automatically to the Array class on page load, so you
7198   can use any of these methods on simple arrays. If Array already implements
7199   one of these methods, the mixin will not override them.
7200
7201   ## Writing Your Own Enumerable
7202
7203   To make your own custom class enumerable, you need two items:
7204
7205   1. You must have a length property. This property should change whenever
7206      the number of items in your enumerable object changes. If you using this
7207      with an `Ember.Object` subclass, you should be sure to change the length
7208      property using `set().`
7209
7210   2. If you must implement `nextObject().` See documentation.
7211
7212   Once you have these two methods implement, apply the `Ember.Enumerable` mixin
7213   to your class and you will be able to enumerate the contents of your object
7214   like any other collection.
7215
7216   ## Using Ember Enumeration with Other Libraries
7217
7218   Many other libraries provide some kind of iterator or enumeration like
7219   facility. This is often where the most common API conflicts occur.
7220   Ember's API is designed to be as friendly as possible with other
7221   libraries by implementing only methods that mostly correspond to the
7222   JavaScript 1.8 API.
7223
7224   @class Enumerable
7225   @namespace Ember
7226   @extends Ember.Mixin
7227   @since Ember 0.9
7228 */
7229 Ember.Enumerable = Ember.Mixin.create(
7230   /** @scope Ember.Enumerable.prototype */ {
7231
7232   // compatibility
7233   isEnumerable: true,
7234
7235   /**
7236     Implement this method to make your class enumerable.
7237
7238     This method will be call repeatedly during enumeration. The index value
7239     will always begin with 0 and increment monotonically. You don't have to
7240     rely on the index value to determine what object to return, but you should
7241     always check the value and start from the beginning when you see the
7242     requested index is 0.
7243
7244     The `previousObject` is the object that was returned from the last call
7245     to `nextObject` for the current iteration. This is a useful way to
7246     manage iteration if you are tracing a linked list, for example.
7247
7248     Finally the context parameter will always contain a hash you can use as
7249     a "scratchpad" to maintain any other state you need in order to iterate
7250     properly. The context object is reused and is not reset between
7251     iterations so make sure you setup the context with a fresh state whenever
7252     the index parameter is 0.
7253
7254     Generally iterators will continue to call `nextObject` until the index
7255     reaches the your current length-1. If you run out of data before this
7256     time for some reason, you should simply return undefined.
7257
7258     The default implementation of this method simply looks up the index.
7259     This works great on any Array-like objects.
7260
7261     @method nextObject
7262     @param {Number} index the current index of the iteration
7263     @param {Object} previousObject the value returned by the last call to 
7264       `nextObject`.
7265     @param {Object} context a context object you can use to maintain state.
7266     @return {Object} the next object in the iteration or undefined
7267   */
7268   nextObject: Ember.required(Function),
7269
7270   /**
7271     Helper method returns the first object from a collection. This is usually
7272     used by bindings and other parts of the framework to extract a single
7273     object if the enumerable contains only one item.
7274
7275     If you override this method, you should implement it so that it will
7276     always return the same value each time it is called. If your enumerable
7277     contains only one object, this method should always return that object.
7278     If your enumerable is empty, this method should return `undefined`.
7279
7280     ```javascript
7281     var arr = ["a", "b", "c"];
7282     arr.firstObject();  // "a"
7283
7284     var arr = [];
7285     arr.firstObject();  // undefined
7286     ```
7287
7288     @property firstObject
7289     @return {Object} the object or undefined
7290   */
7291   firstObject: Ember.computed(function() {
7292     if (get(this, 'length')===0) return undefined ;
7293
7294     // handle generic enumerables
7295     var context = popCtx(), ret;
7296     ret = this.nextObject(0, null, context);
7297     pushCtx(context);
7298     return ret ;
7299   }).property('[]'),
7300
7301   /**
7302     Helper method returns the last object from a collection. If your enumerable
7303     contains only one object, this method should always return that object.
7304     If your enumerable is empty, this method should return `undefined`.
7305
7306     ```javascript
7307     var arr = ["a", "b", "c"];
7308     arr.lastObject();  // "c"
7309
7310     var arr = [];
7311     arr.lastObject();  // undefined
7312     ```
7313
7314     @property lastObject
7315     @return {Object} the last object or undefined
7316   */
7317   lastObject: Ember.computed(function() {
7318     var len = get(this, 'length');
7319     if (len===0) return undefined ;
7320     var context = popCtx(), idx=0, cur, last = null;
7321     do {
7322       last = cur;
7323       cur = this.nextObject(idx++, last, context);
7324     } while (cur !== undefined);
7325     pushCtx(context);
7326     return last;
7327   }).property('[]'),
7328
7329   /**
7330     Returns `true` if the passed object can be found in the receiver. The
7331     default version will iterate through the enumerable until the object
7332     is found. You may want to override this with a more efficient version.
7333
7334     ```javascript
7335     var arr = ["a", "b", "c"];
7336     arr.contains("a"); // true
7337     arr.contains("z"); // false
7338     ```
7339
7340     @method contains
7341     @param {Object} obj The object to search for.
7342     @return {Boolean} `true` if object is found in enumerable.
7343   */
7344   contains: function(obj) {
7345     return this.find(function(item) { return item===obj; }) !== undefined;
7346   },
7347
7348   /**
7349     Iterates through the enumerable, calling the passed function on each
7350     item. This method corresponds to the `forEach()` method defined in
7351     JavaScript 1.6.
7352
7353     The callback method you provide should have the following signature (all
7354     parameters are optional):
7355
7356     ```javascript
7357     function(item, index, enumerable);
7358     ```
7359
7360     - `item` is the current item in the iteration.
7361     - `index` is the current index in the iteration.
7362     - `enumerable` is the enumerable object itself.
7363
7364     Note that in addition to a callback, you can also pass an optional target
7365     object that will be set as `this` on the context. This is a good way
7366     to give your iterator function access to the current object.
7367
7368     @method forEach
7369     @param {Function} callback The callback to execute
7370     @param {Object} [target] The target object to use
7371     @return {Object} receiver
7372   */
7373   forEach: function(callback, target) {
7374     if (typeof callback !== "function") throw new TypeError() ;
7375     var len = get(this, 'length'), last = null, context = popCtx();
7376
7377     if (target === undefined) target = null;
7378
7379     for(var idx=0;idx<len;idx++) {
7380       var next = this.nextObject(idx, last, context) ;
7381       callback.call(target, next, idx, this);
7382       last = next ;
7383     }
7384     last = null ;
7385     context = pushCtx(context);
7386     return this ;
7387   },
7388
7389   /**
7390     Alias for `mapProperty`
7391
7392     @method getEach
7393     @param {String} key name of the property
7394     @return {Array} The mapped array.
7395   */
7396   getEach: function(key) {
7397     return this.mapProperty(key);
7398   },
7399
7400   /**
7401     Sets the value on the named property for each member. This is more
7402     efficient than using other methods defined on this helper. If the object
7403     implements Ember.Observable, the value will be changed to `set(),` otherwise
7404     it will be set directly. `null` objects are skipped.
7405
7406     @method setEach
7407     @param {String} key The key to set
7408     @param {Object} value The object to set
7409     @return {Object} receiver
7410   */
7411   setEach: function(key, value) {
7412     return this.forEach(function(item) {
7413       set(item, key, value);
7414     });
7415   },
7416
7417   /**
7418     Maps all of the items in the enumeration to another value, returning
7419     a new array. This method corresponds to `map()` defined in JavaScript 1.6.
7420
7421     The callback method you provide should have the following signature (all
7422     parameters are optional):
7423
7424     ```javascript
7425     function(item, index, enumerable);
7426     ```
7427
7428     - `item` is the current item in the iteration.
7429     - `index` is the current index in the iteration.
7430     - `enumerable` is the enumerable object itself.
7431
7432     It should return the mapped value.
7433
7434     Note that in addition to a callback, you can also pass an optional target
7435     object that will be set as `this` on the context. This is a good way
7436     to give your iterator function access to the current object.
7437
7438     @method map
7439     @param {Function} callback The callback to execute
7440     @param {Object} [target] The target object to use
7441     @return {Array} The mapped array.
7442   */
7443   map: function(callback, target) {
7444     var ret = [];
7445     this.forEach(function(x, idx, i) {
7446       ret[idx] = callback.call(target, x, idx,i);
7447     });
7448     return ret ;
7449   },
7450
7451   /**
7452     Similar to map, this specialized function returns the value of the named
7453     property on all items in the enumeration.
7454
7455     @method mapProperty
7456     @param {String} key name of the property
7457     @return {Array} The mapped array.
7458   */
7459   mapProperty: function(key) {
7460     return this.map(function(next) {
7461       return get(next, key);
7462     });
7463   },
7464
7465   /**
7466     Returns an array with all of the items in the enumeration that the passed
7467     function returns true for. This method corresponds to `filter()` defined in
7468     JavaScript 1.6.
7469
7470     The callback method you provide should have the following signature (all
7471     parameters are optional):
7472
7473     ```javascript
7474     function(item, index, enumerable);
7475     ```
7476
7477     - `item` is the current item in the iteration.
7478     - `index` is the current index in the iteration.
7479     - `enumerable` is the enumerable object itself.
7480
7481     It should return the `true` to include the item in the results, `false`
7482     otherwise.
7483
7484     Note that in addition to a callback, you can also pass an optional target
7485     object that will be set as `this` on the context. This is a good way
7486     to give your iterator function access to the current object.
7487
7488     @method filter
7489     @param {Function} callback The callback to execute
7490     @param {Object} [target] The target object to use
7491     @return {Array} A filtered array.
7492   */
7493   filter: function(callback, target) {
7494     var ret = [];
7495     this.forEach(function(x, idx, i) {
7496       if (callback.call(target, x, idx, i)) ret.push(x);
7497     });
7498     return ret ;
7499   },
7500
7501   /**
7502     Returns an array with all of the items in the enumeration where the passed
7503     function returns false for. This method is the inverse of filter().
7504
7505     The callback method you provide should have the following signature (all
7506     parameters are optional):
7507
7508           function(item, index, enumerable);
7509
7510     - *item* is the current item in the iteration.
7511     - *index* is the current index in the iteration
7512     - *enumerable* is the enumerable object itself.
7513
7514     It should return the a falsey value to include the item in the results.
7515
7516     Note that in addition to a callback, you can also pass an optional target
7517     object that will be set as "this" on the context. This is a good way
7518     to give your iterator function access to the current object.
7519
7520     @method reject
7521     @param {Function} callback The callback to execute
7522     @param {Object} [target] The target object to use
7523     @return {Array} A rejected array.
7524    */
7525   reject: function(callback, target) {
7526     return this.filter(function() {
7527       return !(callback.apply(target, arguments));
7528     });
7529   },
7530
7531   /**
7532     Returns an array with just the items with the matched property. You
7533     can pass an optional second argument with the target value. Otherwise
7534     this will match any property that evaluates to `true`.
7535
7536     @method filterProperty
7537     @param {String} key the property to test
7538     @param {String} [value] optional value to test against.
7539     @return {Array} filtered array
7540   */
7541   filterProperty: function(key, value) {
7542     return this.filter(iter.apply(this, arguments));
7543   },
7544
7545   /**
7546     Returns an array with the items that do not have truthy values for
7547     key.  You can pass an optional second argument with the target value.  Otherwise
7548     this will match any property that evaluates to false.
7549
7550     @method rejectProperty
7551     @param {String} key the property to test
7552     @param {String} [value] optional value to test against.
7553     @return {Array} rejected array
7554   */
7555   rejectProperty: function(key, value) {
7556     var exactValue = function(item) { return get(item, key) === value; },
7557         hasValue = function(item) { return !!get(item, key); },
7558         use = (arguments.length === 2 ? exactValue : hasValue);
7559
7560     return this.reject(use);
7561   },
7562
7563   /**
7564     Returns the first item in the array for which the callback returns true.
7565     This method works similar to the `filter()` method defined in JavaScript 1.6
7566     except that it will stop working on the array once a match is found.
7567
7568     The callback method you provide should have the following signature (all
7569     parameters are optional):
7570
7571     ```javascript
7572     function(item, index, enumerable);
7573     ```
7574
7575     - `item` is the current item in the iteration.
7576     - `index` is the current index in the iteration.
7577     - `enumerable` is the enumerable object itself.
7578
7579     It should return the `true` to include the item in the results, `false`
7580     otherwise.
7581
7582     Note that in addition to a callback, you can also pass an optional target
7583     object that will be set as `this` on the context. This is a good way
7584     to give your iterator function access to the current object.
7585
7586     @method find
7587     @param {Function} callback The callback to execute
7588     @param {Object} [target] The target object to use
7589     @return {Object} Found item or `null`.
7590   */
7591   find: function(callback, target) {
7592     var len = get(this, 'length') ;
7593     if (target === undefined) target = null;
7594
7595     var last = null, next, found = false, ret ;
7596     var context = popCtx();
7597     for(var idx=0;idx<len && !found;idx++) {
7598       next = this.nextObject(idx, last, context) ;
7599       if (found = callback.call(target, next, idx, this)) ret = next ;
7600       last = next ;
7601     }
7602     next = last = null ;
7603     context = pushCtx(context);
7604     return ret ;
7605   },
7606
7607   /**
7608     Returns the first item with a property matching the passed value. You
7609     can pass an optional second argument with the target value. Otherwise
7610     this will match any property that evaluates to `true`.
7611
7612     This method works much like the more generic `find()` method.
7613
7614     @method findProperty
7615     @param {String} key the property to test
7616     @param {String} [value] optional value to test against.
7617     @return {Object} found item or `null`
7618   */
7619   findProperty: function(key, value) {
7620     return this.find(iter.apply(this, arguments));
7621   },
7622
7623   /**
7624     Returns `true` if the passed function returns true for every item in the
7625     enumeration. This corresponds with the `every()` method in JavaScript 1.6.
7626
7627     The callback method you provide should have the following signature (all
7628     parameters are optional):
7629
7630     ```javascript
7631     function(item, index, enumerable);
7632     ```
7633
7634     - `item` is the current item in the iteration.
7635     - `index` is the current index in the iteration.
7636     - `enumerable` is the enumerable object itself.
7637
7638     It should return the `true` or `false`.
7639
7640     Note that in addition to a callback, you can also pass an optional target
7641     object that will be set as `this` on the context. This is a good way
7642     to give your iterator function access to the current object.
7643
7644     Example Usage:
7645
7646     ```javascript
7647     if (people.every(isEngineer)) { Paychecks.addBigBonus(); }
7648     ```
7649
7650     @method every
7651     @param {Function} callback The callback to execute
7652     @param {Object} [target] The target object to use
7653     @return {Boolean}
7654   */
7655   every: function(callback, target) {
7656     return !this.find(function(x, idx, i) {
7657       return !callback.call(target, x, idx, i);
7658     });
7659   },
7660
7661   /**
7662     Returns `true` if the passed property resolves to `true` for all items in
7663     the enumerable. This method is often simpler/faster than using a callback.
7664
7665     @method everyProperty
7666     @param {String} key the property to test
7667     @param {String} [value] optional value to test against.
7668     @return {Boolean}
7669   */
7670   everyProperty: function(key, value) {
7671     return this.every(iter.apply(this, arguments));
7672   },
7673
7674
7675   /**
7676     Returns `true` if the passed function returns true for any item in the
7677     enumeration. This corresponds with the `every()` method in JavaScript 1.6.
7678
7679     The callback method you provide should have the following signature (all
7680     parameters are optional):
7681
7682     ```javascript
7683     function(item, index, enumerable);
7684     ```
7685
7686     - `item` is the current item in the iteration.
7687     - `index` is the current index in the iteration.
7688     - `enumerable` is the enumerable object itself.
7689
7690     It should return the `true` to include the item in the results, `false`
7691     otherwise.
7692
7693     Note that in addition to a callback, you can also pass an optional target
7694     object that will be set as `this` on the context. This is a good way
7695     to give your iterator function access to the current object.
7696
7697     Usage Example:
7698
7699     ```javascript
7700     if (people.some(isManager)) { Paychecks.addBiggerBonus(); }
7701     ```
7702
7703     @method some
7704     @param {Function} callback The callback to execute
7705     @param {Object} [target] The target object to use
7706     @return {Array} A filtered array.
7707   */
7708   some: function(callback, target) {
7709     return !!this.find(function(x, idx, i) {
7710       return !!callback.call(target, x, idx, i);
7711     });
7712   },
7713
7714   /**
7715     Returns `true` if the passed property resolves to `true` for any item in
7716     the enumerable. This method is often simpler/faster than using a callback.
7717
7718     @method someProperty
7719     @param {String} key the property to test
7720     @param {String} [value] optional value to test against.
7721     @return {Boolean} `true`
7722   */
7723   someProperty: function(key, value) {
7724     return this.some(iter.apply(this, arguments));
7725   },
7726
7727   /**
7728     This will combine the values of the enumerator into a single value. It
7729     is a useful way to collect a summary value from an enumeration. This
7730     corresponds to the `reduce()` method defined in JavaScript 1.8.
7731
7732     The callback method you provide should have the following signature (all
7733     parameters are optional):
7734
7735     ```javascript
7736     function(previousValue, item, index, enumerable);
7737     ```
7738
7739     - `previousValue` is the value returned by the last call to the iterator.
7740     - `item` is the current item in the iteration.
7741     - `index` is the current index in the iteration.
7742     - `enumerable` is the enumerable object itself.
7743
7744     Return the new cumulative value.
7745
7746     In addition to the callback you can also pass an `initialValue`. An error
7747     will be raised if you do not pass an initial value and the enumerator is
7748     empty.
7749
7750     Note that unlike the other methods, this method does not allow you to
7751     pass a target object to set as this for the callback. It's part of the
7752     spec. Sorry.
7753
7754     @method reduce
7755     @param {Function} callback The callback to execute
7756     @param {Object} initialValue Initial value for the reduce
7757     @param {String} reducerProperty internal use only.
7758     @return {Object} The reduced value.
7759   */
7760   reduce: function(callback, initialValue, reducerProperty) {
7761     if (typeof callback !== "function") { throw new TypeError(); }
7762
7763     var ret = initialValue;
7764
7765     this.forEach(function(item, i) {
7766       ret = callback.call(null, ret, item, i, this, reducerProperty);
7767     }, this);
7768
7769     return ret;
7770   },
7771
7772   /**
7773     Invokes the named method on every object in the receiver that
7774     implements it. This method corresponds to the implementation in
7775     Prototype 1.6.
7776
7777     @method invoke
7778     @param {String} methodName the name of the method
7779     @param {Object...} args optional arguments to pass as well.
7780     @return {Array} return values from calling invoke.
7781   */
7782   invoke: function(methodName) {
7783     var args, ret = [];
7784     if (arguments.length>1) args = a_slice.call(arguments, 1);
7785
7786     this.forEach(function(x, idx) {
7787       var method = x && x[methodName];
7788       if ('function' === typeof method) {
7789         ret[idx] = args ? method.apply(x, args) : method.call(x);
7790       }
7791     }, this);
7792
7793     return ret;
7794   },
7795
7796   /**
7797     Simply converts the enumerable into a genuine array. The order is not
7798     guaranteed. Corresponds to the method implemented by Prototype.
7799
7800     @method toArray
7801     @return {Array} the enumerable as an array.
7802   */
7803   toArray: function() {
7804     var ret = [];
7805     this.forEach(function(o, idx) { ret[idx] = o; });
7806     return ret ;
7807   },
7808
7809   /**
7810     Returns a copy of the array with all null elements removed.
7811
7812     ```javascript
7813     var arr = ["a", null, "c", null];
7814     arr.compact();  // ["a", "c"]
7815     ```
7816
7817     @method compact
7818     @return {Array} the array without null elements.
7819   */
7820   compact: function() { return this.without(null); },
7821
7822   /**
7823     Returns a new enumerable that excludes the passed value. The default
7824     implementation returns an array regardless of the receiver type unless
7825     the receiver does not contain the value.
7826
7827     ```javascript
7828     var arr = ["a", "b", "a", "c"];
7829     arr.without("a");  // ["b", "c"]
7830     ```
7831
7832     @method without
7833     @param {Object} value
7834     @return {Ember.Enumerable}
7835   */
7836   without: function(value) {
7837     if (!this.contains(value)) return this; // nothing to do
7838     var ret = [] ;
7839     this.forEach(function(k) {
7840       if (k !== value) ret[ret.length] = k;
7841     }) ;
7842     return ret ;
7843   },
7844
7845   /**
7846     Returns a new enumerable that contains only unique values. The default
7847     implementation returns an array regardless of the receiver type.
7848
7849     ```javascript
7850     var arr = ["a", "a", "b", "b"];
7851     arr.uniq();  // ["a", "b"]
7852     ```
7853
7854     @method uniq
7855     @return {Ember.Enumerable}
7856   */
7857   uniq: function() {
7858     var ret = [];
7859     this.forEach(function(k){
7860       if (a_indexOf(ret, k)<0) ret.push(k);
7861     });
7862     return ret;
7863   },
7864
7865   /**
7866     This property will trigger anytime the enumerable's content changes.
7867     You can observe this property to be notified of changes to the enumerables
7868     content.
7869
7870     For plain enumerables, this property is read only. `Ember.Array` overrides
7871     this method.
7872
7873     @property []
7874     @type Ember.Array
7875   */
7876   '[]': Ember.computed(function(key, value) {
7877     return this;
7878   }),
7879
7880   // ..........................................................
7881   // ENUMERABLE OBSERVERS
7882   //
7883
7884   /**
7885     Registers an enumerable observer. Must implement `Ember.EnumerableObserver`
7886     mixin.
7887
7888     @method addEnumerableObserver
7889     @param target {Object}
7890     @param opts {Hash}
7891   */
7892   addEnumerableObserver: function(target, opts) {
7893     var willChange = (opts && opts.willChange) || 'enumerableWillChange',
7894         didChange  = (opts && opts.didChange) || 'enumerableDidChange';
7895
7896     var hasObservers = get(this, 'hasEnumerableObservers');
7897     if (!hasObservers) Ember.propertyWillChange(this, 'hasEnumerableObservers');
7898     Ember.addListener(this, '@enumerable:before', target, willChange);
7899     Ember.addListener(this, '@enumerable:change', target, didChange);
7900     if (!hasObservers) Ember.propertyDidChange(this, 'hasEnumerableObservers');
7901     return this;
7902   },
7903
7904   /**
7905     Removes a registered enumerable observer.
7906
7907     @method removeEnumerableObserver
7908     @param target {Object}
7909     @param [opts] {Hash}
7910   */
7911   removeEnumerableObserver: function(target, opts) {
7912     var willChange = (opts && opts.willChange) || 'enumerableWillChange',
7913         didChange  = (opts && opts.didChange) || 'enumerableDidChange';
7914
7915     var hasObservers = get(this, 'hasEnumerableObservers');
7916     if (hasObservers) Ember.propertyWillChange(this, 'hasEnumerableObservers');
7917     Ember.removeListener(this, '@enumerable:before', target, willChange);
7918     Ember.removeListener(this, '@enumerable:change', target, didChange);
7919     if (hasObservers) Ember.propertyDidChange(this, 'hasEnumerableObservers');
7920     return this;
7921   },
7922
7923   /**
7924     Becomes true whenever the array currently has observers watching changes
7925     on the array.
7926
7927     @property hasEnumerableObservers
7928     @type Boolean
7929   */
7930   hasEnumerableObservers: Ember.computed(function() {
7931     return Ember.hasListeners(this, '@enumerable:change') || Ember.hasListeners(this, '@enumerable:before');
7932   }),
7933
7934
7935   /**
7936     Invoke this method just before the contents of your enumerable will
7937     change. You can either omit the parameters completely or pass the objects
7938     to be removed or added if available or just a count.
7939
7940     @method enumerableContentWillChange
7941     @param {Ember.Enumerable|Number} removing An enumerable of the objects to
7942       be removed or the number of items to be removed.
7943     @param {Ember.Enumerable|Number} adding An enumerable of the objects to be
7944       added or the number of items to be added.
7945     @chainable
7946   */
7947   enumerableContentWillChange: function(removing, adding) {
7948
7949     var removeCnt, addCnt, hasDelta;
7950
7951     if ('number' === typeof removing) removeCnt = removing;
7952     else if (removing) removeCnt = get(removing, 'length');
7953     else removeCnt = removing = -1;
7954
7955     if ('number' === typeof adding) addCnt = adding;
7956     else if (adding) addCnt = get(adding,'length');
7957     else addCnt = adding = -1;
7958
7959     hasDelta = addCnt<0 || removeCnt<0 || addCnt-removeCnt!==0;
7960
7961     if (removing === -1) removing = null;
7962     if (adding   === -1) adding   = null;
7963
7964     Ember.propertyWillChange(this, '[]');
7965     if (hasDelta) Ember.propertyWillChange(this, 'length');
7966     Ember.sendEvent(this, '@enumerable:before', [this, removing, adding]);
7967
7968     return this;
7969   },
7970
7971   /**
7972     Invoke this method when the contents of your enumerable has changed.
7973     This will notify any observers watching for content changes. If your are
7974     implementing an ordered enumerable (such as an array), also pass the
7975     start and end values where the content changed so that it can be used to
7976     notify range observers.
7977
7978     @method enumerableContentDidChange
7979     @param {Number} [start] optional start offset for the content change.
7980       For unordered enumerables, you should always pass -1.
7981     @param {Ember.Enumerable|Number} removing An enumerable of the objects to
7982       be removed or the number of items to be removed.
7983     @param {Ember.Enumerable|Number} adding  An enumerable of the objects to
7984       be added or the number of items to be added.
7985     @chainable
7986   */
7987   enumerableContentDidChange: function(removing, adding) {
7988     var notify = this.propertyDidChange, removeCnt, addCnt, hasDelta;
7989
7990     if ('number' === typeof removing) removeCnt = removing;
7991     else if (removing) removeCnt = get(removing, 'length');
7992     else removeCnt = removing = -1;
7993
7994     if ('number' === typeof adding) addCnt = adding;
7995     else if (adding) addCnt = get(adding, 'length');
7996     else addCnt = adding = -1;
7997
7998     hasDelta = addCnt<0 || removeCnt<0 || addCnt-removeCnt!==0;
7999
8000     if (removing === -1) removing = null;
8001     if (adding   === -1) adding   = null;
8002
8003     Ember.sendEvent(this, '@enumerable:change', [this, removing, adding]);
8004     if (hasDelta) Ember.propertyDidChange(this, 'length');
8005     Ember.propertyDidChange(this, '[]');
8006
8007     return this ;
8008   }
8009
8010 }) ;
8011
8012 })();
8013
8014
8015
8016 (function() {
8017 /**
8018 @module ember
8019 @submodule ember-runtime
8020 */
8021
8022 // ..........................................................
8023 // HELPERS
8024 //
8025
8026 var get = Ember.get, set = Ember.set, meta = Ember.meta, map = Ember.EnumerableUtils.map, cacheFor = Ember.cacheFor;
8027
8028 function none(obj) { return obj===null || obj===undefined; }
8029
8030 // ..........................................................
8031 // ARRAY
8032 //
8033 /**
8034   This module implements Observer-friendly Array-like behavior. This mixin is
8035   picked up by the Array class as well as other controllers, etc. that want to
8036   appear to be arrays.
8037
8038   Unlike `Ember.Enumerable,` this mixin defines methods specifically for
8039   collections that provide index-ordered access to their contents. When you
8040   are designing code that needs to accept any kind of Array-like object, you
8041   should use these methods instead of Array primitives because these will
8042   properly notify observers of changes to the array.
8043
8044   Although these methods are efficient, they do add a layer of indirection to
8045   your application so it is a good idea to use them only when you need the
8046   flexibility of using both true JavaScript arrays and "virtual" arrays such
8047   as controllers and collections.
8048
8049   You can use the methods defined in this module to access and modify array
8050   contents in a KVO-friendly way. You can also be notified whenever the
8051   membership if an array changes by changing the syntax of the property to
8052   `.observes('*myProperty.[]')`.
8053
8054   To support `Ember.Array` in your own class, you must override two
8055   primitives to use it: `replace()` and `objectAt()`.
8056
8057   Note that the Ember.Array mixin also incorporates the `Ember.Enumerable`
8058   mixin. All `Ember.Array`-like objects are also enumerable.
8059
8060   @class Array
8061   @namespace Ember
8062   @extends Ember.Mixin
8063   @uses Ember.Enumerable
8064   @since Ember 0.9.0
8065 */
8066 Ember.Array = Ember.Mixin.create(Ember.Enumerable, /** @scope Ember.Array.prototype */ {
8067
8068   // compatibility
8069   isSCArray: true,
8070
8071   /**
8072     Your array must support the `length` property. Your replace methods should
8073     set this property whenever it changes.
8074
8075     @property {Number} length
8076   */
8077   length: Ember.required(),
8078
8079   /**
8080     Returns the object at the given `index`. If the given `index` is negative
8081     or is greater or equal than the array length, returns `undefined`.
8082
8083     This is one of the primitives you must implement to support `Ember.Array`.
8084     If your object supports retrieving the value of an array item using `get()`
8085     (i.e. `myArray.get(0)`), then you do not need to implement this method
8086     yourself.
8087
8088     ```javascript
8089     var arr = ['a', 'b', 'c', 'd'];
8090     arr.objectAt(0);   // "a"
8091     arr.objectAt(3);   // "d"
8092     arr.objectAt(-1);  // undefined
8093     arr.objectAt(4);   // undefined
8094     arr.objectAt(5);   // undefined
8095     ```
8096
8097     @method objectAt
8098     @param {Number} idx The index of the item to return.
8099   */
8100   objectAt: function(idx) {
8101     if ((idx < 0) || (idx>=get(this, 'length'))) return undefined ;
8102     return get(this, idx);
8103   },
8104
8105   /**
8106     This returns the objects at the specified indexes, using `objectAt`.
8107
8108     ```javascript
8109     var arr = ['a', 'b', 'c', 'd'];
8110     arr.objectsAt([0, 1, 2]);  // ["a", "b", "c"]
8111     arr.objectsAt([2, 3, 4]);  // ["c", "d", undefined]
8112     ```
8113
8114     @method objectsAt
8115     @param {Array} indexes An array of indexes of items to return.
8116    */
8117   objectsAt: function(indexes) {
8118     var self = this;
8119     return map(indexes, function(idx){ return self.objectAt(idx); });
8120   },
8121
8122   // overrides Ember.Enumerable version
8123   nextObject: function(idx) {
8124     return this.objectAt(idx);
8125   },
8126
8127   /**
8128     This is the handler for the special array content property. If you get
8129     this property, it will return this. If you set this property it a new
8130     array, it will replace the current content.
8131
8132     This property overrides the default property defined in `Ember.Enumerable`.
8133
8134     @property []
8135   */
8136   '[]': Ember.computed(function(key, value) {
8137     if (value !== undefined) this.replace(0, get(this, 'length'), value) ;
8138     return this ;
8139   }),
8140
8141   firstObject: Ember.computed(function() {
8142     return this.objectAt(0);
8143   }),
8144
8145   lastObject: Ember.computed(function() {
8146     return this.objectAt(get(this, 'length')-1);
8147   }),
8148
8149   // optimized version from Enumerable
8150   contains: function(obj){
8151     return this.indexOf(obj) >= 0;
8152   },
8153
8154   // Add any extra methods to Ember.Array that are native to the built-in Array.
8155   /**
8156     Returns a new array that is a slice of the receiver. This implementation
8157     uses the observable array methods to retrieve the objects for the new
8158     slice.
8159
8160     ```javascript
8161     var arr = ['red', 'green', 'blue'];
8162     arr.slice(0);       // ['red', 'green', 'blue']
8163     arr.slice(0, 2);    // ['red', 'green']
8164     arr.slice(1, 100);  // ['green', 'blue']
8165     ```
8166
8167     @method slice
8168     @param beginIndex {Integer} (Optional) index to begin slicing from.
8169     @param endIndex {Integer} (Optional) index to end the slice at.
8170     @return {Array} New array with specified slice
8171   */
8172   slice: function(beginIndex, endIndex) {
8173     var ret = [];
8174     var length = get(this, 'length') ;
8175     if (none(beginIndex)) beginIndex = 0 ;
8176     if (none(endIndex) || (endIndex > length)) endIndex = length ;
8177     while(beginIndex < endIndex) {
8178       ret[ret.length] = this.objectAt(beginIndex++) ;
8179     }
8180     return ret ;
8181   },
8182
8183   /**
8184     Returns the index of the given object's first occurrence.
8185     If no `startAt` argument is given, the starting location to
8186     search is 0. If it's negative, will count backward from
8187     the end of the array. Returns -1 if no match is found.
8188
8189     ```javascript
8190     var arr = ["a", "b", "c", "d", "a"];
8191     arr.indexOf("a");       //  0
8192     arr.indexOf("z");       // -1
8193     arr.indexOf("a", 2);    //  4
8194     arr.indexOf("a", -1);   //  4
8195     arr.indexOf("b", 3);    // -1
8196     arr.indexOf("a", 100);  // -1
8197     ```javascript
8198
8199     @method indexOf
8200     @param {Object} object the item to search for
8201     @param {Number} startAt optional starting location to search, default 0
8202     @return {Number} index or -1 if not found
8203   */
8204   indexOf: function(object, startAt) {
8205     var idx, len = get(this, 'length');
8206
8207     if (startAt === undefined) startAt = 0;
8208     if (startAt < 0) startAt += len;
8209
8210     for(idx=startAt;idx<len;idx++) {
8211       if (this.objectAt(idx, true) === object) return idx ;
8212     }
8213     return -1;
8214   },
8215
8216   /**
8217     Returns the index of the given object's last occurrence.
8218     If no `startAt` argument is given, the search starts from
8219     the last position. If it's negative, will count backward
8220     from the end of the array. Returns -1 if no match is found.
8221
8222     ```javascript
8223     var arr = ["a", "b", "c", "d", "a"];
8224     arr.lastIndexOf("a");       //  4
8225     arr.lastIndexOf("z");       // -1
8226     arr.lastIndexOf("a", 2);    //  0
8227     arr.lastIndexOf("a", -1);   //  4
8228     arr.lastIndexOf("b", 3);    //  1
8229     arr.lastIndexOf("a", 100);  //  4
8230     ```
8231
8232     @method lastIndexOf
8233     @param {Object} object the item to search for
8234     @param {Number} startAt optional starting location to search, default 0
8235     @return {Number} index or -1 if not found
8236   */
8237   lastIndexOf: function(object, startAt) {
8238     var idx, len = get(this, 'length');
8239
8240     if (startAt === undefined || startAt >= len) startAt = len-1;
8241     if (startAt < 0) startAt += len;
8242
8243     for(idx=startAt;idx>=0;idx--) {
8244       if (this.objectAt(idx) === object) return idx ;
8245     }
8246     return -1;
8247   },
8248
8249   // ..........................................................
8250   // ARRAY OBSERVERS
8251   //
8252
8253   /**
8254     Adds an array observer to the receiving array. The array observer object
8255     normally must implement two methods:
8256
8257     * `arrayWillChange(start, removeCount, addCount)` - This method will be
8258       called just before the array is modified.
8259     * `arrayDidChange(start, removeCount, addCount)` - This method will be
8260       called just after the array is modified.
8261
8262     Both callbacks will be passed the starting index of the change as well a
8263     a count of the items to be removed and added. You can use these callbacks
8264     to optionally inspect the array during the change, clear caches, or do
8265     any other bookkeeping necessary.
8266
8267     In addition to passing a target, you can also include an options hash
8268     which you can use to override the method names that will be invoked on the
8269     target.
8270
8271     @method addArrayObserver
8272     @param {Object} target The observer object.
8273     @param {Hash} opts Optional hash of configuration options including
8274       `willChange`, `didChange`, and a `context` option.
8275     @return {Ember.Array} receiver
8276   */
8277   addArrayObserver: function(target, opts) {
8278     var willChange = (opts && opts.willChange) || 'arrayWillChange',
8279         didChange  = (opts && opts.didChange) || 'arrayDidChange';
8280
8281     var hasObservers = get(this, 'hasArrayObservers');
8282     if (!hasObservers) Ember.propertyWillChange(this, 'hasArrayObservers');
8283     Ember.addListener(this, '@array:before', target, willChange);
8284     Ember.addListener(this, '@array:change', target, didChange);
8285     if (!hasObservers) Ember.propertyDidChange(this, 'hasArrayObservers');
8286     return this;
8287   },
8288
8289   /**
8290     Removes an array observer from the object if the observer is current
8291     registered. Calling this method multiple times with the same object will
8292     have no effect.
8293
8294     @method removeArrayObserver
8295     @param {Object} target The object observing the array.
8296     @return {Ember.Array} receiver
8297   */
8298   removeArrayObserver: function(target, opts) {
8299     var willChange = (opts && opts.willChange) || 'arrayWillChange',
8300         didChange  = (opts && opts.didChange) || 'arrayDidChange';
8301
8302     var hasObservers = get(this, 'hasArrayObservers');
8303     if (hasObservers) Ember.propertyWillChange(this, 'hasArrayObservers');
8304     Ember.removeListener(this, '@array:before', target, willChange);
8305     Ember.removeListener(this, '@array:change', target, didChange);
8306     if (hasObservers) Ember.propertyDidChange(this, 'hasArrayObservers');
8307     return this;
8308   },
8309
8310   /**
8311     Becomes true whenever the array currently has observers watching changes
8312     on the array.
8313
8314     @property Boolean
8315   */
8316   hasArrayObservers: Ember.computed(function() {
8317     return Ember.hasListeners(this, '@array:change') || Ember.hasListeners(this, '@array:before');
8318   }),
8319
8320   /**
8321     If you are implementing an object that supports `Ember.Array`, call this
8322     method just before the array content changes to notify any observers and
8323     invalidate any related properties. Pass the starting index of the change
8324     as well as a delta of the amounts to change.
8325
8326     @method arrayContentWillChange
8327     @param {Number} startIdx The starting index in the array that will change.
8328     @param {Number} removeAmt The number of items that will be removed. If you 
8329       pass `null` assumes 0
8330     @param {Number} addAmt The number of items that will be added  If you 
8331       pass `null` assumes 0.
8332     @return {Ember.Array} receiver
8333   */
8334   arrayContentWillChange: function(startIdx, removeAmt, addAmt) {
8335
8336     // if no args are passed assume everything changes
8337     if (startIdx===undefined) {
8338       startIdx = 0;
8339       removeAmt = addAmt = -1;
8340     } else {
8341       if (removeAmt === undefined) removeAmt=-1;
8342       if (addAmt    === undefined) addAmt=-1;
8343     }
8344
8345     // Make sure the @each proxy is set up if anyone is observing @each
8346     if (Ember.isWatching(this, '@each')) { get(this, '@each'); }
8347
8348     Ember.sendEvent(this, '@array:before', [this, startIdx, removeAmt, addAmt]);
8349
8350     var removing, lim;
8351     if (startIdx>=0 && removeAmt>=0 && get(this, 'hasEnumerableObservers')) {
8352       removing = [];
8353       lim = startIdx+removeAmt;
8354       for(var idx=startIdx;idx<lim;idx++) removing.push(this.objectAt(idx));
8355     } else {
8356       removing = removeAmt;
8357     }
8358
8359     this.enumerableContentWillChange(removing, addAmt);
8360
8361     return this;
8362   },
8363
8364   arrayContentDidChange: function(startIdx, removeAmt, addAmt) {
8365
8366     // if no args are passed assume everything changes
8367     if (startIdx===undefined) {
8368       startIdx = 0;
8369       removeAmt = addAmt = -1;
8370     } else {
8371       if (removeAmt === undefined) removeAmt=-1;
8372       if (addAmt    === undefined) addAmt=-1;
8373     }
8374
8375     var adding, lim;
8376     if (startIdx>=0 && addAmt>=0 && get(this, 'hasEnumerableObservers')) {
8377       adding = [];
8378       lim = startIdx+addAmt;
8379       for(var idx=startIdx;idx<lim;idx++) adding.push(this.objectAt(idx));
8380     } else {
8381       adding = addAmt;
8382     }
8383
8384     this.enumerableContentDidChange(removeAmt, adding);
8385     Ember.sendEvent(this, '@array:change', [this, startIdx, removeAmt, addAmt]);
8386
8387     var length      = get(this, 'length'),
8388         cachedFirst = cacheFor(this, 'firstObject'),
8389         cachedLast  = cacheFor(this, 'lastObject');
8390     if (this.objectAt(0) !== cachedFirst) {
8391       Ember.propertyWillChange(this, 'firstObject');
8392       Ember.propertyDidChange(this, 'firstObject');
8393     }
8394     if (this.objectAt(length-1) !== cachedLast) {
8395       Ember.propertyWillChange(this, 'lastObject');
8396       Ember.propertyDidChange(this, 'lastObject');
8397     }
8398
8399     return this;
8400   },
8401
8402   // ..........................................................
8403   // ENUMERATED PROPERTIES
8404   //
8405
8406   /**
8407     Returns a special object that can be used to observe individual properties
8408     on the array. Just get an equivalent property on this object and it will
8409     return an enumerable that maps automatically to the named key on the
8410     member objects.
8411
8412     @property @each
8413   */
8414   '@each': Ember.computed(function() {
8415     if (!this.__each) this.__each = new Ember.EachProxy(this);
8416     return this.__each;
8417   })
8418
8419 }) ;
8420
8421 })();
8422
8423
8424
8425 (function() {
8426 /**
8427 @module ember
8428 @submodule ember-runtime
8429 */
8430
8431
8432 /**
8433   Implements some standard methods for comparing objects. Add this mixin to
8434   any class you create that can compare its instances.
8435
8436   You should implement the `compare()` method.
8437
8438   @class Comparable
8439   @namespace Ember
8440   @extends Ember.Mixin
8441   @since Ember 0.9
8442 */
8443 Ember.Comparable = Ember.Mixin.create( /** @scope Ember.Comparable.prototype */{
8444
8445   /**
8446     walk like a duck. Indicates that the object can be compared.
8447
8448     @property isComparable
8449     @type Boolean
8450     @default true
8451   */
8452   isComparable: true,
8453
8454   /**
8455     Override to return the result of the comparison of the two parameters. The
8456     compare method should return:
8457
8458     - `-1` if `a < b`
8459     - `0` if `a == b`
8460     - `1` if `a > b`
8461
8462     Default implementation raises an exception.
8463
8464     @method compare
8465     @param a {Object} the first object to compare
8466     @param b {Object} the second object to compare
8467     @return {Integer} the result of the comparison
8468   */
8469   compare: Ember.required(Function)
8470
8471 });
8472
8473
8474 })();
8475
8476
8477
8478 (function() {
8479 /**
8480 @module ember
8481 @submodule ember-runtime
8482 */
8483
8484
8485
8486 var get = Ember.get, set = Ember.set;
8487
8488 /**
8489   Implements some standard methods for copying an object. Add this mixin to
8490   any object you create that can create a copy of itself. This mixin is
8491   added automatically to the built-in array.
8492
8493   You should generally implement the `copy()` method to return a copy of the
8494   receiver.
8495
8496   Note that `frozenCopy()` will only work if you also implement
8497   `Ember.Freezable`.
8498
8499   @class Copyable
8500   @namespace Ember
8501   @extends Ember.Mixin
8502   @since Ember 0.9
8503 */
8504 Ember.Copyable = Ember.Mixin.create(
8505 /** @scope Ember.Copyable.prototype */ {
8506
8507   /**
8508     Override to return a copy of the receiver. Default implementation raises
8509     an exception.
8510
8511     @method copy
8512     @param deep {Boolean} if `true`, a deep copy of the object should be made
8513     @return {Object} copy of receiver
8514   */
8515   copy: Ember.required(Function),
8516
8517   /**
8518     If the object implements `Ember.Freezable`, then this will return a new
8519     copy if the object is not frozen and the receiver if the object is frozen.
8520
8521     Raises an exception if you try to call this method on a object that does
8522     not support freezing.
8523
8524     You should use this method whenever you want a copy of a freezable object
8525     since a freezable object can simply return itself without actually
8526     consuming more memory.
8527
8528     @method frozenCopy
8529     @return {Object} copy of receiver or receiver
8530   */
8531   frozenCopy: function() {
8532     if (Ember.Freezable && Ember.Freezable.detect(this)) {
8533       return get(this, 'isFrozen') ? this : this.copy().freeze();
8534     } else {
8535       throw new Error(Ember.String.fmt("%@ does not support freezing", [this]));
8536     }
8537   }
8538 });
8539
8540 })();
8541
8542
8543
8544 (function() {
8545 /**
8546 @module ember
8547 @submodule ember-runtime
8548 */
8549
8550
8551 var get = Ember.get, set = Ember.set;
8552
8553 /**
8554   The `Ember.Freezable` mixin implements some basic methods for marking an
8555   object as frozen. Once an object is frozen it should be read only. No changes
8556   may be made the internal state of the object.
8557
8558   ## Enforcement
8559
8560   To fully support freezing in your subclass, you must include this mixin and
8561   override any method that might alter any property on the object to instead
8562   raise an exception. You can check the state of an object by checking the
8563   `isFrozen` property.
8564
8565   Although future versions of JavaScript may support language-level freezing
8566   object objects, that is not the case today. Even if an object is freezable,
8567   it is still technically possible to modify the object, even though it could
8568   break other parts of your application that do not expect a frozen object to
8569   change. It is, therefore, very important that you always respect the
8570   `isFrozen` property on all freezable objects.
8571
8572   ## Example Usage
8573
8574   The example below shows a simple object that implement the `Ember.Freezable`
8575   protocol.
8576
8577   ```javascript
8578   Contact = Ember.Object.extend(Ember.Freezable, {
8579     firstName: null,
8580     lastName: null,
8581
8582     // swaps the names
8583     swapNames: function() {
8584       if (this.get('isFrozen')) throw Ember.FROZEN_ERROR;
8585       var tmp = this.get('firstName');
8586       this.set('firstName', this.get('lastName'));
8587       this.set('lastName', tmp);
8588       return this;
8589     }
8590
8591   });
8592
8593   c = Context.create({ firstName: "John", lastName: "Doe" });
8594   c.swapNames();  // returns c
8595   c.freeze();
8596   c.swapNames();  // EXCEPTION
8597   ```
8598
8599   ## Copying
8600
8601   Usually the `Ember.Freezable` protocol is implemented in cooperation with the
8602   `Ember.Copyable` protocol, which defines a `frozenCopy()` method that will
8603   return a frozen object, if the object implements this method as well.
8604
8605   @class Freezable
8606   @namespace Ember
8607   @extends Ember.Mixin
8608   @since Ember 0.9
8609 */
8610 Ember.Freezable = Ember.Mixin.create(
8611 /** @scope Ember.Freezable.prototype */ {
8612
8613   /**
8614     Set to `true` when the object is frozen. Use this property to detect
8615     whether your object is frozen or not.
8616
8617     @property isFrozen
8618     @type Boolean
8619   */
8620   isFrozen: false,
8621
8622   /**
8623     Freezes the object. Once this method has been called the object should
8624     no longer allow any properties to be edited.
8625
8626     @method freeze
8627     @return {Object} receiver
8628   */
8629   freeze: function() {
8630     if (get(this, 'isFrozen')) return this;
8631     set(this, 'isFrozen', true);
8632     return this;
8633   }
8634
8635 });
8636
8637 Ember.FROZEN_ERROR = "Frozen object cannot be modified.";
8638
8639 })();
8640
8641
8642
8643 (function() {
8644 /**
8645 @module ember
8646 @submodule ember-runtime
8647 */
8648
8649 var forEach = Ember.EnumerableUtils.forEach;
8650
8651 /**
8652   This mixin defines the API for modifying generic enumerables. These methods
8653   can be applied to an object regardless of whether it is ordered or
8654   unordered.
8655
8656   Note that an Enumerable can change even if it does not implement this mixin.
8657   For example, a MappedEnumerable cannot be directly modified but if its
8658   underlying enumerable changes, it will change also.
8659
8660   ## Adding Objects
8661
8662   To add an object to an enumerable, use the `addObject()` method. This
8663   method will only add the object to the enumerable if the object is not
8664   already present and the object if of a type supported by the enumerable.
8665
8666   ```javascript
8667   set.addObject(contact);
8668   ```
8669
8670   ## Removing Objects
8671
8672   To remove an object form an enumerable, use the `removeObject()` method. This
8673   will only remove the object if it is already in the enumerable, otherwise
8674   this method has no effect.
8675
8676   ```javascript
8677   set.removeObject(contact);
8678   ```
8679
8680   ## Implementing In Your Own Code
8681
8682   If you are implementing an object and want to support this API, just include
8683   this mixin in your class and implement the required methods. In your unit
8684   tests, be sure to apply the Ember.MutableEnumerableTests to your object.
8685
8686   @class MutableEnumerable
8687   @namespace Ember
8688   @extends Ember.Mixin
8689   @uses Ember.Enumerable
8690 */
8691 Ember.MutableEnumerable = Ember.Mixin.create(Ember.Enumerable,
8692   /** @scope Ember.MutableEnumerable.prototype */ {
8693
8694   /**
8695     __Required.__ You must implement this method to apply this mixin.
8696
8697     Attempts to add the passed object to the receiver if the object is not
8698     already present in the collection. If the object is present, this method
8699     has no effect.
8700
8701     If the passed object is of a type not supported by the receiver
8702     then this method should raise an exception.
8703
8704     @method addObject
8705     @param {Object} object The object to add to the enumerable.
8706     @return {Object} the passed object
8707   */
8708   addObject: Ember.required(Function),
8709
8710   /**
8711     Adds each object in the passed enumerable to the receiver.
8712
8713     @method addObjects
8714     @param {Ember.Enumerable} objects the objects to add.
8715     @return {Object} receiver
8716   */
8717   addObjects: function(objects) {
8718     Ember.beginPropertyChanges(this);
8719     forEach(objects, function(obj) { this.addObject(obj); }, this);
8720     Ember.endPropertyChanges(this);
8721     return this;
8722   },
8723
8724   /**
8725     __Required.__ You must implement this method to apply this mixin.
8726
8727     Attempts to remove the passed object from the receiver collection if the
8728     object is in present in the collection. If the object is not present,
8729     this method has no effect.
8730
8731     If the passed object is of a type not supported by the receiver
8732     then this method should raise an exception.
8733
8734     @method removeObject
8735     @param {Object} object The object to remove from the enumerable.
8736     @return {Object} the passed object
8737   */
8738   removeObject: Ember.required(Function),
8739
8740
8741   /**
8742     Removes each objects in the passed enumerable from the receiver.
8743
8744     @method removeObjects
8745     @param {Ember.Enumerable} objects the objects to remove
8746     @return {Object} receiver
8747   */
8748   removeObjects: function(objects) {
8749     Ember.beginPropertyChanges(this);
8750     forEach(objects, function(obj) { this.removeObject(obj); }, this);
8751     Ember.endPropertyChanges(this);
8752     return this;
8753   }
8754
8755 });
8756
8757 })();
8758
8759
8760
8761 (function() {
8762 /**
8763 @module ember
8764 @submodule ember-runtime
8765 */
8766 // ..........................................................
8767 // CONSTANTS
8768 //
8769
8770 var OUT_OF_RANGE_EXCEPTION = "Index out of range" ;
8771 var EMPTY = [];
8772
8773 // ..........................................................
8774 // HELPERS
8775 //
8776
8777 var get = Ember.get, set = Ember.set, forEach = Ember.EnumerableUtils.forEach;
8778
8779 /**
8780   This mixin defines the API for modifying array-like objects. These methods
8781   can be applied only to a collection that keeps its items in an ordered set.
8782
8783   Note that an Array can change even if it does not implement this mixin.
8784   For example, one might implement a SparseArray that cannot be directly
8785   modified, but if its underlying enumerable changes, it will change also.
8786
8787   @class MutableArray
8788   @namespace Ember
8789   @extends Ember.Mixin
8790   @uses Ember.Array
8791   @uses Ember.MutableEnumerable
8792 */
8793 Ember.MutableArray = Ember.Mixin.create(Ember.Array, Ember.MutableEnumerable,
8794   /** @scope Ember.MutableArray.prototype */ {
8795
8796   /**
8797     __Required.__ You must implement this method to apply this mixin.
8798
8799     This is one of the primitives you must implement to support `Ember.Array`.
8800     You should replace amt objects started at idx with the objects in the
8801     passed array. You should also call `this.enumerableContentDidChange()`
8802
8803     @method replace
8804     @param {Number} idx Starting index in the array to replace. If 
8805       idx >= length, then append to the end of the array.
8806     @param {Number} amt Number of elements that should be removed from 
8807       the array, starting at *idx*.
8808     @param {Array} objects An array of zero or more objects that should be 
8809       inserted into the array at *idx*
8810   */
8811   replace: Ember.required(),
8812
8813   /**
8814     Remove all elements from self. This is useful if you
8815     want to reuse an existing array without having to recreate it.
8816
8817     ```javascript
8818     var colors = ["red", "green", "blue"];
8819     color.length();   //  3
8820     colors.clear();   //  []
8821     colors.length();  //  0
8822     ```
8823
8824     @method clear
8825     @return {Ember.Array} An empty Array.
8826   */
8827   clear: function () {
8828     var len = get(this, 'length');
8829     if (len === 0) return this;
8830     this.replace(0, len, EMPTY);
8831     return this;
8832   },
8833
8834   /**
8835     This will use the primitive `replace()` method to insert an object at the
8836     specified index.
8837
8838     ```javascript
8839     var colors = ["red", "green", "blue"];
8840     colors.insertAt(2, "yellow");  // ["red", "green", "yellow", "blue"]
8841     colors.insertAt(5, "orange");  // Error: Index out of range
8842     ```javascript
8843
8844     @method insertAt
8845     @param {Number} idx index of insert the object at.
8846     @param {Object} object object to insert
8847   */
8848   insertAt: function(idx, object) {
8849     if (idx > get(this, 'length')) throw new Error(OUT_OF_RANGE_EXCEPTION) ;
8850     this.replace(idx, 0, [object]) ;
8851     return this ;
8852   },
8853
8854   /**
8855     Remove an object at the specified index using the `replace()` primitive
8856     method. You can pass either a single index, or a start and a length.
8857
8858     If you pass a start and length that is beyond the
8859     length this method will throw an `Ember.OUT_OF_RANGE_EXCEPTION`
8860
8861     ```javascript
8862     var colors = ["red", "green", "blue", "yellow", "orange"];
8863     colors.removeAt(0);     // ["green", "blue", "yellow", "orange"]
8864     colors.removeAt(2, 2);  // ["green", "blue"]
8865     colors.removeAt(4, 2);  // Error: Index out of range
8866     ```
8867
8868     @method removeAt
8869     @param {Number} start index, start of range
8870     @param {Number} len length of passing range
8871     @return {Object} receiver
8872   */
8873   removeAt: function(start, len) {
8874     if ('number' === typeof start) {
8875
8876       if ((start < 0) || (start >= get(this, 'length'))) {
8877         throw new Error(OUT_OF_RANGE_EXCEPTION);
8878       }
8879
8880       // fast case
8881       if (len === undefined) len = 1;
8882       this.replace(start, len, EMPTY);
8883     }
8884
8885     return this ;
8886   },
8887
8888   /**
8889     Push the object onto the end of the array. Works just like `push()` but it
8890     is KVO-compliant.
8891
8892     ```javascript
8893     var colors = ["red", "green", "blue"];
8894     colors.pushObject("black");               // ["red", "green", "blue", "black"]
8895     colors.pushObject(["yellow", "orange"]);  // ["red", "green", "blue", "black", ["yellow", "orange"]]
8896     ```
8897
8898     @method pushObject
8899     @param {anything} obj object to push
8900   */
8901   pushObject: function(obj) {
8902     this.insertAt(get(this, 'length'), obj) ;
8903     return obj ;
8904   },
8905
8906   /**
8907     Add the objects in the passed numerable to the end of the array. Defers
8908     notifying observers of the change until all objects are added.
8909
8910     ```javascript
8911     var colors = ["red", "green", "blue"];
8912     colors.pushObjects("black");               // ["red", "green", "blue", "black"]
8913     colors.pushObjects(["yellow", "orange"]);  // ["red", "green", "blue", "black", "yellow", "orange"]
8914     ```
8915
8916     @method pushObjects
8917     @param {Ember.Enumerable} objects the objects to add
8918     @return {Ember.Array} receiver
8919   */
8920   pushObjects: function(objects) {
8921     this.replace(get(this, 'length'), 0, objects);
8922     return this;
8923   },
8924
8925   /**
8926     Pop object from array or nil if none are left. Works just like `pop()` but
8927     it is KVO-compliant.
8928
8929     ```javascript
8930     var colors = ["red", "green", "blue"];
8931     colors.popObject();   // "blue"
8932     console.log(colors);  // ["red", "green"]
8933     ```
8934
8935     @method popObject
8936     @return object
8937   */
8938   popObject: function() {
8939     var len = get(this, 'length') ;
8940     if (len === 0) return null ;
8941
8942     var ret = this.objectAt(len-1) ;
8943     this.removeAt(len-1, 1) ;
8944     return ret ;
8945   },
8946
8947   /**
8948     Shift an object from start of array or nil if none are left. Works just
8949     like `shift()` but it is KVO-compliant.
8950
8951     ```javascript
8952     var colors = ["red", "green", "blue"];
8953     colors.shiftObject();  // "red"
8954     console.log(colors);   // ["green", "blue"]
8955     ```
8956
8957     @method shiftObject
8958     @return object
8959   */
8960   shiftObject: function() {
8961     if (get(this, 'length') === 0) return null ;
8962     var ret = this.objectAt(0) ;
8963     this.removeAt(0) ;
8964     return ret ;
8965   },
8966
8967   /**
8968     Unshift an object to start of array. Works just like `unshift()` but it is
8969     KVO-compliant.
8970
8971     ```javascript
8972     var colors = ["red", "green", "blue"];
8973     colors.unshiftObject("yellow");             // ["yellow", "red", "green", "blue"]
8974     colors.unshiftObject(["black", "white"]);   // [["black", "white"], "yellow", "red", "green", "blue"]
8975     ```
8976
8977     @method unshiftObject
8978     @param {anything} obj object to unshift
8979   */
8980   unshiftObject: function(obj) {
8981     this.insertAt(0, obj) ;
8982     return obj ;
8983   },
8984
8985   /**
8986     Adds the named objects to the beginning of the array. Defers notifying
8987     observers until all objects have been added.
8988
8989     ```javascript
8990     var colors = ["red", "green", "blue"];
8991     colors.unshiftObjects(["black", "white"]);   // ["black", "white", "red", "green", "blue"]
8992     colors.unshiftObjects("yellow");             // Type Error: 'undefined' is not a function
8993     ```
8994
8995     @method unshiftObjects
8996     @param {Ember.Enumerable} objects the objects to add
8997     @return {Ember.Array} receiver
8998   */
8999   unshiftObjects: function(objects) {
9000     this.replace(0, 0, objects);
9001     return this;
9002   },
9003
9004   /**
9005     Reverse objects in the array. Works just like `reverse()` but it is
9006     KVO-compliant.
9007
9008     @method reverseObjects
9009     @return {Ember.Array} receiver
9010    */
9011   reverseObjects: function() {
9012     var len = get(this, 'length');
9013     if (len === 0) return this;
9014     var objects = this.toArray().reverse();
9015     this.replace(0, len, objects);
9016     return this;
9017   },
9018
9019   /**
9020     Replace all the the receiver's content with content of the argument.
9021     If argument is an empty array receiver will be cleared.
9022
9023     ```javascript
9024     var colors = ["red", "green", "blue"];
9025     colors.setObjects(["black", "white"]);  // ["black", "white"]
9026     colors.setObjects([]);                  // []
9027     ```
9028
9029     @method setObjects
9030     @param {Ember.Array} objects array whose content will be used for replacing
9031         the content of the receiver
9032     @return {Ember.Array} receiver with the new content
9033    */
9034   setObjects: function(objects) {
9035     if (objects.length === 0) return this.clear();
9036
9037     var len = get(this, 'length');
9038     this.replace(0, len, objects);
9039     return this;
9040   },
9041
9042   // ..........................................................
9043   // IMPLEMENT Ember.MutableEnumerable
9044   //
9045
9046   removeObject: function(obj) {
9047     var loc = get(this, 'length') || 0;
9048     while(--loc >= 0) {
9049       var curObject = this.objectAt(loc) ;
9050       if (curObject === obj) this.removeAt(loc) ;
9051     }
9052     return this ;
9053   },
9054
9055   addObject: function(obj) {
9056     if (!this.contains(obj)) this.pushObject(obj);
9057     return this ;
9058   }
9059
9060 });
9061
9062
9063 })();
9064
9065
9066
9067 (function() {
9068 /**
9069 @module ember
9070 @submodule ember-runtime
9071 */
9072
9073 var get = Ember.get, set = Ember.set, defineProperty = Ember.defineProperty;
9074
9075 /**
9076   ## Overview
9077
9078   This mixin provides properties and property observing functionality, core
9079   features of the Ember object model.
9080
9081   Properties and observers allow one object to observe changes to a
9082   property on another object. This is one of the fundamental ways that
9083   models, controllers and views communicate with each other in an Ember
9084   application.
9085
9086   Any object that has this mixin applied can be used in observer
9087   operations. That includes `Ember.Object` and most objects you will
9088   interact with as you write your Ember application.
9089
9090   Note that you will not generally apply this mixin to classes yourself,
9091   but you will use the features provided by this module frequently, so it
9092   is important to understand how to use it.
9093
9094   ## Using `get()` and `set()`
9095
9096   Because of Ember's support for bindings and observers, you will always
9097   access properties using the get method, and set properties using the
9098   set method. This allows the observing objects to be notified and
9099   computed properties to be handled properly.
9100
9101   More documentation about `get` and `set` are below.
9102
9103   ## Observing Property Changes
9104
9105   You typically observe property changes simply by adding the `observes`
9106   call to the end of your method declarations in classes that you write.
9107   For example:
9108
9109   ```javascript
9110   Ember.Object.create({
9111     valueObserver: function() {
9112       // Executes whenever the "value" property changes
9113     }.observes('value')
9114   });
9115   ```
9116
9117   Although this is the most common way to add an observer, this capability
9118   is actually built into the `Ember.Object` class on top of two methods
9119   defined in this mixin: `addObserver` and `removeObserver`. You can use
9120   these two methods to add and remove observers yourself if you need to
9121   do so at runtime.
9122
9123   To add an observer for a property, call:
9124
9125   ```javascript
9126   object.addObserver('propertyKey', targetObject, targetAction)
9127   ```
9128
9129   This will call the `targetAction` method on the `targetObject` to be called
9130   whenever the value of the `propertyKey` changes.
9131
9132   Note that if `propertyKey` is a computed property, the observer will be
9133   called when any of the property dependencies are changed, even if the
9134   resulting value of the computed property is unchanged. This is necessary
9135   because computed properties are not computed until `get` is called.
9136
9137   @class Observable
9138   @namespace Ember
9139   @extends Ember.Mixin
9140 */
9141 Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ {
9142
9143   // compatibility
9144   isObserverable: true,
9145
9146   /**
9147     Retrieves the value of a property from the object.
9148
9149     This method is usually similar to using `object[keyName]` or `object.keyName`,
9150     however it supports both computed properties and the unknownProperty
9151     handler.
9152
9153     Because `get` unifies the syntax for accessing all these kinds
9154     of properties, it can make many refactorings easier, such as replacing a
9155     simple property with a computed property, or vice versa.
9156
9157     ### Computed Properties
9158
9159     Computed properties are methods defined with the `property` modifier
9160     declared at the end, such as:
9161
9162     ```javascript
9163     fullName: function() {
9164       return this.getEach('firstName', 'lastName').compact().join(' ');
9165     }.property('firstName', 'lastName')
9166     ```
9167
9168     When you call `get` on a computed property, the function will be
9169     called and the return value will be returned instead of the function
9170     itself.
9171
9172     ### Unknown Properties
9173
9174     Likewise, if you try to call `get` on a property whose value is
9175     `undefined`, the `unknownProperty()` method will be called on the object.
9176     If this method returns any value other than `undefined`, it will be returned
9177     instead. This allows you to implement "virtual" properties that are
9178     not defined upfront.
9179
9180     @method get
9181     @param {String} key The property to retrieve
9182     @return {Object} The property value or undefined.
9183   */
9184   get: function(keyName) {
9185     return get(this, keyName);
9186   },
9187
9188   /**
9189     To get multiple properties at once, call `getProperties`
9190     with a list of strings or an array:
9191
9192     ```javascript
9193     record.getProperties('firstName', 'lastName', 'zipCode');  // { firstName: 'John', lastName: 'Doe', zipCode: '10011' }
9194     ```
9195
9196     is equivalent to:
9197
9198     ```javascript
9199     record.getProperties(['firstName', 'lastName', 'zipCode']);  // { firstName: 'John', lastName: 'Doe', zipCode: '10011' }
9200     ```
9201
9202     @method getProperties
9203     @param {String...|Array} list of keys to get
9204     @return {Hash}
9205   */
9206   getProperties: function() {
9207     var ret = {};
9208     var propertyNames = arguments;
9209     if (arguments.length === 1 && Ember.typeOf(arguments[0]) === 'array') {
9210       propertyNames = arguments[0];
9211     }
9212     for(var i = 0; i < propertyNames.length; i++) {
9213       ret[propertyNames[i]] = get(this, propertyNames[i]);
9214     }
9215     return ret;
9216   },
9217
9218   /**
9219     Sets the provided key or path to the value.
9220
9221     This method is generally very similar to calling `object[key] = value` or
9222     `object.key = value`, except that it provides support for computed
9223     properties, the `unknownProperty()` method and property observers.
9224
9225     ### Computed Properties
9226
9227     If you try to set a value on a key that has a computed property handler
9228     defined (see the `get()` method for an example), then `set()` will call
9229     that method, passing both the value and key instead of simply changing
9230     the value itself. This is useful for those times when you need to
9231     implement a property that is composed of one or more member
9232     properties.
9233
9234     ### Unknown Properties
9235
9236     If you try to set a value on a key that is undefined in the target
9237     object, then the `unknownProperty()` handler will be called instead. This
9238     gives you an opportunity to implement complex "virtual" properties that
9239     are not predefined on the object. If `unknownProperty()` returns
9240     undefined, then `set()` will simply set the value on the object.
9241
9242     ### Property Observers
9243
9244     In addition to changing the property, `set()` will also register a property
9245     change with the object. Unless you have placed this call inside of a
9246     `beginPropertyChanges()` and `endPropertyChanges(),` any "local" observers
9247     (i.e. observer methods declared on the same object), will be called
9248     immediately. Any "remote" observers (i.e. observer methods declared on
9249     another object) will be placed in a queue and called at a later time in a
9250     coalesced manner.
9251
9252     ### Chaining
9253
9254     In addition to property changes, `set()` returns the value of the object
9255     itself so you can do chaining like this:
9256
9257     ```javascript
9258     record.set('firstName', 'Charles').set('lastName', 'Jolley');
9259     ```
9260
9261     @method set
9262     @param {String} key The property to set
9263     @param {Object} value The value to set or `null`.
9264     @return {Ember.Observable}
9265   */
9266   set: function(keyName, value) {
9267     set(this, keyName, value);
9268     return this;
9269   },
9270
9271   /**
9272     To set multiple properties at once, call `setProperties`
9273     with a Hash:
9274
9275     ```javascript
9276     record.setProperties({ firstName: 'Charles', lastName: 'Jolley' });
9277     ```
9278
9279     @method setProperties
9280     @param {Hash} hash the hash of keys and values to set
9281     @return {Ember.Observable}
9282   */
9283   setProperties: function(hash) {
9284     return Ember.setProperties(this, hash);
9285   },
9286
9287   /**
9288     Begins a grouping of property changes.
9289
9290     You can use this method to group property changes so that notifications
9291     will not be sent until the changes are finished. If you plan to make a
9292     large number of changes to an object at one time, you should call this
9293     method at the beginning of the changes to begin deferring change
9294     notifications. When you are done making changes, call
9295     `endPropertyChanges()` to deliver the deferred change notifications and end
9296     deferring.
9297
9298     @method beginPropertyChanges
9299     @return {Ember.Observable}
9300   */
9301   beginPropertyChanges: function() {
9302     Ember.beginPropertyChanges();
9303     return this;
9304   },
9305
9306   /**
9307     Ends a grouping of property changes.
9308
9309     You can use this method to group property changes so that notifications
9310     will not be sent until the changes are finished. If you plan to make a
9311     large number of changes to an object at one time, you should call
9312     `beginPropertyChanges()` at the beginning of the changes to defer change
9313     notifications. When you are done making changes, call this method to
9314     deliver the deferred change notifications and end deferring.
9315
9316     @method endPropertyChanges
9317     @return {Ember.Observable}
9318   */
9319   endPropertyChanges: function() {
9320     Ember.endPropertyChanges();
9321     return this;
9322   },
9323
9324   /**
9325     Notify the observer system that a property is about to change.
9326
9327     Sometimes you need to change a value directly or indirectly without
9328     actually calling `get()` or `set()` on it. In this case, you can use this
9329     method and `propertyDidChange()` instead. Calling these two methods
9330     together will notify all observers that the property has potentially
9331     changed value.
9332
9333     Note that you must always call `propertyWillChange` and `propertyDidChange`
9334     as a pair. If you do not, it may get the property change groups out of
9335     order and cause notifications to be delivered more often than you would
9336     like.
9337
9338     @method propertyWillChange
9339     @param {String} key The property key that is about to change.
9340     @return {Ember.Observable}
9341   */
9342   propertyWillChange: function(keyName){
9343     Ember.propertyWillChange(this, keyName);
9344     return this;
9345   },
9346
9347   /**
9348     Notify the observer system that a property has just changed.
9349
9350     Sometimes you need to change a value directly or indirectly without
9351     actually calling `get()` or `set()` on it. In this case, you can use this
9352     method and `propertyWillChange()` instead. Calling these two methods
9353     together will notify all observers that the property has potentially
9354     changed value.
9355
9356     Note that you must always call `propertyWillChange` and `propertyDidChange`
9357     as a pair. If you do not, it may get the property change groups out of
9358     order and cause notifications to be delivered more often than you would
9359     like.
9360
9361     @method propertyDidChange
9362     @param {String} keyName The property key that has just changed.
9363     @return {Ember.Observable}
9364   */
9365   propertyDidChange: function(keyName) {
9366     Ember.propertyDidChange(this, keyName);
9367     return this;
9368   },
9369
9370   /**
9371     Convenience method to call `propertyWillChange` and `propertyDidChange` in
9372     succession.
9373
9374     @method notifyPropertyChange
9375     @param {String} keyName The property key to be notified about.
9376     @return {Ember.Observable}
9377   */
9378   notifyPropertyChange: function(keyName) {
9379     this.propertyWillChange(keyName);
9380     this.propertyDidChange(keyName);
9381     return this;
9382   },
9383
9384   addBeforeObserver: function(key, target, method) {
9385     Ember.addBeforeObserver(this, key, target, method);
9386   },
9387
9388   /**
9389     Adds an observer on a property.
9390
9391     This is the core method used to register an observer for a property.
9392
9393     Once you call this method, anytime the key's value is set, your observer
9394     will be notified. Note that the observers are triggered anytime the
9395     value is set, regardless of whether it has actually changed. Your
9396     observer should be prepared to handle that.
9397
9398     You can also pass an optional context parameter to this method. The
9399     context will be passed to your observer method whenever it is triggered.
9400     Note that if you add the same target/method pair on a key multiple times
9401     with different context parameters, your observer will only be called once
9402     with the last context you passed.
9403
9404     ### Observer Methods
9405
9406     Observer methods you pass should generally have the following signature if
9407     you do not pass a `context` parameter:
9408
9409     ```javascript
9410     fooDidChange: function(sender, key, value, rev) { };
9411     ```
9412
9413     The sender is the object that changed. The key is the property that
9414     changes. The value property is currently reserved and unused. The rev
9415     is the last property revision of the object when it changed, which you can
9416     use to detect if the key value has really changed or not.
9417
9418     If you pass a `context` parameter, the context will be passed before the
9419     revision like so:
9420
9421     ```javascript
9422     fooDidChange: function(sender, key, value, context, rev) { };
9423     ```
9424
9425     Usually you will not need the value, context or revision parameters at
9426     the end. In this case, it is common to write observer methods that take
9427     only a sender and key value as parameters or, if you aren't interested in
9428     any of these values, to write an observer that has no parameters at all.
9429
9430     @method addObserver
9431     @param {String} key The key to observer
9432     @param {Object} target The target object to invoke
9433     @param {String|Function} method The method to invoke.
9434     @return {Ember.Object} self
9435   */
9436   addObserver: function(key, target, method) {
9437     Ember.addObserver(this, key, target, method);
9438   },
9439
9440   /**
9441     Remove an observer you have previously registered on this object. Pass
9442     the same key, target, and method you passed to `addObserver()` and your
9443     target will no longer receive notifications.
9444
9445     @method removeObserver
9446     @param {String} key The key to observer
9447     @param {Object} target The target object to invoke
9448     @param {String|Function} method The method to invoke.
9449     @return {Ember.Observable} receiver
9450   */
9451   removeObserver: function(key, target, method) {
9452     Ember.removeObserver(this, key, target, method);
9453   },
9454
9455   /**
9456     Returns `true` if the object currently has observers registered for a
9457     particular key. You can use this method to potentially defer performing
9458     an expensive action until someone begins observing a particular property
9459     on the object.
9460
9461     @method hasObserverFor
9462     @param {String} key Key to check
9463     @return {Boolean}
9464   */
9465   hasObserverFor: function(key) {
9466     return Ember.hasListeners(this, key+':change');
9467   },
9468
9469   /**
9470     @deprecated
9471     @method getPath
9472     @param {String} path The property path to retrieve
9473     @return {Object} The property value or undefined.
9474   */
9475   getPath: function(path) {
9476     Ember.deprecate("getPath is deprecated since get now supports paths");
9477     return this.get(path);
9478   },
9479
9480   /**
9481     @deprecated
9482     @method setPath
9483     @param {String} path The path to the property that will be set
9484     @param {Object} value The value to set or `null`.
9485     @return {Ember.Observable}
9486   */
9487   setPath: function(path, value) {
9488     Ember.deprecate("setPath is deprecated since set now supports paths");
9489     return this.set(path, value);
9490   },
9491
9492   /**
9493     Retrieves the value of a property, or a default value in the case that the
9494     property returns `undefined`.
9495
9496     ```javascript
9497     person.getWithDefault('lastName', 'Doe');
9498     ```
9499
9500     @method getWithDefault
9501     @param {String} keyName The name of the property to retrieve
9502     @param {Object} defaultValue The value to return if the property value is undefined
9503     @return {Object} The property value or the defaultValue.
9504   */
9505   getWithDefault: function(keyName, defaultValue) {
9506     return Ember.getWithDefault(this, keyName, defaultValue);
9507   },
9508
9509   /**
9510     Set the value of a property to the current value plus some amount.
9511
9512     ```javascript
9513     person.incrementProperty('age');
9514     team.incrementProperty('score', 2);
9515     ```
9516
9517     @method incrementProperty
9518     @param {String} keyName The name of the property to increment
9519     @param {Object} increment The amount to increment by. Defaults to 1
9520     @return {Object} The new property value
9521   */
9522   incrementProperty: function(keyName, increment) {
9523     if (!increment) { increment = 1; }
9524     set(this, keyName, (get(this, keyName) || 0)+increment);
9525     return get(this, keyName);
9526   },
9527
9528   /**
9529     Set the value of a property to the current value minus some amount.
9530
9531     ```javascript
9532     player.decrementProperty('lives');
9533     orc.decrementProperty('health', 5);
9534     ```
9535
9536     @method decrementProperty
9537     @param {String} keyName The name of the property to decrement
9538     @param {Object} increment The amount to decrement by. Defaults to 1
9539     @return {Object} The new property value
9540   */
9541   decrementProperty: function(keyName, increment) {
9542     if (!increment) { increment = 1; }
9543     set(this, keyName, (get(this, keyName) || 0)-increment);
9544     return get(this, keyName);
9545   },
9546
9547   /**
9548     Set the value of a boolean property to the opposite of it's
9549     current value.
9550
9551     ```javascript
9552     starship.toggleProperty('warpDriveEnaged');
9553     ```
9554
9555     @method toggleProperty
9556     @param {String} keyName The name of the property to toggle
9557     @return {Object} The new property value
9558   */
9559   toggleProperty: function(keyName) {
9560     set(this, keyName, !get(this, keyName));
9561     return get(this, keyName);
9562   },
9563
9564   /**
9565     Returns the cached value of a computed property, if it exists.
9566     This allows you to inspect the value of a computed property
9567     without accidentally invoking it if it is intended to be
9568     generated lazily.
9569
9570     @method cacheFor
9571     @param {String} keyName
9572     @return {Object} The cached value of the computed property, if any
9573   */
9574   cacheFor: function(keyName) {
9575     return Ember.cacheFor(this, keyName);
9576   },
9577
9578   // intended for debugging purposes
9579   observersForKey: function(keyName) {
9580     return Ember.observersFor(this, keyName);
9581   }
9582 });
9583
9584
9585 })();
9586
9587
9588
9589 (function() {
9590 /**
9591 @module ember
9592 @submodule ember-runtime
9593 */
9594
9595 var get = Ember.get, set = Ember.set;
9596
9597 /**
9598 @class TargetActionSupport
9599 @namespace Ember
9600 @extends Ember.Mixin
9601 */
9602 Ember.TargetActionSupport = Ember.Mixin.create({
9603   target: null,
9604   action: null,
9605
9606   targetObject: Ember.computed(function() {
9607     var target = get(this, 'target');
9608
9609     if (Ember.typeOf(target) === "string") {
9610       var value = get(this, target);
9611       if (value === undefined) { value = get(Ember.lookup, target); }
9612       return value;
9613     } else {
9614       return target;
9615     }
9616   }).property('target'),
9617
9618   triggerAction: function() {
9619     var action = get(this, 'action'),
9620         target = get(this, 'targetObject');
9621
9622     if (target && action) {
9623       var ret;
9624
9625       if (typeof target.send === 'function') {
9626         ret = target.send(action, this);
9627       } else {
9628         if (typeof action === 'string') {
9629           action = target[action];
9630         }
9631         ret = action.call(target, this);
9632       }
9633       if (ret !== false) ret = true;
9634
9635       return ret;
9636     } else {
9637       return false;
9638     }
9639   }
9640 });
9641
9642 })();
9643
9644
9645
9646 (function() {
9647 /**
9648 @module ember
9649 @submodule ember-runtime
9650 */
9651
9652 /**
9653   This mixin allows for Ember objects to subscribe to and emit events.
9654
9655   ```javascript
9656   App.Person = Ember.Object.extend(Ember.Evented, {
9657     greet: function() {
9658       // ...
9659       this.trigger('greet');
9660     }
9661   });
9662
9663   var person = App.Person.create();
9664
9665   person.on('greet', function() {
9666     console.log('Our person has greeted');
9667   });
9668
9669   person.greet();
9670
9671   // outputs: 'Our person has greeted'
9672   ```
9673
9674   @class Evented
9675   @namespace Ember
9676   @extends Ember.Mixin
9677  */
9678 Ember.Evented = Ember.Mixin.create({
9679
9680   /**
9681    Subscribes to a named event with given function.
9682
9683    ```javascript
9684    person.on('didLoad', function() {
9685      // fired once the person has loaded
9686    });
9687    ```
9688
9689    An optional target can be passed in as the 2nd argument that will
9690    be set as the "this" for the callback. This is a good way to give your
9691    function access to the object triggering the event. When the target
9692    parameter is used the callback becomes the third argument.
9693
9694    @method on
9695    @param {String} name The name of the event
9696    @param {Object} [target] The "this" binding for the callback
9697    @param {Function} method The callback to execute
9698   */
9699   on: function(name, target, method) {
9700     Ember.addListener(this, name, target, method);
9701   },
9702
9703   /**
9704     Subscribes a function to a named event and then cancels the subscription
9705     after the first time the event is triggered. It is good to use ``one`` when
9706     you only care about the first time an event has taken place.
9707
9708     This function takes an optional 2nd argument that will become the "this"
9709     value for the callback. If this argument is passed then the 3rd argument
9710     becomes the function.
9711
9712     @method one
9713     @param {String} name The name of the event
9714     @param {Object} [target] The "this" binding for the callback
9715     @param {Function} method The callback to execute
9716   */
9717   one: function(name, target, method) {
9718     if (!method) {
9719       method = target;
9720       target = null;
9721     }
9722
9723     Ember.addListener(this, name, target, method, true);
9724   },
9725
9726   /**
9727     Triggers a named event for the object. Any additional arguments
9728     will be passed as parameters to the functions that are subscribed to the
9729     event.
9730
9731     ```javascript
9732     person.on('didEat', food) {
9733       console.log('person ate some ' + food);
9734     });
9735
9736     person.trigger('didEat', 'broccoli');
9737
9738     // outputs: person ate some broccoli
9739     ```
9740     @method trigger
9741     @param {String} name The name of the event
9742     @param {Object...} args Optional arguments to pass on
9743   */
9744   trigger: function(name) {
9745     var args = [], i, l;
9746     for (i = 1, l = arguments.length; i < l; i++) {
9747       args.push(arguments[i]);
9748     }
9749     Ember.sendEvent(this, name, args);
9750   },
9751
9752   fire: function(name) {
9753     Ember.deprecate("Ember.Evented#fire() has been deprecated in favor of trigger() for compatibility with jQuery. It will be removed in 1.0. Please update your code to call trigger() instead.");
9754     this.trigger.apply(this, arguments);
9755   },
9756
9757   /**
9758     Cancels subscription for give name, target, and method.
9759
9760     @method off
9761     @param {String} name The name of the event
9762     @param {Object} target The target of the subscription
9763     @param {Function} method The function of the subscription
9764   */
9765   off: function(name, target, method) {
9766     Ember.removeListener(this, name, target, method);
9767   },
9768
9769   /**
9770     Checks to see if object has any subscriptions for named event.
9771
9772     @method has
9773     @param {String} name The name of the event
9774     @return {Boolean} does the object have a subscription for event
9775    */
9776   has: function(name) {
9777     return Ember.hasListeners(this, name);
9778   }
9779 });
9780
9781 })();
9782
9783
9784
9785 (function() {
9786 var RSVP = requireModule("rsvp");
9787
9788 RSVP.async = function(callback, binding) {
9789   Ember.run.schedule('actions', binding, callback);
9790 };
9791
9792 /**
9793 @module ember
9794 @submodule ember-runtime
9795 */
9796
9797 var get = Ember.get,
9798     slice = Array.prototype.slice;
9799
9800 /**
9801   @class Deferred
9802   @namespace Ember
9803   @extends Ember.Mixin
9804  */
9805 Ember.DeferredMixin = Ember.Mixin.create({
9806   /**
9807     Add handlers to be called when the Deferred object is resolved or rejected.
9808
9809     @method then
9810     @param {Function} doneCallback a callback function to be called when done
9811     @param {Function} failCallback a callback function to be called when failed
9812   */
9813   then: function(doneCallback, failCallback) {
9814     var promise = get(this, 'promise');
9815     return promise.then.apply(promise, arguments);
9816   },
9817
9818   /**
9819     Resolve a Deferred object and call any `doneCallbacks` with the given args.
9820
9821     @method resolve
9822   */
9823   resolve: function(value) {
9824     get(this, 'promise').resolve(value);
9825   },
9826
9827   /**
9828     Reject a Deferred object and call any `failCallbacks` with the given args.
9829
9830     @method reject
9831   */
9832   reject: function(value) {
9833     get(this, 'promise').reject(value);
9834   },
9835
9836   promise: Ember.computed(function() {
9837     return new RSVP.Promise();
9838   })
9839 });
9840
9841
9842 })();
9843
9844
9845
9846 (function() {
9847
9848 })();
9849
9850
9851
9852 (function() {
9853 Ember.Container = requireModule('container');
9854 Ember.Container.set = Ember.set;
9855
9856 })();
9857
9858
9859
9860 (function() {
9861 /**
9862 @module ember
9863 @submodule ember-runtime
9864 */
9865
9866
9867 // NOTE: this object should never be included directly. Instead use Ember.
9868 // Ember.Object. We only define this separately so that Ember.Set can depend on it
9869
9870
9871 var set = Ember.set, get = Ember.get,
9872     o_create = Ember.create,
9873     o_defineProperty = Ember.platform.defineProperty,
9874     a_slice = Array.prototype.slice,
9875     GUID_KEY = Ember.GUID_KEY,
9876     guidFor = Ember.guidFor,
9877     generateGuid = Ember.generateGuid,
9878     meta = Ember.meta,
9879     rewatch = Ember.rewatch,
9880     finishChains = Ember.finishChains,
9881     destroy = Ember.destroy,
9882     schedule = Ember.run.schedule,
9883     Mixin = Ember.Mixin,
9884     applyMixin = Mixin._apply,
9885     finishPartial = Mixin.finishPartial,
9886     reopen = Mixin.prototype.reopen,
9887     MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER,
9888     indexOf = Ember.EnumerableUtils.indexOf;
9889
9890 var undefinedDescriptor = {
9891   configurable: true,
9892   writable: true,
9893   enumerable: false,
9894   value: undefined
9895 };
9896
9897 function makeCtor() {
9898
9899   // Note: avoid accessing any properties on the object since it makes the
9900   // method a lot faster. This is glue code so we want it to be as fast as
9901   // possible.
9902
9903   var wasApplied = false, initMixins, initProperties;
9904
9905   var Class = function() {
9906     if (!wasApplied) {
9907       Class.proto(); // prepare prototype...
9908     }
9909     o_defineProperty(this, GUID_KEY, undefinedDescriptor);
9910     o_defineProperty(this, '_super', undefinedDescriptor);
9911     var m = meta(this);
9912     m.proto = this;
9913     if (initMixins) {
9914       // capture locally so we can clear the closed over variable
9915       var mixins = initMixins;
9916       initMixins = null;
9917       this.reopen.apply(this, mixins);
9918     }
9919     if (initProperties) {
9920       // capture locally so we can clear the closed over variable
9921       var props = initProperties;
9922       initProperties = null;
9923
9924       var concatenatedProperties = this.concatenatedProperties;
9925
9926       for (var i = 0, l = props.length; i < l; i++) {
9927         var properties = props[i];
9928         for (var keyName in properties) {
9929           if (!properties.hasOwnProperty(keyName)) { continue; }
9930
9931           var value = properties[keyName],
9932               IS_BINDING = Ember.IS_BINDING;
9933
9934           if (IS_BINDING.test(keyName)) {
9935             var bindings = m.bindings;
9936             if (!bindings) {
9937               bindings = m.bindings = {};
9938             } else if (!m.hasOwnProperty('bindings')) {
9939               bindings = m.bindings = o_create(m.bindings);
9940             }
9941             bindings[keyName] = value;
9942           }
9943
9944           var desc = m.descs[keyName];
9945
9946           Ember.assert("Ember.Object.create no longer supports defining computed properties.", !(value instanceof Ember.ComputedProperty));
9947           Ember.assert("Ember.Object.create no longer supports defining methods that call _super.", !(typeof value === 'function' && value.toString().indexOf('._super') !== -1));
9948
9949           if (concatenatedProperties && indexOf(concatenatedProperties, keyName) >= 0) {
9950             var baseValue = this[keyName];
9951
9952             if (baseValue) {
9953               if ('function' === typeof baseValue.concat) {
9954                 value = baseValue.concat(value);
9955               } else {
9956                 value = Ember.makeArray(baseValue).concat(value);
9957               }
9958             } else {
9959               value = Ember.makeArray(value);
9960             }
9961           }
9962
9963           if (desc) {
9964             desc.set(this, keyName, value);
9965           } else {
9966             if (typeof this.setUnknownProperty === 'function' && !(keyName in this)) {
9967               this.setUnknownProperty(keyName, value);
9968             } else if (MANDATORY_SETTER) {
9969               Ember.defineProperty(this, keyName, null, value); // setup mandatory setter
9970             } else {
9971               this[keyName] = value;
9972             }
9973           }
9974         }
9975       }
9976     }
9977     finishPartial(this, m);
9978     delete m.proto;
9979     finishChains(this);
9980     this.init.apply(this, arguments);
9981   };
9982
9983   Class.toString = Mixin.prototype.toString;
9984   Class.willReopen = function() {
9985     if (wasApplied) {
9986       Class.PrototypeMixin = Mixin.create(Class.PrototypeMixin);
9987     }
9988
9989     wasApplied = false;
9990   };
9991   Class._initMixins = function(args) { initMixins = args; };
9992   Class._initProperties = function(args) { initProperties = args; };
9993
9994   Class.proto = function() {
9995     var superclass = Class.superclass;
9996     if (superclass) { superclass.proto(); }
9997
9998     if (!wasApplied) {
9999       wasApplied = true;
10000       Class.PrototypeMixin.applyPartial(Class.prototype);
10001       rewatch(Class.prototype);
10002     }
10003
10004     return this.prototype;
10005   };
10006
10007   return Class;
10008
10009 }
10010
10011 var CoreObject = makeCtor();
10012
10013 CoreObject.PrototypeMixin = Mixin.create({
10014
10015   reopen: function() {
10016     applyMixin(this, arguments, true);
10017     return this;
10018   },
10019
10020   isInstance: true,
10021
10022   init: function() {},
10023
10024   /**
10025     Defines the properties that will be concatenated from the superclass
10026     (instead of overridden).
10027
10028     By default, when you extend an Ember class a property defined in
10029     the subclass overrides a property with the same name that is defined
10030     in the superclass. However, there are some cases where it is preferable
10031     to build up a property's value by combining the superclass' property
10032     value with the subclass' value. An example of this in use within Ember
10033     is the `classNames` property of `Ember.View`.
10034
10035     Here is some sample code showing the difference between a concatenated
10036     property and a normal one:
10037
10038     ```javascript
10039     App.BarView = Ember.View.extend({
10040       someNonConcatenatedProperty: ['bar'],
10041       classNames: ['bar']
10042     });
10043
10044     App.FooBarView = App.BarView.extend({
10045       someNonConcatenatedProperty: ['foo'],
10046       classNames: ['foo'],
10047     });
10048
10049     var fooBarView = App.FooBarView.create();
10050     fooBarView.get('someNonConcatenatedProperty'); // ['foo']
10051     fooBarView.get('classNames'); // ['ember-view', 'bar', 'foo']
10052     ```
10053
10054     This behavior extends to object creation as well. Continuing the
10055     above example:
10056
10057     ```javascript
10058     var view = App.FooBarView.create({
10059       someNonConcatenatedProperty: ['baz'],
10060       classNames: ['baz']
10061     })
10062     view.get('someNonConcatenatedProperty'); // ['baz']
10063     view.get('classNames'); // ['ember-view', 'bar', 'foo', 'baz']
10064     ```
10065     Adding a single property that is not an array will just add it in the array:
10066     
10067     ```javascript
10068     var view = App.FooBarView.create({
10069       classNames: 'baz'
10070     })
10071     view.get('classNames'); // ['ember-view', 'bar', 'foo', 'baz']
10072     ```
10073     
10074     Using the `concatenatedProperties` property, we can tell to Ember that mix
10075     the content of the properties.
10076
10077     In `Ember.View` the `classNameBindings` and `attributeBindings` properties
10078     are also concatenated, in addition to `classNames`.
10079
10080     This feature is available for you to use throughout the Ember object model,
10081     although typical app developers are likely to use it infrequently.
10082
10083     @property concatenatedProperties
10084     @type Array
10085     @default null
10086   */
10087   concatenatedProperties: null,
10088
10089   /**
10090     @property isDestroyed
10091     @default false
10092   */
10093   isDestroyed: false,
10094
10095   /**
10096     @property isDestroying
10097     @default false
10098   */
10099   isDestroying: false,
10100
10101   /**
10102     Destroys an object by setting the `isDestroyed` flag and removing its
10103     metadata, which effectively destroys observers and bindings.
10104
10105     If you try to set a property on a destroyed object, an exception will be
10106     raised.
10107
10108     Note that destruction is scheduled for the end of the run loop and does not
10109     happen immediately.
10110
10111     @method destroy
10112     @return {Ember.Object} receiver
10113   */
10114   destroy: function() {
10115     if (this.isDestroying) { return; }
10116
10117     this.isDestroying = true;
10118
10119     if (this.willDestroy) { this.willDestroy(); }
10120
10121     schedule('destroy', this, this._scheduledDestroy);
10122     return this;
10123   },
10124
10125   /**
10126     @private
10127
10128     Invoked by the run loop to actually destroy the object. This is
10129     scheduled for execution by the `destroy` method.
10130
10131     @method _scheduledDestroy
10132   */
10133   _scheduledDestroy: function() {
10134     destroy(this);
10135     set(this, 'isDestroyed', true);
10136
10137     if (this.didDestroy) { this.didDestroy(); }
10138   },
10139
10140   bind: function(to, from) {
10141     if (!(from instanceof Ember.Binding)) { from = Ember.Binding.from(from); }
10142     from.to(to).connect(this);
10143     return from;
10144   },
10145
10146   /**
10147     Returns a string representation which attempts to provide more information
10148     than Javascript's `toString` typically does, in a generic way for all Ember
10149     objects.
10150
10151         App.Person = Em.Object.extend()
10152         person = App.Person.create()
10153         person.toString() //=> "<App.Person:ember1024>"
10154
10155     If the object's class is not defined on an Ember namespace, it will
10156     indicate it is a subclass of the registered superclass:
10157
10158         Student = App.Person.extend()
10159         student = Student.create()
10160         student.toString() //=> "<(subclass of App.Person):ember1025>"
10161
10162     If the method `toStringExtension` is defined, its return value will be
10163     included in the output.
10164
10165         App.Teacher = App.Person.extend({
10166           toStringExtension: function(){
10167             return this.get('fullName');
10168           }
10169         });
10170         teacher = App.Teacher.create()
10171         teacher.toString(); // #=> "<App.Teacher:ember1026:Tom Dale>"
10172
10173     @method toString
10174     @return {String} string representation
10175   */
10176   toString: function toString() {
10177     var hasToStringExtension = typeof this.toStringExtension === 'function',
10178         extension = hasToStringExtension ? ":" + this.toStringExtension() : '';
10179     var ret = '<'+this.constructor.toString()+':'+guidFor(this)+extension+'>';
10180     this.toString = makeToString(ret);
10181     return ret;
10182   }
10183 });
10184
10185 function makeToString(ret) {
10186   return function() { return ret; };
10187 }
10188
10189 if (Ember.config.overridePrototypeMixin) {
10190   Ember.config.overridePrototypeMixin(CoreObject.PrototypeMixin);
10191 }
10192
10193 CoreObject.__super__ = null;
10194
10195 var ClassMixin = Mixin.create({
10196
10197   ClassMixin: Ember.required(),
10198
10199   PrototypeMixin: Ember.required(),
10200
10201   isClass: true,
10202
10203   isMethod: false,
10204
10205   extend: function() {
10206     var Class = makeCtor(), proto;
10207     Class.ClassMixin = Mixin.create(this.ClassMixin);
10208     Class.PrototypeMixin = Mixin.create(this.PrototypeMixin);
10209
10210     Class.ClassMixin.ownerConstructor = Class;
10211     Class.PrototypeMixin.ownerConstructor = Class;
10212
10213     reopen.apply(Class.PrototypeMixin, arguments);
10214
10215     Class.superclass = this;
10216     Class.__super__  = this.prototype;
10217
10218     proto = Class.prototype = o_create(this.prototype);
10219     proto.constructor = Class;
10220     generateGuid(proto, 'ember');
10221     meta(proto).proto = proto; // this will disable observers on prototype
10222
10223     Class.ClassMixin.apply(Class);
10224     return Class;
10225   },
10226
10227   createWithMixins: function() {
10228     var C = this;
10229     if (arguments.length>0) { this._initMixins(arguments); }
10230     return new C();
10231   },
10232
10233   create: function() {
10234     var C = this;
10235     if (arguments.length>0) { this._initProperties(arguments); }
10236     return new C();
10237   },
10238
10239   reopen: function() {
10240     this.willReopen();
10241     reopen.apply(this.PrototypeMixin, arguments);
10242     return this;
10243   },
10244
10245   reopenClass: function() {
10246     reopen.apply(this.ClassMixin, arguments);
10247     applyMixin(this, arguments, false);
10248     return this;
10249   },
10250
10251   detect: function(obj) {
10252     if ('function' !== typeof obj) { return false; }
10253     while(obj) {
10254       if (obj===this) { return true; }
10255       obj = obj.superclass;
10256     }
10257     return false;
10258   },
10259
10260   detectInstance: function(obj) {
10261     return obj instanceof this;
10262   },
10263
10264   /**
10265     In some cases, you may want to annotate computed properties with additional
10266     metadata about how they function or what values they operate on. For
10267     example, computed property functions may close over variables that are then
10268     no longer available for introspection.
10269
10270     You can pass a hash of these values to a computed property like this:
10271
10272     ```javascript
10273     person: function() {
10274       var personId = this.get('personId');
10275       return App.Person.create({ id: personId });
10276     }.property().meta({ type: App.Person })
10277     ```
10278
10279     Once you've done this, you can retrieve the values saved to the computed
10280     property from your class like this:
10281
10282     ```javascript
10283     MyClass.metaForProperty('person');
10284     ```
10285
10286     This will return the original hash that was passed to `meta()`.
10287
10288     @method metaForProperty
10289     @param key {String} property name
10290   */
10291   metaForProperty: function(key) {
10292     var desc = meta(this.proto(), false).descs[key];
10293
10294     Ember.assert("metaForProperty() could not find a computed property with key '"+key+"'.", !!desc && desc instanceof Ember.ComputedProperty);
10295     return desc._meta || {};
10296   },
10297
10298   /**
10299     Iterate over each computed property for the class, passing its name
10300     and any associated metadata (see `metaForProperty`) to the callback.
10301
10302     @method eachComputedProperty
10303     @param {Function} callback
10304     @param {Object} binding
10305   */
10306   eachComputedProperty: function(callback, binding) {
10307     var proto = this.proto(),
10308         descs = meta(proto).descs,
10309         empty = {},
10310         property;
10311
10312     for (var name in descs) {
10313       property = descs[name];
10314
10315       if (property instanceof Ember.ComputedProperty) {
10316         callback.call(binding || this, name, property._meta || empty);
10317       }
10318     }
10319   }
10320
10321 });
10322
10323 if (Ember.config.overrideClassMixin) {
10324   Ember.config.overrideClassMixin(ClassMixin);
10325 }
10326
10327 CoreObject.ClassMixin = ClassMixin;
10328 ClassMixin.apply(CoreObject);
10329
10330 /**
10331   @class CoreObject
10332   @namespace Ember
10333 */
10334 Ember.CoreObject = CoreObject;
10335
10336 })();
10337
10338
10339
10340 (function() {
10341 /**
10342 @module ember
10343 @submodule ember-runtime
10344 */
10345
10346 var get = Ember.get, set = Ember.set, guidFor = Ember.guidFor, none = Ember.isNone;
10347
10348 /**
10349   An unordered collection of objects.
10350
10351   A Set works a bit like an array except that its items are not ordered. You
10352   can create a set to efficiently test for membership for an object. You can
10353   also iterate through a set just like an array, even accessing objects by
10354   index, however there is no guarantee as to their order.
10355
10356   All Sets are observable via the Enumerable Observer API - which works
10357   on any enumerable object including both Sets and Arrays.
10358
10359   ## Creating a Set
10360
10361   You can create a set like you would most objects using
10362   `new Ember.Set()`. Most new sets you create will be empty, but you can
10363   also initialize the set with some content by passing an array or other
10364   enumerable of objects to the constructor.
10365
10366   Finally, you can pass in an existing set and the set will be copied. You
10367   can also create a copy of a set by calling `Ember.Set#copy()`.
10368
10369   ```javascript
10370   // creates a new empty set
10371   var foundNames = new Ember.Set();
10372
10373   // creates a set with four names in it.
10374   var names = new Ember.Set(["Charles", "Tom", "Juan", "Alex"]); // :P
10375
10376   // creates a copy of the names set.
10377   var namesCopy = new Ember.Set(names);
10378
10379   // same as above.
10380   var anotherNamesCopy = names.copy();
10381   ```
10382
10383   ## Adding/Removing Objects
10384
10385   You generally add or remove objects from a set using `add()` or
10386   `remove()`. You can add any type of object including primitives such as
10387   numbers, strings, and booleans.
10388
10389   Unlike arrays, objects can only exist one time in a set. If you call `add()`
10390   on a set with the same object multiple times, the object will only be added
10391   once. Likewise, calling `remove()` with the same object multiple times will
10392   remove the object the first time and have no effect on future calls until
10393   you add the object to the set again.
10394
10395   NOTE: You cannot add/remove `null` or `undefined` to a set. Any attempt to do
10396   so will be ignored.
10397
10398   In addition to add/remove you can also call `push()`/`pop()`. Push behaves
10399   just like `add()` but `pop()`, unlike `remove()` will pick an arbitrary
10400   object, remove it and return it. This is a good way to use a set as a job
10401   queue when you don't care which order the jobs are executed in.
10402
10403   ## Testing for an Object
10404
10405   To test for an object's presence in a set you simply call
10406   `Ember.Set#contains()`.
10407
10408   ## Observing changes
10409
10410   When using `Ember.Set`, you can observe the `"[]"` property to be
10411   alerted whenever the content changes. You can also add an enumerable
10412   observer to the set to be notified of specific objects that are added and
10413   removed from the set. See `Ember.Enumerable` for more information on
10414   enumerables.
10415
10416   This is often unhelpful. If you are filtering sets of objects, for instance,
10417   it is very inefficient to re-filter all of the items each time the set
10418   changes. It would be better if you could just adjust the filtered set based
10419   on what was changed on the original set. The same issue applies to merging
10420   sets, as well.
10421
10422   ## Other Methods
10423
10424   `Ember.Set` primary implements other mixin APIs. For a complete reference
10425   on the methods you will use with `Ember.Set`, please consult these mixins.
10426   The most useful ones will be `Ember.Enumerable` and
10427   `Ember.MutableEnumerable` which implement most of the common iterator
10428   methods you are used to on Array.
10429
10430   Note that you can also use the `Ember.Copyable` and `Ember.Freezable`
10431   APIs on `Ember.Set` as well. Once a set is frozen it can no longer be
10432   modified. The benefit of this is that when you call `frozenCopy()` on it,
10433   Ember will avoid making copies of the set. This allows you to write
10434   code that can know with certainty when the underlying set data will or
10435   will not be modified.
10436
10437   @class Set
10438   @namespace Ember
10439   @extends Ember.CoreObject
10440   @uses Ember.MutableEnumerable
10441   @uses Ember.Copyable
10442   @uses Ember.Freezable
10443   @since Ember 0.9
10444 */
10445 Ember.Set = Ember.CoreObject.extend(Ember.MutableEnumerable, Ember.Copyable, Ember.Freezable,
10446   /** @scope Ember.Set.prototype */ {
10447
10448   // ..........................................................
10449   // IMPLEMENT ENUMERABLE APIS
10450   //
10451
10452   /**
10453     This property will change as the number of objects in the set changes.
10454
10455     @property length
10456     @type number
10457     @default 0
10458   */
10459   length: 0,
10460
10461   /**
10462     Clears the set. This is useful if you want to reuse an existing set
10463     without having to recreate it.
10464
10465     ```javascript
10466     var colors = new Ember.Set(["red", "green", "blue"]);
10467     colors.length;  // 3
10468     colors.clear();
10469     colors.length;  // 0
10470     ```
10471
10472     @method clear
10473     @return {Ember.Set} An empty Set
10474   */
10475   clear: function() {
10476     if (this.isFrozen) { throw new Error(Ember.FROZEN_ERROR); }
10477
10478     var len = get(this, 'length');
10479     if (len === 0) { return this; }
10480
10481     var guid;
10482
10483     this.enumerableContentWillChange(len, 0);
10484     Ember.propertyWillChange(this, 'firstObject');
10485     Ember.propertyWillChange(this, 'lastObject');
10486
10487     for (var i=0; i < len; i++){
10488       guid = guidFor(this[i]);
10489       delete this[guid];
10490       delete this[i];
10491     }
10492
10493     set(this, 'length', 0);
10494
10495     Ember.propertyDidChange(this, 'firstObject');
10496     Ember.propertyDidChange(this, 'lastObject');
10497     this.enumerableContentDidChange(len, 0);
10498
10499     return this;
10500   },
10501
10502   /**
10503     Returns true if the passed object is also an enumerable that contains the
10504     same objects as the receiver.
10505
10506     ```javascript
10507     var colors = ["red", "green", "blue"],
10508         same_colors = new Ember.Set(colors);
10509
10510     same_colors.isEqual(colors);               // true
10511     same_colors.isEqual(["purple", "brown"]);  // false
10512     ```
10513
10514     @method isEqual
10515     @param {Ember.Set} obj the other object.
10516     @return {Boolean}
10517   */
10518   isEqual: function(obj) {
10519     // fail fast
10520     if (!Ember.Enumerable.detect(obj)) return false;
10521
10522     var loc = get(this, 'length');
10523     if (get(obj, 'length') !== loc) return false;
10524
10525     while(--loc >= 0) {
10526       if (!obj.contains(this[loc])) return false;
10527     }
10528
10529     return true;
10530   },
10531
10532   /**
10533     Adds an object to the set. Only non-`null` objects can be added to a set
10534     and those can only be added once. If the object is already in the set or
10535     the passed value is null this method will have no effect.
10536
10537     This is an alias for `Ember.MutableEnumerable.addObject()`.
10538
10539     ```javascript
10540     var colors = new Ember.Set();
10541     colors.add("blue");     // ["blue"]
10542     colors.add("blue");     // ["blue"]
10543     colors.add("red");      // ["blue", "red"]
10544     colors.add(null);       // ["blue", "red"]
10545     colors.add(undefined);  // ["blue", "red"]
10546     ```
10547
10548     @method add
10549     @param {Object} obj The object to add.
10550     @return {Ember.Set} The set itself.
10551   */
10552   add: Ember.aliasMethod('addObject'),
10553
10554   /**
10555     Removes the object from the set if it is found. If you pass a `null` value
10556     or an object that is already not in the set, this method will have no
10557     effect. This is an alias for `Ember.MutableEnumerable.removeObject()`.
10558
10559     ```javascript
10560     var colors = new Ember.Set(["red", "green", "blue"]);
10561     colors.remove("red");     // ["blue", "green"]
10562     colors.remove("purple");  // ["blue", "green"]
10563     colors.remove(null);      // ["blue", "green"]
10564     ```
10565
10566     @method remove
10567     @param {Object} obj The object to remove
10568     @return {Ember.Set} The set itself.
10569   */
10570   remove: Ember.aliasMethod('removeObject'),
10571
10572   /**
10573     Removes the last element from the set and returns it, or `null` if it's empty.
10574
10575     ```javascript
10576     var colors = new Ember.Set(["green", "blue"]);
10577     colors.pop();  // "blue"
10578     colors.pop();  // "green"
10579     colors.pop();  // null
10580     ```
10581
10582     @method pop
10583     @return {Object} The removed object from the set or null.
10584   */
10585   pop: function() {
10586     if (get(this, 'isFrozen')) throw new Error(Ember.FROZEN_ERROR);
10587     var obj = this.length > 0 ? this[this.length-1] : null;
10588     this.remove(obj);
10589     return obj;
10590   },
10591
10592   /**
10593     Inserts the given object on to the end of the set. It returns
10594     the set itself.
10595
10596     This is an alias for `Ember.MutableEnumerable.addObject()`.
10597
10598     ```javascript
10599     var colors = new Ember.Set();
10600     colors.push("red");   // ["red"]
10601     colors.push("green"); // ["red", "green"]
10602     colors.push("blue");  // ["red", "green", "blue"]
10603     ```
10604
10605     @method push
10606     @return {Ember.Set} The set itself.
10607   */
10608   push: Ember.aliasMethod('addObject'),
10609
10610   /**
10611     Removes the last element from the set and returns it, or `null` if it's empty.
10612
10613     This is an alias for `Ember.Set.pop()`.
10614
10615     ```javascript
10616     var colors = new Ember.Set(["green", "blue"]);
10617     colors.shift();  // "blue"
10618     colors.shift();  // "green"
10619     colors.shift();  // null
10620     ```
10621
10622     @method shift
10623     @return {Object} The removed object from the set or null.
10624   */
10625   shift: Ember.aliasMethod('pop'),
10626
10627   /**
10628     Inserts the given object on to the end of the set. It returns
10629     the set itself.
10630
10631     This is an alias of `Ember.Set.push()`
10632
10633     ```javascript
10634     var colors = new Ember.Set();
10635     colors.unshift("red");    // ["red"]
10636     colors.unshift("green");  // ["red", "green"]
10637     colors.unshift("blue");   // ["red", "green", "blue"]
10638     ```
10639
10640     @method unshift
10641     @return {Ember.Set} The set itself.
10642   */
10643   unshift: Ember.aliasMethod('push'),
10644
10645   /**
10646     Adds each object in the passed enumerable to the set.
10647
10648     This is an alias of `Ember.MutableEnumerable.addObjects()`
10649
10650     ```javascript
10651     var colors = new Ember.Set();
10652     colors.addEach(["red", "green", "blue"]);  // ["red", "green", "blue"]
10653     ```
10654
10655     @method addEach
10656     @param {Ember.Enumerable} objects the objects to add.
10657     @return {Ember.Set} The set itself.
10658   */
10659   addEach: Ember.aliasMethod('addObjects'),
10660
10661   /**
10662     Removes each object in the passed enumerable to the set.
10663
10664     This is an alias of `Ember.MutableEnumerable.removeObjects()`
10665
10666     ```javascript
10667     var colors = new Ember.Set(["red", "green", "blue"]);
10668     colors.removeEach(["red", "blue"]);  //  ["green"]
10669     ```
10670
10671     @method removeEach
10672     @param {Ember.Enumerable} objects the objects to remove.
10673     @return {Ember.Set} The set itself.
10674   */
10675   removeEach: Ember.aliasMethod('removeObjects'),
10676
10677   // ..........................................................
10678   // PRIVATE ENUMERABLE SUPPORT
10679   //
10680
10681   init: function(items) {
10682     this._super();
10683     if (items) this.addObjects(items);
10684   },
10685
10686   // implement Ember.Enumerable
10687   nextObject: function(idx) {
10688     return this[idx];
10689   },
10690
10691   // more optimized version
10692   firstObject: Ember.computed(function() {
10693     return this.length > 0 ? this[0] : undefined;
10694   }),
10695
10696   // more optimized version
10697   lastObject: Ember.computed(function() {
10698     return this.length > 0 ? this[this.length-1] : undefined;
10699   }),
10700
10701   // implements Ember.MutableEnumerable
10702   addObject: function(obj) {
10703     if (get(this, 'isFrozen')) throw new Error(Ember.FROZEN_ERROR);
10704     if (none(obj)) return this; // nothing to do
10705
10706     var guid = guidFor(obj),
10707         idx  = this[guid],
10708         len  = get(this, 'length'),
10709         added ;
10710
10711     if (idx>=0 && idx<len && (this[idx] === obj)) return this; // added
10712
10713     added = [obj];
10714
10715     this.enumerableContentWillChange(null, added);
10716     Ember.propertyWillChange(this, 'lastObject');
10717
10718     len = get(this, 'length');
10719     this[guid] = len;
10720     this[len] = obj;
10721     set(this, 'length', len+1);
10722
10723     Ember.propertyDidChange(this, 'lastObject');
10724     this.enumerableContentDidChange(null, added);
10725
10726     return this;
10727   },
10728
10729   // implements Ember.MutableEnumerable
10730   removeObject: function(obj) {
10731     if (get(this, 'isFrozen')) throw new Error(Ember.FROZEN_ERROR);
10732     if (none(obj)) return this; // nothing to do
10733
10734     var guid = guidFor(obj),
10735         idx  = this[guid],
10736         len = get(this, 'length'),
10737         isFirst = idx === 0,
10738         isLast = idx === len-1,
10739         last, removed;
10740
10741
10742     if (idx>=0 && idx<len && (this[idx] === obj)) {
10743       removed = [obj];
10744
10745       this.enumerableContentWillChange(removed, null);
10746       if (isFirst) { Ember.propertyWillChange(this, 'firstObject'); }
10747       if (isLast)  { Ember.propertyWillChange(this, 'lastObject'); }
10748
10749       // swap items - basically move the item to the end so it can be removed
10750       if (idx < len-1) {
10751         last = this[len-1];
10752         this[idx] = last;
10753         this[guidFor(last)] = idx;
10754       }
10755
10756       delete this[guid];
10757       delete this[len-1];
10758       set(this, 'length', len-1);
10759
10760       if (isFirst) { Ember.propertyDidChange(this, 'firstObject'); }
10761       if (isLast)  { Ember.propertyDidChange(this, 'lastObject'); }
10762       this.enumerableContentDidChange(removed, null);
10763     }
10764
10765     return this;
10766   },
10767
10768   // optimized version
10769   contains: function(obj) {
10770     return this[guidFor(obj)]>=0;
10771   },
10772
10773   copy: function() {
10774     var C = this.constructor, ret = new C(), loc = get(this, 'length');
10775     set(ret, 'length', loc);
10776     while(--loc>=0) {
10777       ret[loc] = this[loc];
10778       ret[guidFor(this[loc])] = loc;
10779     }
10780     return ret;
10781   },
10782
10783   toString: function() {
10784     var len = this.length, idx, array = [];
10785     for(idx = 0; idx < len; idx++) {
10786       array[idx] = this[idx];
10787     }
10788     return "Ember.Set<%@>".fmt(array.join(','));
10789   }
10790
10791 });
10792
10793 })();
10794
10795
10796
10797 (function() {
10798 /**
10799 @module ember
10800 @submodule ember-runtime
10801 */
10802
10803 /**
10804   `Ember.Object` is the main base class for all Ember objects. It is a subclass
10805   of `Ember.CoreObject` with the `Ember.Observable` mixin applied. For details,
10806   see the documentation for each of these.
10807
10808   @class Object
10809   @namespace Ember
10810   @extends Ember.CoreObject
10811   @uses Ember.Observable
10812 */
10813 Ember.Object = Ember.CoreObject.extend(Ember.Observable);
10814
10815 })();
10816
10817
10818
10819 (function() {
10820 /**
10821 @module ember
10822 @submodule ember-runtime
10823 */
10824
10825 var get = Ember.get, indexOf = Ember.ArrayPolyfills.indexOf;
10826
10827 /**
10828   A Namespace is an object usually used to contain other objects or methods
10829   such as an application or framework. Create a namespace anytime you want
10830   to define one of these new containers.
10831
10832   # Example Usage
10833
10834   ```javascript
10835   MyFramework = Ember.Namespace.create({
10836     VERSION: '1.0.0'
10837   });
10838   ```
10839
10840   @class Namespace
10841   @namespace Ember
10842   @extends Ember.Object
10843 */
10844 var Namespace = Ember.Namespace = Ember.Object.extend({
10845   isNamespace: true,
10846
10847   init: function() {
10848     Ember.Namespace.NAMESPACES.push(this);
10849     Ember.Namespace.PROCESSED = false;
10850   },
10851
10852   toString: function() {
10853     var name = get(this, 'name');
10854     if (name) { return name; }
10855
10856     findNamespaces();
10857     return this[Ember.GUID_KEY+'_name'];
10858   },
10859
10860   nameClasses: function() {
10861     processNamespace([this.toString()], this, {});
10862   },
10863
10864   destroy: function() {
10865     var namespaces = Ember.Namespace.NAMESPACES;
10866     Ember.lookup[this.toString()] = undefined;
10867     namespaces.splice(indexOf.call(namespaces, this), 1);
10868     this._super();
10869   }
10870 });
10871
10872 Namespace.reopenClass({
10873   NAMESPACES: [Ember],
10874   PROCESSED: false,
10875   processAll: processAllNamespaces
10876 });
10877
10878 var hasOwnProp = ({}).hasOwnProperty,
10879     guidFor = Ember.guidFor;
10880
10881 function processNamespace(paths, root, seen) {
10882   var idx = paths.length;
10883
10884   // Loop over all of the keys in the namespace, looking for classes
10885   for(var key in root) {
10886     if (!hasOwnProp.call(root, key)) { continue; }
10887     var obj = root[key];
10888
10889     // If we are processing the `Ember` namespace, for example, the
10890     // `paths` will start with `["Ember"]`. Every iteration through
10891     // the loop will update the **second** element of this list with
10892     // the key, so processing `Ember.View` will make the Array
10893     // `['Ember', 'View']`.
10894     paths[idx] = key;
10895
10896     // If we have found an unprocessed class
10897     if (obj && obj.toString === classToString) {
10898       // Replace the class' `toString` with the dot-separated path
10899       // and set its `NAME_KEY`
10900       obj.toString = makeToString(paths.join('.'));
10901       obj[NAME_KEY] = paths.join('.');
10902
10903     // Support nested namespaces
10904     } else if (obj && obj.isNamespace) {
10905       // Skip aliased namespaces
10906       if (seen[guidFor(obj)]) { continue; }
10907       seen[guidFor(obj)] = true;
10908
10909       // Process the child namespace
10910       processNamespace(paths, obj, seen);
10911     }
10912   }
10913
10914   paths.length = idx; // cut out last item
10915 }
10916
10917 function findNamespaces() {
10918   var Namespace = Ember.Namespace, lookup = Ember.lookup, obj, isNamespace;
10919
10920   if (Namespace.PROCESSED) { return; }
10921
10922   for (var prop in lookup) {
10923     // These don't raise exceptions but can cause warnings
10924     if (prop === "parent" || prop === "top" || prop === "frameElement") { continue; }
10925
10926     //  get(window.globalStorage, 'isNamespace') would try to read the storage for domain isNamespace and cause exception in Firefox.
10927     // globalStorage is a storage obsoleted by the WhatWG storage specification. See https://developer.mozilla.org/en/DOM/Storage#globalStorage
10928     if (prop === "globalStorage" && lookup.StorageList && lookup.globalStorage instanceof lookup.StorageList) { continue; }
10929     // Unfortunately, some versions of IE don't support window.hasOwnProperty
10930     if (lookup.hasOwnProperty && !lookup.hasOwnProperty(prop)) { continue; }
10931
10932     // At times we are not allowed to access certain properties for security reasons.
10933     // There are also times where even if we can access them, we are not allowed to access their properties.
10934     try {
10935       obj = Ember.lookup[prop];
10936       isNamespace = obj && obj.isNamespace;
10937     } catch (e) {
10938       continue;
10939     }
10940
10941     if (isNamespace) {
10942       Ember.deprecate("Namespaces should not begin with lowercase.", /^[A-Z]/.test(prop));
10943       obj[NAME_KEY] = prop;
10944     }
10945   }
10946 }
10947
10948 var NAME_KEY = Ember.NAME_KEY = Ember.GUID_KEY + '_name';
10949
10950 function superClassString(mixin) {
10951   var superclass = mixin.superclass;
10952   if (superclass) {
10953     if (superclass[NAME_KEY]) { return superclass[NAME_KEY]; }
10954     else { return superClassString(superclass); }
10955   } else {
10956     return;
10957   }
10958 }
10959
10960 function classToString() {
10961   if (!Ember.BOOTED && !this[NAME_KEY]) {
10962     processAllNamespaces();
10963   }
10964
10965   var ret;
10966
10967   if (this[NAME_KEY]) {
10968     ret = this[NAME_KEY];
10969   } else {
10970     var str = superClassString(this);
10971     if (str) {
10972       ret = "(subclass of " + str + ")";
10973     } else {
10974       ret = "(unknown mixin)";
10975     }
10976     this.toString = makeToString(ret);
10977   }
10978
10979   return ret;
10980 }
10981
10982 function processAllNamespaces() {
10983   if (!Namespace.PROCESSED) {
10984     findNamespaces();
10985     Namespace.PROCESSED = true;
10986   }
10987
10988   if (Ember.anyUnprocessedMixins) {
10989     var namespaces = Namespace.NAMESPACES, namespace;
10990     for (var i=0, l=namespaces.length; i<l; i++) {
10991       namespace = namespaces[i];
10992       processNamespace([namespace.toString()], namespace, {});
10993     }
10994
10995     Ember.anyUnprocessedMixins = false;
10996   }
10997 }
10998
10999 function makeToString(ret) {
11000   return function() { return ret; };
11001 }
11002
11003 Ember.Mixin.prototype.toString = classToString;
11004
11005 })();
11006
11007
11008
11009 (function() {
11010 /**
11011 @module ember
11012 @submodule ember-runtime
11013 */
11014
11015 /**
11016   Defines a namespace that will contain an executable application. This is
11017   very similar to a normal namespace except that it is expected to include at
11018   least a 'ready' function which can be run to initialize the application.
11019
11020   Currently `Ember.Application` is very similar to `Ember.Namespace.`  However,
11021   this class may be augmented by additional frameworks so it is important to
11022   use this instance when building new applications.
11023
11024   # Example Usage
11025
11026   ```javascript
11027   MyApp = Ember.Application.create({
11028     VERSION: '1.0.0',
11029     store: Ember.Store.create().from(Ember.fixtures)
11030   });
11031
11032   MyApp.ready = function() {
11033     //..init code goes here...
11034   }
11035   ```
11036
11037   @class Application
11038   @namespace Ember
11039   @extends Ember.Namespace
11040 */
11041 Ember.Application = Ember.Namespace.extend();
11042
11043
11044 })();
11045
11046
11047
11048 (function() {
11049 /**
11050 @module ember
11051 @submodule ember-runtime
11052 */
11053
11054
11055 var get = Ember.get, set = Ember.set;
11056
11057 /**
11058   An ArrayProxy wraps any other object that implements `Ember.Array` and/or
11059   `Ember.MutableArray,` forwarding all requests. This makes it very useful for
11060   a number of binding use cases or other cases where being able to swap
11061   out the underlying array is useful.
11062
11063   A simple example of usage:
11064
11065   ```javascript
11066   var pets = ['dog', 'cat', 'fish'];
11067   var ap = Ember.ArrayProxy.create({ content: Ember.A(pets) });
11068
11069   ap.get('firstObject');                        // 'dog'
11070   ap.set('content', ['amoeba', 'paramecium']);
11071   ap.get('firstObject');                        // 'amoeba'
11072   ```
11073
11074   This class can also be useful as a layer to transform the contents of
11075   an array, as they are accessed. This can be done by overriding
11076   `objectAtContent`:
11077
11078   ```javascript
11079   var pets = ['dog', 'cat', 'fish'];
11080   var ap = Ember.ArrayProxy.create({
11081       content: Ember.A(pets),
11082       objectAtContent: function(idx) {
11083           return this.get('content').objectAt(idx).toUpperCase();
11084       }
11085   });
11086
11087   ap.get('firstObject'); // . 'DOG'
11088   ```
11089
11090   @class ArrayProxy
11091   @namespace Ember
11092   @extends Ember.Object
11093   @uses Ember.MutableArray
11094 */
11095 Ember.ArrayProxy = Ember.Object.extend(Ember.MutableArray,
11096 /** @scope Ember.ArrayProxy.prototype */ {
11097
11098   /**
11099     The content array. Must be an object that implements `Ember.Array` and/or
11100     `Ember.MutableArray.`
11101
11102     @property content
11103     @type Ember.Array
11104   */
11105   content: null,
11106
11107   /**
11108    The array that the proxy pretends to be. In the default `ArrayProxy`
11109    implementation, this and `content` are the same. Subclasses of `ArrayProxy`
11110    can override this property to provide things like sorting and filtering.
11111
11112    @property arrangedContent
11113   */
11114   arrangedContent: Ember.computed('content', function() {
11115     return get(this, 'content');
11116   }),
11117
11118   /**
11119     Should actually retrieve the object at the specified index from the
11120     content. You can override this method in subclasses to transform the
11121     content item to something new.
11122
11123     This method will only be called if content is non-`null`.
11124
11125     @method objectAtContent
11126     @param {Number} idx The index to retrieve.
11127     @return {Object} the value or undefined if none found
11128   */
11129   objectAtContent: function(idx) {
11130     return get(this, 'arrangedContent').objectAt(idx);
11131   },
11132
11133   /**
11134     Should actually replace the specified objects on the content array.
11135     You can override this method in subclasses to transform the content item
11136     into something new.
11137
11138     This method will only be called if content is non-`null`.
11139
11140     @method replaceContent
11141     @param {Number} idx The starting index
11142     @param {Number} amt The number of items to remove from the content.
11143     @param {Array} objects Optional array of objects to insert or null if no
11144       objects.
11145     @return {void}
11146   */
11147   replaceContent: function(idx, amt, objects) {
11148     get(this, 'content').replace(idx, amt, objects);
11149   },
11150
11151   /**
11152     @private
11153
11154     Invoked when the content property is about to change. Notifies observers that the
11155     entire array content will change.
11156
11157     @method _contentWillChange
11158   */
11159   _contentWillChange: Ember.beforeObserver(function() {
11160     this._teardownContent();
11161   }, 'content'),
11162
11163   _teardownContent: function() {
11164     var content = get(this, 'content');
11165
11166     if (content) {
11167       content.removeArrayObserver(this, {
11168         willChange: 'contentArrayWillChange',
11169         didChange: 'contentArrayDidChange'
11170       });
11171     }
11172   },
11173
11174   contentArrayWillChange: Ember.K,
11175   contentArrayDidChange: Ember.K,
11176
11177   /**
11178     @private
11179
11180     Invoked when the content property changes. Notifies observers that the
11181     entire array content has changed.
11182
11183     @method _contentDidChange
11184   */
11185   _contentDidChange: Ember.observer(function() {
11186     var content = get(this, 'content');
11187
11188     Ember.assert("Can't set ArrayProxy's content to itself", content !== this);
11189
11190     this._setupContent();
11191   }, 'content'),
11192
11193   _setupContent: function() {
11194     var content = get(this, 'content');
11195
11196     if (content) {
11197       content.addArrayObserver(this, {
11198         willChange: 'contentArrayWillChange',
11199         didChange: 'contentArrayDidChange'
11200       });
11201     }
11202   },
11203
11204   _arrangedContentWillChange: Ember.beforeObserver(function() {
11205     var arrangedContent = get(this, 'arrangedContent'),
11206         len = arrangedContent ? get(arrangedContent, 'length') : 0;
11207
11208     this.arrangedContentArrayWillChange(this, 0, len, undefined);
11209     this.arrangedContentWillChange(this);
11210
11211     this._teardownArrangedContent(arrangedContent);
11212   }, 'arrangedContent'),
11213
11214   _arrangedContentDidChange: Ember.observer(function() {
11215     var arrangedContent = get(this, 'arrangedContent'),
11216         len = arrangedContent ? get(arrangedContent, 'length') : 0;
11217
11218     Ember.assert("Can't set ArrayProxy's content to itself", arrangedContent !== this);
11219
11220     this._setupArrangedContent();
11221
11222     this.arrangedContentDidChange(this);
11223     this.arrangedContentArrayDidChange(this, 0, undefined, len);
11224   }, 'arrangedContent'),
11225
11226   _setupArrangedContent: function() {
11227     var arrangedContent = get(this, 'arrangedContent');
11228
11229     if (arrangedContent) {
11230       arrangedContent.addArrayObserver(this, {
11231         willChange: 'arrangedContentArrayWillChange',
11232         didChange: 'arrangedContentArrayDidChange'
11233       });
11234     }
11235   },
11236
11237   _teardownArrangedContent: function() {
11238     var arrangedContent = get(this, 'arrangedContent');
11239
11240     if (arrangedContent) {
11241       arrangedContent.removeArrayObserver(this, {
11242         willChange: 'arrangedContentArrayWillChange',
11243         didChange: 'arrangedContentArrayDidChange'
11244       });
11245     }
11246   },
11247
11248   arrangedContentWillChange: Ember.K,
11249   arrangedContentDidChange: Ember.K,
11250
11251   objectAt: function(idx) {
11252     return get(this, 'content') && this.objectAtContent(idx);
11253   },
11254
11255   length: Ember.computed(function() {
11256     var arrangedContent = get(this, 'arrangedContent');
11257     return arrangedContent ? get(arrangedContent, 'length') : 0;
11258     // No dependencies since Enumerable notifies length of change
11259   }),
11260
11261   replace: function(idx, amt, objects) {
11262     Ember.assert('The content property of '+ this.constructor + ' should be set before modifying it', this.get('content'));
11263     if (get(this, 'content')) this.replaceContent(idx, amt, objects);
11264     return this;
11265   },
11266
11267   arrangedContentArrayWillChange: function(item, idx, removedCnt, addedCnt) {
11268     this.arrayContentWillChange(idx, removedCnt, addedCnt);
11269   },
11270
11271   arrangedContentArrayDidChange: function(item, idx, removedCnt, addedCnt) {
11272     this.arrayContentDidChange(idx, removedCnt, addedCnt);
11273   },
11274
11275   init: function() {
11276     this._super();
11277     this._setupContent();
11278     this._setupArrangedContent();
11279   },
11280
11281   willDestroy: function() {
11282     this._teardownArrangedContent();
11283     this._teardownContent();
11284   }
11285 });
11286
11287
11288 })();
11289
11290
11291
11292 (function() {
11293 /**
11294 @module ember
11295 @submodule ember-runtime
11296 */
11297
11298 var get = Ember.get,
11299     set = Ember.set,
11300     fmt = Ember.String.fmt,
11301     addBeforeObserver = Ember.addBeforeObserver,
11302     addObserver = Ember.addObserver,
11303     removeBeforeObserver = Ember.removeBeforeObserver,
11304     removeObserver = Ember.removeObserver,
11305     propertyWillChange = Ember.propertyWillChange,
11306     propertyDidChange = Ember.propertyDidChange;
11307
11308 function contentPropertyWillChange(content, contentKey) {
11309   var key = contentKey.slice(8); // remove "content."
11310   if (key in this) { return; }  // if shadowed in proxy
11311   propertyWillChange(this, key);
11312 }
11313
11314 function contentPropertyDidChange(content, contentKey) {
11315   var key = contentKey.slice(8); // remove "content."
11316   if (key in this) { return; } // if shadowed in proxy
11317   propertyDidChange(this, key);
11318 }
11319
11320 /**
11321   `Ember.ObjectProxy` forwards all properties not defined by the proxy itself
11322   to a proxied `content` object.
11323
11324   ```javascript
11325   object = Ember.Object.create({
11326     name: 'Foo'
11327   });
11328
11329   proxy = Ember.ObjectProxy.create({
11330     content: object
11331   });
11332
11333   // Access and change existing properties
11334   proxy.get('name')          // 'Foo'
11335   proxy.set('name', 'Bar');
11336   object.get('name')         // 'Bar'
11337
11338   // Create new 'description' property on `object`
11339   proxy.set('description', 'Foo is a whizboo baz');
11340   object.get('description')  // 'Foo is a whizboo baz'
11341   ```
11342
11343   While `content` is unset, setting a property to be delegated will throw an
11344   Error.
11345
11346   ```javascript
11347   proxy = Ember.ObjectProxy.create({
11348     content: null,
11349     flag: null
11350   });
11351   proxy.set('flag', true);
11352   proxy.get('flag');         // true
11353   proxy.get('foo');          // undefined
11354   proxy.set('foo', 'data');  // throws Error
11355   ```
11356
11357   Delegated properties can be bound to and will change when content is updated.
11358
11359   Computed properties on the proxy itself can depend on delegated properties.
11360
11361   ```javascript
11362   ProxyWithComputedProperty = Ember.ObjectProxy.extend({
11363     fullName: function () {
11364       var firstName = this.get('firstName'),
11365           lastName = this.get('lastName');
11366       if (firstName && lastName) {
11367         return firstName + ' ' + lastName;
11368       }
11369       return firstName || lastName;
11370     }.property('firstName', 'lastName')
11371   });
11372
11373   proxy = ProxyWithComputedProperty.create();
11374
11375   proxy.get('fullName');  // undefined
11376   proxy.set('content', {
11377     firstName: 'Tom', lastName: 'Dale'
11378   }); // triggers property change for fullName on proxy
11379
11380   proxy.get('fullName');  // 'Tom Dale'
11381   ```
11382
11383   @class ObjectProxy
11384   @namespace Ember
11385   @extends Ember.Object
11386 */
11387 Ember.ObjectProxy = Ember.Object.extend(
11388 /** @scope Ember.ObjectProxy.prototype */ {
11389   /**
11390     The object whose properties will be forwarded.
11391
11392     @property content
11393     @type Ember.Object
11394     @default null
11395   */
11396   content: null,
11397   _contentDidChange: Ember.observer(function() {
11398     Ember.assert("Can't set ObjectProxy's content to itself", this.get('content') !== this);
11399   }, 'content'),
11400
11401   willWatchProperty: function (key) {
11402     var contentKey = 'content.' + key;
11403     addBeforeObserver(this, contentKey, null, contentPropertyWillChange);
11404     addObserver(this, contentKey, null, contentPropertyDidChange);
11405   },
11406
11407   didUnwatchProperty: function (key) {
11408     var contentKey = 'content.' + key;
11409     removeBeforeObserver(this, contentKey, null, contentPropertyWillChange);
11410     removeObserver(this, contentKey, null, contentPropertyDidChange);
11411   },
11412
11413   unknownProperty: function (key) {
11414     var content = get(this, 'content');
11415     if (content) {
11416       return get(content, key);
11417     }
11418   },
11419
11420   setUnknownProperty: function (key, value) {
11421     var content = get(this, 'content');
11422     Ember.assert(fmt("Cannot delegate set('%@', %@) to the 'content' property of object proxy %@: its 'content' is undefined.", [key, value, this]), content);
11423     return set(content, key, value);
11424   }
11425 });
11426
11427 })();
11428
11429
11430
11431 (function() {
11432 /**
11433 @module ember
11434 @submodule ember-runtime
11435 */
11436
11437
11438 var set = Ember.set, get = Ember.get, guidFor = Ember.guidFor;
11439 var forEach = Ember.EnumerableUtils.forEach;
11440
11441 var EachArray = Ember.Object.extend(Ember.Array, {
11442
11443   init: function(content, keyName, owner) {
11444     this._super();
11445     this._keyName = keyName;
11446     this._owner   = owner;
11447     this._content = content;
11448   },
11449
11450   objectAt: function(idx) {
11451     var item = this._content.objectAt(idx);
11452     return item && get(item, this._keyName);
11453   },
11454
11455   length: Ember.computed(function() {
11456     var content = this._content;
11457     return content ? get(content, 'length') : 0;
11458   })
11459
11460 });
11461
11462 var IS_OBSERVER = /^.+:(before|change)$/;
11463
11464 function addObserverForContentKey(content, keyName, proxy, idx, loc) {
11465   var objects = proxy._objects, guid;
11466   if (!objects) objects = proxy._objects = {};
11467
11468   while(--loc>=idx) {
11469     var item = content.objectAt(loc);
11470     if (item) {
11471       Ember.addBeforeObserver(item, keyName, proxy, 'contentKeyWillChange');
11472       Ember.addObserver(item, keyName, proxy, 'contentKeyDidChange');
11473
11474       // keep track of the indicies each item was found at so we can map
11475       // it back when the obj changes.
11476       guid = guidFor(item);
11477       if (!objects[guid]) objects[guid] = [];
11478       objects[guid].push(loc);
11479     }
11480   }
11481 }
11482
11483 function removeObserverForContentKey(content, keyName, proxy, idx, loc) {
11484   var objects = proxy._objects;
11485   if (!objects) objects = proxy._objects = {};
11486   var indicies, guid;
11487
11488   while(--loc>=idx) {
11489     var item = content.objectAt(loc);
11490     if (item) {
11491       Ember.removeBeforeObserver(item, keyName, proxy, 'contentKeyWillChange');
11492       Ember.removeObserver(item, keyName, proxy, 'contentKeyDidChange');
11493
11494       guid = guidFor(item);
11495       indicies = objects[guid];
11496       indicies[indicies.indexOf(loc)] = null;
11497     }
11498   }
11499 }
11500
11501 /**
11502   This is the object instance returned when you get the `@each` property on an
11503   array. It uses the unknownProperty handler to automatically create
11504   EachArray instances for property names.
11505
11506   @private
11507   @class EachProxy
11508   @namespace Ember
11509   @extends Ember.Object
11510 */
11511 Ember.EachProxy = Ember.Object.extend({
11512
11513   init: function(content) {
11514     this._super();
11515     this._content = content;
11516     content.addArrayObserver(this);
11517
11518     // in case someone is already observing some keys make sure they are
11519     // added
11520     forEach(Ember.watchedEvents(this), function(eventName) {
11521       this.didAddListener(eventName);
11522     }, this);
11523   },
11524
11525   /**
11526     You can directly access mapped properties by simply requesting them.
11527     The `unknownProperty` handler will generate an EachArray of each item.
11528
11529     @method unknownProperty
11530     @param keyName {String}
11531     @param value {anything}
11532   */
11533   unknownProperty: function(keyName, value) {
11534     var ret;
11535     ret = new EachArray(this._content, keyName, this);
11536     Ember.defineProperty(this, keyName, null, ret);
11537     this.beginObservingContentKey(keyName);
11538     return ret;
11539   },
11540
11541   // ..........................................................
11542   // ARRAY CHANGES
11543   // Invokes whenever the content array itself changes.
11544
11545   arrayWillChange: function(content, idx, removedCnt, addedCnt) {
11546     var keys = this._keys, key, array, lim;
11547
11548     lim = removedCnt>0 ? idx+removedCnt : -1;
11549     Ember.beginPropertyChanges(this);
11550
11551     for(key in keys) {
11552       if (!keys.hasOwnProperty(key)) { continue; }
11553
11554       if (lim>0) removeObserverForContentKey(content, key, this, idx, lim);
11555
11556       Ember.propertyWillChange(this, key);
11557     }
11558
11559     Ember.propertyWillChange(this._content, '@each');
11560     Ember.endPropertyChanges(this);
11561   },
11562
11563   arrayDidChange: function(content, idx, removedCnt, addedCnt) {
11564     var keys = this._keys, key, array, lim;
11565
11566     lim = addedCnt>0 ? idx+addedCnt : -1;
11567     Ember.beginPropertyChanges(this);
11568
11569     for(key in keys) {
11570       if (!keys.hasOwnProperty(key)) { continue; }
11571
11572       if (lim>0) addObserverForContentKey(content, key, this, idx, lim);
11573
11574       Ember.propertyDidChange(this, key);
11575     }
11576
11577     Ember.propertyDidChange(this._content, '@each');
11578     Ember.endPropertyChanges(this);
11579   },
11580
11581   // ..........................................................
11582   // LISTEN FOR NEW OBSERVERS AND OTHER EVENT LISTENERS
11583   // Start monitoring keys based on who is listening...
11584
11585   didAddListener: function(eventName) {
11586     if (IS_OBSERVER.test(eventName)) {
11587       this.beginObservingContentKey(eventName.slice(0, -7));
11588     }
11589   },
11590
11591   didRemoveListener: function(eventName) {
11592     if (IS_OBSERVER.test(eventName)) {
11593       this.stopObservingContentKey(eventName.slice(0, -7));
11594     }
11595   },
11596
11597   // ..........................................................
11598   // CONTENT KEY OBSERVING
11599   // Actual watch keys on the source content.
11600
11601   beginObservingContentKey: function(keyName) {
11602     var keys = this._keys;
11603     if (!keys) keys = this._keys = {};
11604     if (!keys[keyName]) {
11605       keys[keyName] = 1;
11606       var content = this._content,
11607           len = get(content, 'length');
11608       addObserverForContentKey(content, keyName, this, 0, len);
11609     } else {
11610       keys[keyName]++;
11611     }
11612   },
11613
11614   stopObservingContentKey: function(keyName) {
11615     var keys = this._keys;
11616     if (keys && (keys[keyName]>0) && (--keys[keyName]<=0)) {
11617       var content = this._content,
11618           len     = get(content, 'length');
11619       removeObserverForContentKey(content, keyName, this, 0, len);
11620     }
11621   },
11622
11623   contentKeyWillChange: function(obj, keyName) {
11624     Ember.propertyWillChange(this, keyName);
11625   },
11626
11627   contentKeyDidChange: function(obj, keyName) {
11628     Ember.propertyDidChange(this, keyName);
11629   }
11630
11631 });
11632
11633
11634
11635 })();
11636
11637
11638
11639 (function() {
11640 /**
11641 @module ember
11642 @submodule ember-runtime
11643 */
11644
11645
11646 var get = Ember.get, set = Ember.set;
11647
11648 // Add Ember.Array to Array.prototype. Remove methods with native
11649 // implementations and supply some more optimized versions of generic methods
11650 // because they are so common.
11651 var NativeArray = Ember.Mixin.create(Ember.MutableArray, Ember.Observable, Ember.Copyable, {
11652
11653   // because length is a built-in property we need to know to just get the
11654   // original property.
11655   get: function(key) {
11656     if (key==='length') return this.length;
11657     else if ('number' === typeof key) return this[key];
11658     else return this._super(key);
11659   },
11660
11661   objectAt: function(idx) {
11662     return this[idx];
11663   },
11664
11665   // primitive for array support.
11666   replace: function(idx, amt, objects) {
11667
11668     if (this.isFrozen) throw Ember.FROZEN_ERROR ;
11669
11670     // if we replaced exactly the same number of items, then pass only the
11671     // replaced range. Otherwise, pass the full remaining array length
11672     // since everything has shifted
11673     var len = objects ? get(objects, 'length') : 0;
11674     this.arrayContentWillChange(idx, amt, len);
11675
11676     if (!objects || objects.length === 0) {
11677       this.splice(idx, amt) ;
11678     } else {
11679       var args = [idx, amt].concat(objects) ;
11680       this.splice.apply(this,args) ;
11681     }
11682
11683     this.arrayContentDidChange(idx, amt, len);
11684     return this ;
11685   },
11686
11687   // If you ask for an unknown property, then try to collect the value
11688   // from member items.
11689   unknownProperty: function(key, value) {
11690     var ret;// = this.reducedProperty(key, value) ;
11691     if ((value !== undefined) && ret === undefined) {
11692       ret = this[key] = value;
11693     }
11694     return ret ;
11695   },
11696
11697   // If browser did not implement indexOf natively, then override with
11698   // specialized version
11699   indexOf: function(object, startAt) {
11700     var idx, len = this.length;
11701
11702     if (startAt === undefined) startAt = 0;
11703     else startAt = (startAt < 0) ? Math.ceil(startAt) : Math.floor(startAt);
11704     if (startAt < 0) startAt += len;
11705
11706     for(idx=startAt;idx<len;idx++) {
11707       if (this[idx] === object) return idx ;
11708     }
11709     return -1;
11710   },
11711
11712   lastIndexOf: function(object, startAt) {
11713     var idx, len = this.length;
11714
11715     if (startAt === undefined) startAt = len-1;
11716     else startAt = (startAt < 0) ? Math.ceil(startAt) : Math.floor(startAt);
11717     if (startAt < 0) startAt += len;
11718
11719     for(idx=startAt;idx>=0;idx--) {
11720       if (this[idx] === object) return idx ;
11721     }
11722     return -1;
11723   },
11724
11725   copy: function(deep) {
11726     if (deep) {
11727       return this.map(function(item){ return Ember.copy(item, true); });
11728     }
11729
11730     return this.slice();
11731   }
11732 });
11733
11734 // Remove any methods implemented natively so we don't override them
11735 var ignore = ['length'];
11736 Ember.EnumerableUtils.forEach(NativeArray.keys(), function(methodName) {
11737   if (Array.prototype[methodName]) ignore.push(methodName);
11738 });
11739
11740 if (ignore.length>0) {
11741   NativeArray = NativeArray.without.apply(NativeArray, ignore);
11742 }
11743
11744 /**
11745   The NativeArray mixin contains the properties needed to to make the native
11746   Array support Ember.MutableArray and all of its dependent APIs. Unless you
11747   have `Ember.EXTEND_PROTOTYPES or `Ember.EXTEND_PROTOTYPES.Array` set to
11748   false, this will be applied automatically. Otherwise you can apply the mixin
11749   at anytime by calling `Ember.NativeArray.activate`.
11750
11751   @class NativeArray
11752   @namespace Ember
11753   @extends Ember.Mixin
11754   @uses Ember.MutableArray
11755   @uses Ember.MutableEnumerable
11756   @uses Ember.Copyable
11757   @uses Ember.Freezable
11758 */
11759 Ember.NativeArray = NativeArray;
11760
11761 /**
11762   Creates an `Ember.NativeArray` from an Array like object.
11763   Does not modify the original object.
11764
11765   @method A
11766   @for Ember
11767   @return {Ember.NativeArray}
11768 */
11769 Ember.A = function(arr){
11770   if (arr === undefined) { arr = []; }
11771   return Ember.Array.detect(arr) ? arr : Ember.NativeArray.apply(arr);
11772 };
11773
11774 /**
11775   Activates the mixin on the Array.prototype if not already applied. Calling
11776   this method more than once is safe.
11777
11778   @method activate
11779   @for Ember.NativeArray
11780   @static
11781   @return {void}
11782 */
11783 Ember.NativeArray.activate = function() {
11784   NativeArray.apply(Array.prototype);
11785
11786   Ember.A = function(arr) { return arr || []; };
11787 };
11788
11789 if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Array) {
11790   Ember.NativeArray.activate();
11791 }
11792
11793
11794 })();
11795
11796
11797
11798 (function() {
11799 var DeferredMixin = Ember.DeferredMixin, // mixins/deferred
11800     EmberObject = Ember.Object,          // system/object
11801     get = Ember.get;
11802
11803 var Deferred = Ember.Object.extend(DeferredMixin);
11804
11805 Deferred.reopenClass({
11806   promise: function(callback, binding) {
11807     var deferred = Deferred.create();
11808     callback.call(binding, deferred);
11809     return get(deferred, 'promise');
11810   }
11811 });
11812
11813 Ember.Deferred = Deferred;
11814
11815 })();
11816
11817
11818
11819 (function() {
11820 /**
11821 @module ember
11822 @submodule ember-runtime
11823 */
11824
11825 var loadHooks = {};
11826 var loaded = {};
11827
11828 /**
11829 @method onLoad
11830 @for Ember
11831 @param name {String} name of hook
11832 @param callback {Function} callback to be called
11833 */
11834 Ember.onLoad = function(name, callback) {
11835   var object;
11836
11837   loadHooks[name] = loadHooks[name] || Ember.A();
11838   loadHooks[name].pushObject(callback);
11839
11840   if (object = loaded[name]) {
11841     callback(object);
11842   }
11843 };
11844
11845 /**
11846 @method runLoadHooks
11847 @for Ember
11848 @param name {String} name of hook
11849 @param object {Object} object to pass to callbacks
11850 */
11851 Ember.runLoadHooks = function(name, object) {
11852   var hooks;
11853
11854   loaded[name] = object;
11855
11856   if (hooks = loadHooks[name]) {
11857     loadHooks[name].forEach(function(callback) {
11858       callback(object);
11859     });
11860   }
11861 };
11862
11863 })();
11864
11865
11866
11867 (function() {
11868
11869 })();
11870
11871
11872
11873 (function() {
11874 var get = Ember.get;
11875
11876 /**
11877 @module ember
11878 @submodule ember-runtime
11879 */
11880
11881 /**
11882   `Ember.ControllerMixin` provides a standard interface for all classes that
11883   compose Ember's controller layer: `Ember.Controller`,
11884   `Ember.ArrayController`, and `Ember.ObjectController`.
11885
11886   Within an `Ember.Router`-managed application single shared instaces of every
11887   Controller object in your application's namespace will be added to the
11888   application's `Ember.Router` instance. See `Ember.Application#initialize`
11889   for additional information.
11890
11891   ## Views
11892
11893   By default a controller instance will be the rendering context
11894   for its associated `Ember.View.` This connection is made during calls to
11895   `Ember.ControllerMixin#connectOutlet`.
11896
11897   Within the view's template, the `Ember.View` instance can be accessed
11898   through the controller with `{{view}}`.
11899
11900   ## Target Forwarding
11901
11902   By default a controller will target your application's `Ember.Router`
11903   instance. Calls to `{{action}}` within the template of a controller's view
11904   are forwarded to the router. See `Ember.Handlebars.helpers.action` for
11905   additional information.
11906
11907   @class ControllerMixin
11908   @namespace Ember
11909   @extends Ember.Mixin
11910 */
11911 Ember.ControllerMixin = Ember.Mixin.create({
11912   /**
11913     The object to which events from the view should be sent.
11914
11915     For example, when a Handlebars template uses the `{{action}}` helper,
11916     it will attempt to send the event to the view's controller's `target`.
11917
11918     By default, a controller's `target` is set to the router after it is
11919     instantiated by `Ember.Application#initialize`.
11920
11921     @property target
11922     @default null
11923   */
11924   target: null,
11925
11926   container: null,
11927
11928   store: null,
11929
11930   send: function(actionName) {
11931     var args = [].slice.call(arguments, 1), target;
11932
11933     if (this[actionName]) {
11934       Ember.assert("The controller " + this + " does not have the action " + actionName, typeof this[actionName] === 'function');
11935       this[actionName].apply(this, args);
11936     } else if(target = get(this, 'target')) {
11937       Ember.assert("The target for controller " + this + " (" + target + ") did not define a `send` method", typeof target.send === 'function');
11938       target.send.apply(target, arguments);
11939     }
11940   }
11941 });
11942
11943 /**
11944   @class Controller
11945   @namespace Ember
11946   @extends Ember.Object
11947   @uses Ember.ControllerMixin
11948 */
11949 Ember.Controller = Ember.Object.extend(Ember.ControllerMixin);
11950
11951 })();
11952
11953
11954
11955 (function() {
11956 /**
11957 @module ember
11958 @submodule ember-runtime
11959 */
11960
11961 var get = Ember.get, set = Ember.set, forEach = Ember.EnumerableUtils.forEach;
11962
11963 /**
11964   `Ember.SortableMixin` provides a standard interface for array proxies
11965   to specify a sort order and maintain this sorting when objects are added,
11966   removed, or updated without changing the implicit order of their underlying
11967   content array:
11968
11969   ```javascript
11970   songs = [
11971     {trackNumber: 4, title: 'Ob-La-Di, Ob-La-Da'},
11972     {trackNumber: 2, title: 'Back in the U.S.S.R.'},
11973     {trackNumber: 3, title: 'Glass Onion'},
11974   ];
11975
11976   songsController = Ember.ArrayController.create({
11977     content: songs,
11978     sortProperties: ['trackNumber']
11979   });
11980
11981   songsController.get('firstObject');  // {trackNumber: 2, title: 'Back in the U.S.S.R.'}
11982
11983   songsController.addObject({trackNumber: 1, title: 'Dear Prudence'});
11984   songsController.get('firstObject');  // {trackNumber: 1, title: 'Dear Prudence'}
11985   ```
11986
11987   @class SortableMixin
11988   @namespace Ember
11989   @extends Ember.Mixin
11990   @uses Ember.MutableEnumerable
11991 */
11992 Ember.SortableMixin = Ember.Mixin.create(Ember.MutableEnumerable, {
11993   sortProperties: null,
11994   sortAscending: true,
11995
11996   orderBy: function(item1, item2) {
11997     var result = 0,
11998         sortProperties = get(this, 'sortProperties'),
11999         sortAscending = get(this, 'sortAscending');
12000
12001     Ember.assert("you need to define `sortProperties`", !!sortProperties);
12002
12003     forEach(sortProperties, function(propertyName) {
12004       if (result === 0) {
12005         result = Ember.compare(get(item1, propertyName), get(item2, propertyName));
12006         if ((result !== 0) && !sortAscending) {
12007           result = (-1) * result;
12008         }
12009       }
12010     });
12011
12012     return result;
12013   },
12014
12015   destroy: function() {
12016     var content = get(this, 'content'),
12017         sortProperties = get(this, 'sortProperties');
12018
12019     if (content && sortProperties) {
12020       forEach(content, function(item) {
12021         forEach(sortProperties, function(sortProperty) {
12022           Ember.removeObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
12023         }, this);
12024       }, this);
12025     }
12026
12027     return this._super();
12028   },
12029
12030   isSorted: Ember.computed('sortProperties', function() {
12031     return !!get(this, 'sortProperties');
12032   }),
12033
12034   arrangedContent: Ember.computed('content', 'sortProperties.@each', function(key, value) {
12035     var content = get(this, 'content'),
12036         isSorted = get(this, 'isSorted'),
12037         sortProperties = get(this, 'sortProperties'),
12038         self = this;
12039
12040     if (content && isSorted) {
12041       content = content.slice();
12042       content.sort(function(item1, item2) {
12043         return self.orderBy(item1, item2);
12044       });
12045       forEach(content, function(item) {
12046         forEach(sortProperties, function(sortProperty) {
12047           Ember.addObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
12048         }, this);
12049       }, this);
12050       return Ember.A(content);
12051     }
12052
12053     return content;
12054   }),
12055
12056   _contentWillChange: Ember.beforeObserver(function() {
12057     var content = get(this, 'content'),
12058         sortProperties = get(this, 'sortProperties');
12059
12060     if (content && sortProperties) {
12061       forEach(content, function(item) {
12062         forEach(sortProperties, function(sortProperty) {
12063           Ember.removeObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
12064         }, this);
12065       }, this);
12066     }
12067
12068     this._super();
12069   }, 'content'),
12070
12071   sortAscendingWillChange: Ember.beforeObserver(function() {
12072     this._lastSortAscending = get(this, 'sortAscending');
12073   }, 'sortAscending'),
12074
12075   sortAscendingDidChange: Ember.observer(function() {
12076     if (get(this, 'sortAscending') !== this._lastSortAscending) {
12077       var arrangedContent = get(this, 'arrangedContent');
12078       arrangedContent.reverseObjects();
12079     }
12080   }, 'sortAscending'),
12081
12082   contentArrayWillChange: function(array, idx, removedCount, addedCount) {
12083     var isSorted = get(this, 'isSorted');
12084
12085     if (isSorted) {
12086       var arrangedContent = get(this, 'arrangedContent');
12087       var removedObjects = array.slice(idx, idx+removedCount);
12088       var sortProperties = get(this, 'sortProperties');
12089
12090       forEach(removedObjects, function(item) {
12091         arrangedContent.removeObject(item);
12092
12093         forEach(sortProperties, function(sortProperty) {
12094           Ember.removeObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
12095         }, this);
12096       }, this);
12097     }
12098
12099     return this._super(array, idx, removedCount, addedCount);
12100   },
12101
12102   contentArrayDidChange: function(array, idx, removedCount, addedCount) {
12103     var isSorted = get(this, 'isSorted'),
12104         sortProperties = get(this, 'sortProperties');
12105
12106     if (isSorted) {
12107       var addedObjects = array.slice(idx, idx+addedCount);
12108       var arrangedContent = get(this, 'arrangedContent');
12109
12110       forEach(addedObjects, function(item) {
12111         this.insertItemSorted(item);
12112
12113         forEach(sortProperties, function(sortProperty) {
12114           Ember.addObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
12115         }, this);
12116       }, this);
12117     }
12118
12119     return this._super(array, idx, removedCount, addedCount);
12120   },
12121
12122   insertItemSorted: function(item) {
12123     var arrangedContent = get(this, 'arrangedContent');
12124     var length = get(arrangedContent, 'length');
12125
12126     var idx = this._binarySearch(item, 0, length);
12127     arrangedContent.insertAt(idx, item);
12128   },
12129
12130   contentItemSortPropertyDidChange: function(item) {
12131     var arrangedContent = get(this, 'arrangedContent'),
12132         oldIndex = arrangedContent.indexOf(item),
12133         leftItem = arrangedContent.objectAt(oldIndex - 1),
12134         rightItem = arrangedContent.objectAt(oldIndex + 1),
12135         leftResult = leftItem && this.orderBy(item, leftItem),
12136         rightResult = rightItem && this.orderBy(item, rightItem);
12137
12138     if (leftResult < 0 || rightResult > 0) {
12139       arrangedContent.removeObject(item);
12140       this.insertItemSorted(item);
12141     }
12142   },
12143
12144   _binarySearch: function(item, low, high) {
12145     var mid, midItem, res, arrangedContent;
12146
12147     if (low === high) {
12148       return low;
12149     }
12150
12151     arrangedContent = get(this, 'arrangedContent');
12152
12153     mid = low + Math.floor((high - low) / 2);
12154     midItem = arrangedContent.objectAt(mid);
12155
12156     res = this.orderBy(midItem, item);
12157
12158     if (res < 0) {
12159       return this._binarySearch(item, mid+1, high);
12160     } else if (res > 0) {
12161       return this._binarySearch(item, low, mid);
12162     }
12163
12164     return mid;
12165   }
12166 });
12167
12168 })();
12169
12170
12171
12172 (function() {
12173 /**
12174 @module ember
12175 @submodule ember-runtime
12176 */
12177
12178 var get = Ember.get, set = Ember.set, isGlobalPath = Ember.isGlobalPath,
12179     forEach = Ember.EnumerableUtils.forEach, replace = Ember.EnumerableUtils.replace;
12180
12181 /**
12182   `Ember.ArrayController` provides a way for you to publish a collection of
12183   objects so that you can easily bind to the collection from a Handlebars
12184   `#each` helper, an `Ember.CollectionView`, or other controllers.
12185
12186   The advantage of using an `ArrayController` is that you only have to set up
12187   your view bindings once; to change what's displayed, simply swap out the
12188   `content` property on the controller.
12189
12190   For example, imagine you wanted to display a list of items fetched via an XHR
12191   request. Create an `Ember.ArrayController` and set its `content` property:
12192
12193   ```javascript
12194   MyApp.listController = Ember.ArrayController.create();
12195
12196   $.get('people.json', function(data) {
12197     MyApp.listController.set('content', data);
12198   });
12199   ```
12200
12201   Then, create a view that binds to your new controller:
12202
12203   ```handlebars
12204   {{#each MyApp.listController}}
12205     {{firstName}} {{lastName}}
12206   {{/each}}
12207   ```
12208
12209   Although you are binding to the controller, the behavior of this controller
12210   is to pass through any methods or properties to the underlying array. This
12211   capability comes from `Ember.ArrayProxy`, which this class inherits from.
12212
12213   Sometimes you want to display computed properties within the body of an
12214   `#each` helper that depend on the underlying items in `content`, but are not
12215   present on those items.   To do this, set `itemController` to the name of a
12216   controller (probably an `ObjectController`) that will wrap each individual item.
12217
12218   For example:
12219
12220   ```handlebars
12221     {{#each post in controller}}
12222       <li>{{title}} ({{titleLength}} characters)</li>
12223     {{/each}}
12224   ```
12225
12226   ```javascript
12227   App.PostsController = Ember.ArrayController.extend({
12228     itemController: 'post'
12229   });
12230
12231   App.PostController = Ember.ObjectController.extend({
12232     // the `title` property will be proxied to the underlying post.
12233
12234     titleLength: function() {
12235       return this.get('title').length;
12236     }.property('title')
12237   });
12238   ```
12239
12240   In some cases it is helpful to return a different `itemController` depending
12241   on the particular item.  Subclasses can do this by overriding
12242   `lookupItemController`.
12243
12244   For example:
12245
12246   ```javascript
12247   App.MyArrayController = Ember.ArrayController.extend({
12248     lookupItemController: function( object ) {
12249       if (object.get('isSpecial')) {
12250         return "special"; // use App.SpecialController
12251       } else {
12252         return "regular"; // use App.RegularController
12253       }
12254     }
12255   });
12256   ```
12257
12258   @class ArrayController
12259   @namespace Ember
12260   @extends Ember.ArrayProxy
12261   @uses Ember.SortableMixin
12262   @uses Ember.ControllerMixin
12263 */
12264
12265 Ember.ArrayController = Ember.ArrayProxy.extend(Ember.ControllerMixin,
12266   Ember.SortableMixin, {
12267
12268   /**
12269     The controller used to wrap items, if any.
12270
12271     @property itemController
12272     @type String
12273     @default null
12274   */
12275   itemController: null,
12276
12277   /**
12278     Return the name of the controller to wrap items, or `null` if items should
12279     be returned directly.  The default implementation simply returns the
12280     `itemController` property, but subclasses can override this method to return
12281     different controllers for different objects.
12282
12283     For example:
12284
12285     ```javascript
12286     App.MyArrayController = Ember.ArrayController.extend({
12287       lookupItemController: function( object ) {
12288         if (object.get('isSpecial')) {
12289           return "special"; // use App.SpecialController
12290         } else {
12291           return "regular"; // use App.RegularController
12292         }
12293       }
12294     });
12295     ```
12296
12297     @method
12298     @type String
12299     @default null
12300   */
12301   lookupItemController: function(object) {
12302     return get(this, 'itemController');
12303   },
12304
12305   objectAtContent: function(idx) {
12306     var length = get(this, 'length'),
12307         object = get(this,'arrangedContent').objectAt(idx),
12308         controllerClass = this.lookupItemController(object);
12309
12310     if (controllerClass && idx < length) {
12311       return this.controllerAt(idx, object, controllerClass);
12312     } else {
12313       // When controllerClass is falsy we have not opted in to using item
12314       // controllers, so return the object directly.  However, when
12315       // controllerClass is defined but the index is out of range,  we want to
12316       // return the "out of range" value, whatever that might be.  Rather than
12317       // make assumptions (e.g. guessing `null` or `undefined`) we defer this to
12318       // `arrangedContent`.
12319       return object;
12320     }
12321   },
12322
12323   arrangedContentDidChange: function() {
12324     this._super();
12325     this._resetSubContainers();
12326   },
12327
12328   arrayContentDidChange: function(idx, removedCnt, addedCnt) {
12329     var subContainers = get(this, 'subContainers'),
12330         subContainersToRemove = subContainers.slice(idx, idx+removedCnt);
12331
12332     forEach(subContainersToRemove, function(subContainer) {
12333       if (subContainer) { subContainer.destroy(); }
12334     });
12335
12336     replace(subContainers, idx, removedCnt, new Array(addedCnt));
12337
12338     // The shadow array of subcontainers must be updated before we trigger
12339     // observers, otherwise observers will get the wrong subcontainer when
12340     // calling `objectAt`
12341     this._super(idx, removedCnt, addedCnt);
12342   },
12343
12344   init: function() {
12345     this._super();
12346     this._resetSubContainers();
12347   },
12348
12349   controllerAt: function(idx, object, controllerClass) {
12350     var container = get(this, 'container'),
12351         subContainers = get(this, 'subContainers'),
12352         subContainer = subContainers[idx],
12353         controller;
12354
12355     if (!subContainer) {
12356       subContainer = subContainers[idx] = container.child();
12357     }
12358
12359     controller = subContainer.lookup("controller:" + controllerClass);
12360     if (!controller) {
12361       throw new Error('Could not resolve itemController: "' + controllerClass + '"');
12362     }
12363
12364     controller.set('target', this);
12365     controller.set('content', object);
12366
12367     return controller;
12368   },
12369
12370   subContainers: null,
12371
12372   _resetSubContainers: function() {
12373     var subContainers = get(this, 'subContainers');
12374
12375     if (subContainers) {
12376       forEach(subContainers, function(subContainer) {
12377         if (subContainer) { subContainer.destroy(); }
12378       });
12379     }
12380
12381     this.set('subContainers', Ember.A());
12382   }
12383 });
12384
12385 })();
12386
12387
12388
12389 (function() {
12390 /**
12391 @module ember
12392 @submodule ember-runtime
12393 */
12394
12395 /**
12396   `Ember.ObjectController` is part of Ember's Controller layer. A single shared
12397   instance of each `Ember.ObjectController` subclass in your application's
12398   namespace will be created at application initialization and be stored on your
12399   application's `Ember.Router` instance.
12400
12401   `Ember.ObjectController` derives its functionality from its superclass
12402   `Ember.ObjectProxy` and the `Ember.ControllerMixin` mixin.
12403
12404   @class ObjectController
12405   @namespace Ember
12406   @extends Ember.ObjectProxy
12407   @uses Ember.ControllerMixin
12408 **/
12409 Ember.ObjectController = Ember.ObjectProxy.extend(Ember.ControllerMixin);
12410
12411 })();
12412
12413
12414
12415 (function() {
12416
12417 })();
12418
12419
12420
12421 (function() {
12422 /**
12423 Ember Runtime
12424
12425 @module ember
12426 @submodule ember-runtime
12427 @requires ember-metal
12428 */
12429
12430 })();
12431
12432 (function() {
12433 /**
12434 @module ember
12435 @submodule ember-views
12436 */
12437
12438 var jQuery = Ember.imports.jQuery;
12439 Ember.assert("Ember Views require jQuery 1.7 (>= 1.7.2), 1.8 or 1.9", jQuery && (jQuery().jquery.match(/^1\.(7(?!$)(?!\.[01])|8|9)(\.\d+)?(pre|rc\d?)?/) || Ember.ENV.FORCE_JQUERY));
12440
12441 /**
12442   Alias for jQuery
12443
12444   @method $
12445   @for Ember
12446 */
12447 Ember.$ = jQuery;
12448
12449 })();
12450
12451
12452
12453 (function() {
12454 /**
12455 @module ember
12456 @submodule ember-views
12457 */
12458
12459 // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#dndevents
12460 var dragEvents = Ember.String.w('dragstart drag dragenter dragleave dragover drop dragend');
12461
12462 // Copies the `dataTransfer` property from a browser event object onto the
12463 // jQuery event object for the specified events
12464 Ember.EnumerableUtils.forEach(dragEvents, function(eventName) {
12465   Ember.$.event.fixHooks[eventName] = { props: ['dataTransfer'] };
12466 });
12467
12468 })();
12469
12470
12471
12472 (function() {
12473 /**
12474 @module ember
12475 @submodule ember-views
12476 */
12477
12478 /*** BEGIN METAMORPH HELPERS ***/
12479
12480 // Internet Explorer prior to 9 does not allow setting innerHTML if the first element
12481 // is a "zero-scope" element. This problem can be worked around by making
12482 // the first node an invisible text node. We, like Modernizr, use &shy;
12483 var needsShy = (function(){
12484   var testEl = document.createElement('div');
12485   testEl.innerHTML = "<div></div>";
12486   testEl.firstChild.innerHTML = "<script></script>";
12487   return testEl.firstChild.innerHTML === '';
12488 })();
12489
12490 // IE 8 (and likely earlier) likes to move whitespace preceeding
12491 // a script tag to appear after it. This means that we can
12492 // accidentally remove whitespace when updating a morph.
12493 var movesWhitespace = (function() {
12494   var testEl = document.createElement('div');
12495   testEl.innerHTML = "Test: <script type='text/x-placeholder'></script>Value";
12496   return testEl.childNodes[0].nodeValue === 'Test:' &&
12497           testEl.childNodes[2].nodeValue === ' Value';
12498 })();
12499
12500 // Use this to find children by ID instead of using jQuery
12501 var findChildById = function(element, id) {
12502   if (element.getAttribute('id') === id) { return element; }
12503
12504   var len = element.childNodes.length, idx, node, found;
12505   for (idx=0; idx<len; idx++) {
12506     node = element.childNodes[idx];
12507     found = node.nodeType === 1 && findChildById(node, id);
12508     if (found) { return found; }
12509   }
12510 };
12511
12512 var setInnerHTMLWithoutFix = function(element, html) {
12513   if (needsShy) {
12514     html = '&shy;' + html;
12515   }
12516
12517   var matches = [];
12518   if (movesWhitespace) {
12519     // Right now we only check for script tags with ids with the
12520     // goal of targeting morphs.
12521     html = html.replace(/(\s+)(<script id='([^']+)')/g, function(match, spaces, tag, id) {
12522       matches.push([id, spaces]);
12523       return tag;
12524     });
12525   }
12526
12527   element.innerHTML = html;
12528
12529   // If we have to do any whitespace adjustments do them now
12530   if (matches.length > 0) {
12531     var len = matches.length, idx;
12532     for (idx=0; idx<len; idx++) {
12533       var script = findChildById(element, matches[idx][0]),
12534           node = document.createTextNode(matches[idx][1]);
12535       script.parentNode.insertBefore(node, script);
12536     }
12537   }
12538
12539   if (needsShy) {
12540     var shyElement = element.firstChild;
12541     while (shyElement.nodeType === 1 && !shyElement.nodeName) {
12542       shyElement = shyElement.firstChild;
12543     }
12544     if (shyElement.nodeType === 3 && shyElement.nodeValue.charAt(0) === "\u00AD") {
12545       shyElement.nodeValue = shyElement.nodeValue.slice(1);
12546     }
12547   }
12548 };
12549
12550 /*** END METAMORPH HELPERS */
12551
12552
12553 var innerHTMLTags = {};
12554 var canSetInnerHTML = function(tagName) {
12555   if (innerHTMLTags[tagName] !== undefined) {
12556     return innerHTMLTags[tagName];
12557   }
12558
12559   var canSet = true;
12560
12561   // IE 8 and earlier don't allow us to do innerHTML on select
12562   if (tagName.toLowerCase() === 'select') {
12563     var el = document.createElement('select');
12564     setInnerHTMLWithoutFix(el, '<option value="test">Test</option>');
12565     canSet = el.options.length === 1;
12566   }
12567
12568   innerHTMLTags[tagName] = canSet;
12569
12570   return canSet;
12571 };
12572
12573 var setInnerHTML = function(element, html) {
12574   var tagName = element.tagName;
12575
12576   if (canSetInnerHTML(tagName)) {
12577     setInnerHTMLWithoutFix(element, html);
12578   } else {
12579     Ember.assert("Can't set innerHTML on "+element.tagName+" in this browser", element.outerHTML);
12580
12581     var startTag = element.outerHTML.match(new RegExp("<"+tagName+"([^>]*)>", 'i'))[0],
12582         endTag = '</'+tagName+'>';
12583
12584     var wrapper = document.createElement('div');
12585     setInnerHTMLWithoutFix(wrapper, startTag + html + endTag);
12586     element = wrapper.firstChild;
12587     while (element.tagName !== tagName) {
12588       element = element.nextSibling;
12589     }
12590   }
12591
12592   return element;
12593 };
12594
12595 function isSimpleClick(event) {
12596   var modifier = event.shiftKey || event.metaKey || event.altKey || event.ctrlKey,
12597       secondaryClick = event.which > 1; // IE9 may return undefined
12598
12599   return !modifier && !secondaryClick;
12600 }
12601
12602 Ember.ViewUtils = {
12603   setInnerHTML: setInnerHTML,
12604   isSimpleClick: isSimpleClick
12605 };
12606
12607 })();
12608
12609
12610
12611 (function() {
12612 /**
12613 @module ember
12614 @submodule ember-views
12615 */
12616
12617 var get = Ember.get, set = Ember.set;
12618 var indexOf = Ember.ArrayPolyfills.indexOf;
12619
12620
12621
12622
12623
12624 var ClassSet = function() {
12625   this.seen = {};
12626   this.list = [];
12627 };
12628
12629 ClassSet.prototype = {
12630   add: function(string) {
12631     if (string in this.seen) { return; }
12632     this.seen[string] = true;
12633
12634     this.list.push(string);
12635   },
12636
12637   toDOM: function() {
12638     return this.list.join(" ");
12639   }
12640 };
12641
12642 /**
12643   `Ember.RenderBuffer` gathers information regarding the a view and generates the
12644   final representation. `Ember.RenderBuffer` will generate HTML which can be pushed
12645   to the DOM.
12646
12647   @class RenderBuffer
12648   @namespace Ember
12649   @constructor
12650 */
12651 Ember.RenderBuffer = function(tagName) {
12652   return new Ember._RenderBuffer(tagName);
12653 };
12654
12655 Ember._RenderBuffer = function(tagName) {
12656   this.tagNames = [tagName || null];
12657   this.buffer = [];
12658 };
12659
12660 Ember._RenderBuffer.prototype =
12661 /** @scope Ember.RenderBuffer.prototype */ {
12662
12663   // The root view's element
12664   _element: null,
12665
12666   /**
12667     @private
12668
12669     An internal set used to de-dupe class names when `addClass()` is
12670     used. After each call to `addClass()`, the `classes` property
12671     will be updated.
12672
12673     @property elementClasses
12674     @type Array
12675     @default []
12676   */
12677   elementClasses: null,
12678
12679   /**
12680     Array of class names which will be applied in the class attribute.
12681
12682     You can use `setClasses()` to set this property directly. If you
12683     use `addClass()`, it will be maintained for you.
12684
12685     @property classes
12686     @type Array
12687     @default []
12688   */
12689   classes: null,
12690
12691   /**
12692     The id in of the element, to be applied in the id attribute.
12693
12694     You should not set this property yourself, rather, you should use
12695     the `id()` method of `Ember.RenderBuffer`.
12696
12697     @property elementId
12698     @type String
12699     @default null
12700   */
12701   elementId: null,
12702
12703   /**
12704     A hash keyed on the name of the attribute and whose value will be
12705     applied to that attribute. For example, if you wanted to apply a
12706     `data-view="Foo.bar"` property to an element, you would set the
12707     elementAttributes hash to `{'data-view':'Foo.bar'}`.
12708
12709     You should not maintain this hash yourself, rather, you should use
12710     the `attr()` method of `Ember.RenderBuffer`.
12711
12712     @property elementAttributes
12713     @type Hash
12714     @default {}
12715   */
12716   elementAttributes: null,
12717
12718   /**
12719     The tagname of the element an instance of `Ember.RenderBuffer` represents.
12720
12721     Usually, this gets set as the first parameter to `Ember.RenderBuffer`. For
12722     example, if you wanted to create a `p` tag, then you would call
12723
12724     ```javascript
12725     Ember.RenderBuffer('p')
12726     ```
12727
12728     @property elementTag
12729     @type String
12730     @default null
12731   */
12732   elementTag: null,
12733
12734   /**
12735     A hash keyed on the name of the style attribute and whose value will
12736     be applied to that attribute. For example, if you wanted to apply a
12737     `background-color:black;` style to an element, you would set the
12738     elementStyle hash to `{'background-color':'black'}`.
12739
12740     You should not maintain this hash yourself, rather, you should use
12741     the `style()` method of `Ember.RenderBuffer`.
12742
12743     @property elementStyle
12744     @type Hash
12745     @default {}
12746   */
12747   elementStyle: null,
12748
12749   /**
12750     Nested `RenderBuffers` will set this to their parent `RenderBuffer`
12751     instance.
12752
12753     @property parentBuffer
12754     @type Ember._RenderBuffer
12755   */
12756   parentBuffer: null,
12757
12758   /**
12759     Adds a string of HTML to the `RenderBuffer`.
12760
12761     @method push
12762     @param {String} string HTML to push into the buffer
12763     @chainable
12764   */
12765   push: function(string) {
12766     this.buffer.push(string);
12767     return this;
12768   },
12769
12770   /**
12771     Adds a class to the buffer, which will be rendered to the class attribute.
12772
12773     @method addClass
12774     @param {String} className Class name to add to the buffer
12775     @chainable
12776   */
12777   addClass: function(className) {
12778     // lazily create elementClasses
12779     var elementClasses = this.elementClasses = (this.elementClasses || new ClassSet());
12780     this.elementClasses.add(className);
12781     this.classes = this.elementClasses.list;
12782
12783     return this;
12784   },
12785
12786   setClasses: function(classNames) {
12787     this.classes = classNames;
12788   },
12789
12790   /**
12791     Sets the elementID to be used for the element.
12792
12793     @method id
12794     @param {String} id
12795     @chainable
12796   */
12797   id: function(id) {
12798     this.elementId = id;
12799     return this;
12800   },
12801
12802   // duck type attribute functionality like jQuery so a render buffer
12803   // can be used like a jQuery object in attribute binding scenarios.
12804
12805   /**
12806     Adds an attribute which will be rendered to the element.
12807
12808     @method attr
12809     @param {String} name The name of the attribute
12810     @param {String} value The value to add to the attribute
12811     @chainable
12812     @return {Ember.RenderBuffer|String} this or the current attribute value
12813   */
12814   attr: function(name, value) {
12815     var attributes = this.elementAttributes = (this.elementAttributes || {});
12816
12817     if (arguments.length === 1) {
12818       return attributes[name];
12819     } else {
12820       attributes[name] = value;
12821     }
12822
12823     return this;
12824   },
12825
12826   /**
12827     Remove an attribute from the list of attributes to render.
12828
12829     @method removeAttr
12830     @param {String} name The name of the attribute
12831     @chainable
12832   */
12833   removeAttr: function(name) {
12834     var attributes = this.elementAttributes;
12835     if (attributes) { delete attributes[name]; }
12836
12837     return this;
12838   },
12839
12840   /**
12841     Adds a style to the style attribute which will be rendered to the element.
12842
12843     @method style
12844     @param {String} name Name of the style
12845     @param {String} value
12846     @chainable
12847   */
12848   style: function(name, value) {
12849     var style = this.elementStyle = (this.elementStyle || {});
12850
12851     this.elementStyle[name] = value;
12852     return this;
12853   },
12854
12855   begin: function(tagName) {
12856     this.tagNames.push(tagName || null);
12857     return this;
12858   },
12859
12860   pushOpeningTag: function() {
12861     var tagName = this.currentTagName();
12862     if (!tagName) { return; }
12863
12864     if (!this._element && this.buffer.length === 0) {
12865       this._element = this.generateElement();
12866       return;
12867     }
12868
12869     var buffer = this.buffer,
12870         id = this.elementId,
12871         classes = this.classes,
12872         attrs = this.elementAttributes,
12873         style = this.elementStyle,
12874         prop;
12875
12876     buffer.push('<' + tagName);
12877
12878     if (id) {
12879       buffer.push(' id="' + this._escapeAttribute(id) + '"');
12880       this.elementId = null;
12881     }
12882     if (classes) {
12883       buffer.push(' class="' + this._escapeAttribute(classes.join(' ')) + '"');
12884       this.classes = null;
12885     }
12886
12887     if (style) {
12888       buffer.push(' style="');
12889
12890       for (prop in style) {
12891         if (style.hasOwnProperty(prop)) {
12892           buffer.push(prop + ':' + this._escapeAttribute(style[prop]) + ';');
12893         }
12894       }
12895
12896       buffer.push('"');
12897
12898       this.elementStyle = null;
12899     }
12900
12901     if (attrs) {
12902       for (prop in attrs) {
12903         if (attrs.hasOwnProperty(prop)) {
12904           buffer.push(' ' + prop + '="' + this._escapeAttribute(attrs[prop]) + '"');
12905         }
12906       }
12907
12908       this.elementAttributes = null;
12909     }
12910
12911     buffer.push('>');
12912   },
12913
12914   pushClosingTag: function() {
12915     var tagName = this.tagNames.pop();
12916     if (tagName) { this.buffer.push('</' + tagName + '>'); }
12917   },
12918
12919   currentTagName: function() {
12920     return this.tagNames[this.tagNames.length-1];
12921   },
12922
12923   generateElement: function() {
12924     var tagName = this.tagNames.pop(), // pop since we don't need to close
12925         element = document.createElement(tagName),
12926         $element = Ember.$(element),
12927         id = this.elementId,
12928         classes = this.classes,
12929         attrs = this.elementAttributes,
12930         style = this.elementStyle,
12931         styleBuffer = '', prop;
12932
12933     if (id) {
12934       $element.attr('id', id);
12935       this.elementId = null;
12936     }
12937     if (classes) {
12938       $element.attr('class', classes.join(' '));
12939       this.classes = null;
12940     }
12941
12942     if (style) {
12943       for (prop in style) {
12944         if (style.hasOwnProperty(prop)) {
12945           styleBuffer += (prop + ':' + style[prop] + ';');
12946         }
12947       }
12948
12949       $element.attr('style', styleBuffer);
12950
12951       this.elementStyle = null;
12952     }
12953
12954     if (attrs) {
12955       for (prop in attrs) {
12956         if (attrs.hasOwnProperty(prop)) {
12957           $element.attr(prop, attrs[prop]);
12958         }
12959       }
12960
12961       this.elementAttributes = null;
12962     }
12963
12964     return element;
12965   },
12966
12967   /**
12968     @method element
12969     @return {DOMElement} The element corresponding to the generated HTML
12970       of this buffer
12971   */
12972   element: function() {
12973     var html = this.innerString();
12974
12975     if (html) {
12976       this._element = Ember.ViewUtils.setInnerHTML(this._element, html);
12977     }
12978
12979     return this._element;
12980   },
12981
12982   /**
12983     Generates the HTML content for this buffer.
12984
12985     @method string
12986     @return {String} The generated HTML
12987   */
12988   string: function() {
12989     if (this._element) {
12990       return this.element().outerHTML;
12991     } else {
12992       return this.innerString();
12993     }
12994   },
12995
12996   innerString: function() {
12997     return this.buffer.join('');
12998   },
12999
13000   _escapeAttribute: function(value) {
13001     // Stolen shamelessly from Handlebars
13002
13003     var escape = {
13004       "<": "&lt;",
13005       ">": "&gt;",
13006       '"': "&quot;",
13007       "'": "&#x27;",
13008       "`": "&#x60;"
13009     };
13010
13011     var badChars = /&(?!\w+;)|[<>"'`]/g;
13012     var possible = /[&<>"'`]/;
13013
13014     var escapeChar = function(chr) {
13015       return escape[chr] || "&amp;";
13016     };
13017
13018     var string = value.toString();
13019
13020     if(!possible.test(string)) { return string; }
13021     return string.replace(badChars, escapeChar);
13022   }
13023
13024 };
13025
13026 })();
13027
13028
13029
13030 (function() {
13031 /**
13032 @module ember
13033 @submodule ember-views
13034 */
13035
13036 var get = Ember.get, set = Ember.set, fmt = Ember.String.fmt;
13037
13038 /**
13039   `Ember.EventDispatcher` handles delegating browser events to their
13040   corresponding `Ember.Views.` For example, when you click on a view,
13041   `Ember.EventDispatcher` ensures that that view's `mouseDown` method gets
13042   called.
13043
13044   @class EventDispatcher
13045   @namespace Ember
13046   @private
13047   @extends Ember.Object
13048 */
13049 Ember.EventDispatcher = Ember.Object.extend(
13050 /** @scope Ember.EventDispatcher.prototype */{
13051
13052   /**
13053     @private
13054
13055     The root DOM element to which event listeners should be attached. Event
13056     listeners will be attached to the document unless this is overridden.
13057
13058     Can be specified as a DOMElement or a selector string.
13059
13060     The default body is a string since this may be evaluated before document.body
13061     exists in the DOM.
13062
13063     @property rootElement
13064     @type DOMElement
13065     @default 'body'
13066   */
13067   rootElement: 'body',
13068
13069   /**
13070     @private
13071
13072     Sets up event listeners for standard browser events.
13073
13074     This will be called after the browser sends a `DOMContentReady` event. By
13075     default, it will set up all of the listeners on the document body. If you
13076     would like to register the listeners on a different element, set the event
13077     dispatcher's `root` property.
13078
13079     @method setup
13080     @param addedEvents {Hash}
13081   */
13082   setup: function(addedEvents) {
13083     var event, events = {
13084       touchstart  : 'touchStart',
13085       touchmove   : 'touchMove',
13086       touchend    : 'touchEnd',
13087       touchcancel : 'touchCancel',
13088       keydown     : 'keyDown',
13089       keyup       : 'keyUp',
13090       keypress    : 'keyPress',
13091       mousedown   : 'mouseDown',
13092       mouseup     : 'mouseUp',
13093       contextmenu : 'contextMenu',
13094       click       : 'click',
13095       dblclick    : 'doubleClick',
13096       mousemove   : 'mouseMove',
13097       focusin     : 'focusIn',
13098       focusout    : 'focusOut',
13099       mouseenter  : 'mouseEnter',
13100       mouseleave  : 'mouseLeave',
13101       submit      : 'submit',
13102       input       : 'input',
13103       change      : 'change',
13104       dragstart   : 'dragStart',
13105       drag        : 'drag',
13106       dragenter   : 'dragEnter',
13107       dragleave   : 'dragLeave',
13108       dragover    : 'dragOver',
13109       drop        : 'drop',
13110       dragend     : 'dragEnd'
13111     };
13112
13113     Ember.$.extend(events, addedEvents || {});
13114
13115     var rootElement = Ember.$(get(this, 'rootElement'));
13116
13117     Ember.assert(fmt('You cannot use the same root element (%@) multiple times in an Ember.Application', [rootElement.selector || rootElement[0].tagName]), !rootElement.is('.ember-application'));
13118     Ember.assert('You cannot make a new Ember.Application using a root element that is a descendent of an existing Ember.Application', !rootElement.closest('.ember-application').length);
13119     Ember.assert('You cannot make a new Ember.Application using a root element that is an ancestor of an existing Ember.Application', !rootElement.find('.ember-application').length);
13120
13121     rootElement.addClass('ember-application');
13122
13123     Ember.assert('Unable to add "ember-application" class to rootElement. Make sure you set rootElement to the body or an element in the body.', rootElement.is('.ember-application'));
13124
13125     for (event in events) {
13126       if (events.hasOwnProperty(event)) {
13127         this.setupHandler(rootElement, event, events[event]);
13128       }
13129     }
13130   },
13131
13132   /**
13133     @private
13134
13135     Registers an event listener on the document. If the given event is
13136     triggered, the provided event handler will be triggered on the target view.
13137
13138     If the target view does not implement the event handler, or if the handler
13139     returns `false`, the parent view will be called. The event will continue to
13140     bubble to each successive parent view until it reaches the top.
13141
13142     For example, to have the `mouseDown` method called on the target view when
13143     a `mousedown` event is received from the browser, do the following:
13144
13145     ```javascript
13146     setupHandler('mousedown', 'mouseDown');
13147     ```
13148
13149     @method setupHandler
13150     @param {Element} rootElement
13151     @param {String} event the browser-originated event to listen to
13152     @param {String} eventName the name of the method to call on the view
13153   */
13154   setupHandler: function(rootElement, event, eventName) {
13155     var self = this;
13156
13157     rootElement.delegate('.ember-view', event + '.ember', function(evt, triggeringManager) {
13158       return Ember.handleErrors(function() {
13159         var view = Ember.View.views[this.id],
13160             result = true, manager = null;
13161
13162         manager = self._findNearestEventManager(view,eventName);
13163
13164         if (manager && manager !== triggeringManager) {
13165           result = self._dispatchEvent(manager, evt, eventName, view);
13166         } else if (view) {
13167           result = self._bubbleEvent(view,evt,eventName);
13168         } else {
13169           evt.stopPropagation();
13170         }
13171
13172         return result;
13173       }, this);
13174     });
13175
13176     rootElement.delegate('[data-ember-action]', event + '.ember', function(evt) {
13177       return Ember.handleErrors(function() {
13178         var actionId = Ember.$(evt.currentTarget).attr('data-ember-action'),
13179             action   = Ember.Handlebars.ActionHelper.registeredActions[actionId],
13180             handler  = action.handler;
13181
13182         if (action.eventName === eventName) {
13183           return handler(evt);
13184         }
13185       }, this);
13186     });
13187   },
13188
13189   _findNearestEventManager: function(view, eventName) {
13190     var manager = null;
13191
13192     while (view) {
13193       manager = get(view, 'eventManager');
13194       if (manager && manager[eventName]) { break; }
13195
13196       view = get(view, 'parentView');
13197     }
13198
13199     return manager;
13200   },
13201
13202   _dispatchEvent: function(object, evt, eventName, view) {
13203     var result = true;
13204
13205     var handler = object[eventName];
13206     if (Ember.typeOf(handler) === 'function') {
13207       result = handler.call(object, evt, view);
13208       // Do not preventDefault in eventManagers.
13209       evt.stopPropagation();
13210     }
13211     else {
13212       result = this._bubbleEvent(view, evt, eventName);
13213     }
13214
13215     return result;
13216   },
13217
13218   _bubbleEvent: function(view, evt, eventName) {
13219     return Ember.run(function() {
13220       return view.handleEvent(eventName, evt);
13221     });
13222   },
13223
13224   destroy: function() {
13225     var rootElement = get(this, 'rootElement');
13226     Ember.$(rootElement).undelegate('.ember').removeClass('ember-application');
13227     return this._super();
13228   }
13229 });
13230
13231 })();
13232
13233
13234
13235 (function() {
13236 /**
13237 @module ember
13238 @submodule ember-views
13239 */
13240
13241 // Add a new named queue for rendering views that happens
13242 // after bindings have synced, and a queue for scheduling actions
13243 // that that should occur after view rendering.
13244 var queues = Ember.run.queues;
13245 queues.splice(Ember.$.inArray('actions', queues)+1, 0, 'render', 'afterRender');
13246
13247 })();
13248
13249
13250
13251 (function() {
13252 /**
13253 @module ember
13254 @submodule ember-views
13255 */
13256
13257 var get = Ember.get, set = Ember.set;
13258
13259 // Original class declaration and documentation in runtime/lib/controllers/controller.js
13260 // NOTE: It may be possible with YUIDoc to combine docs in two locations
13261
13262 /**
13263 Additional methods for the ControllerMixin
13264
13265 @class ControllerMixin
13266 @namespace Ember
13267 */
13268 Ember.ControllerMixin.reopen({
13269   target: null,
13270   namespace: null,
13271   view: null,
13272   container: null
13273 });
13274
13275 })();
13276
13277
13278
13279 (function() {
13280
13281 })();
13282
13283
13284
13285 (function() {
13286 var states = {};
13287
13288 /**
13289 @module ember
13290 @submodule ember-views
13291 */
13292
13293 var get = Ember.get, set = Ember.set, addObserver = Ember.addObserver, removeObserver = Ember.removeObserver;
13294 var meta = Ember.meta, guidFor = Ember.guidFor, fmt = Ember.String.fmt;
13295 var a_slice = [].slice;
13296 var a_forEach = Ember.EnumerableUtils.forEach;
13297 var a_addObject = Ember.EnumerableUtils.addObject;
13298
13299 var childViewsProperty = Ember.computed(function() {
13300   var childViews = this._childViews;
13301
13302   var ret = Ember.A();
13303
13304   a_forEach(childViews, function(view) {
13305     if (view.isVirtual) {
13306       ret.pushObjects(get(view, 'childViews'));
13307     } else {
13308       ret.push(view);
13309     }
13310   });
13311
13312   return ret;
13313 });
13314
13315 Ember.warn("The VIEW_PRESERVES_CONTEXT flag has been removed and the functionality can no longer be disabled.", Ember.ENV.VIEW_PRESERVES_CONTEXT !== false);
13316
13317 /**
13318   Global hash of shared templates. This will automatically be populated
13319   by the build tools so that you can store your Handlebars templates in
13320   separate files that get loaded into JavaScript at buildtime.
13321
13322   @property TEMPLATES
13323   @for Ember
13324   @type Hash
13325 */
13326 Ember.TEMPLATES = {};
13327
13328 Ember.CoreView = Ember.Object.extend(Ember.Evented, {
13329   isView: true,
13330
13331   states: states,
13332
13333   init: function() {
13334     this._super();
13335
13336     // Register the view for event handling. This hash is used by
13337     // Ember.EventDispatcher to dispatch incoming events.
13338     if (!this.isVirtual) Ember.View.views[this.elementId] = this;
13339
13340     this.addBeforeObserver('elementId', function() {
13341       throw new Error("Changing a view's elementId after creation is not allowed");
13342     });
13343
13344     this.transitionTo('preRender');
13345   },
13346
13347   /**
13348     If the view is currently inserted into the DOM of a parent view, this
13349     property will point to the parent of the view.
13350
13351     @property parentView
13352     @type Ember.View
13353     @default null
13354   */
13355   parentView: Ember.computed(function() {
13356     var parent = this._parentView;
13357
13358     if (parent && parent.isVirtual) {
13359       return get(parent, 'parentView');
13360     } else {
13361       return parent;
13362     }
13363   }).property('_parentView'),
13364
13365   state: null,
13366
13367   _parentView: null,
13368
13369   // return the current view, not including virtual views
13370   concreteView: Ember.computed(function() {
13371     if (!this.isVirtual) { return this; }
13372     else { return get(this, 'parentView'); }
13373   }).property('parentView').volatile(),
13374
13375   instrumentName: 'core_view',
13376
13377   instrumentDetails: function(hash) {
13378     hash.object = this.toString();
13379   },
13380
13381   /**
13382     @private
13383
13384     Invoked by the view system when this view needs to produce an HTML
13385     representation. This method will create a new render buffer, if needed,
13386     then apply any default attributes, such as class names and visibility.
13387     Finally, the `render()` method is invoked, which is responsible for
13388     doing the bulk of the rendering.
13389
13390     You should not need to override this method; instead, implement the
13391     `template` property, or if you need more control, override the `render`
13392     method.
13393
13394     @method renderToBuffer
13395     @param {Ember.RenderBuffer} buffer the render buffer. If no buffer is
13396       passed, a default buffer, using the current view's `tagName`, will
13397       be used.
13398   */
13399   renderToBuffer: function(parentBuffer, bufferOperation) {
13400     var name = 'render.' + this.instrumentName,
13401         details = {};
13402
13403     this.instrumentDetails(details);
13404
13405     return Ember.instrument(name, details, function() {
13406       return this._renderToBuffer(parentBuffer, bufferOperation);
13407     }, this);
13408   },
13409
13410   _renderToBuffer: function(parentBuffer, bufferOperation) {
13411     Ember.run.sync();
13412
13413     // If this is the top-most view, start a new buffer. Otherwise,
13414     // create a new buffer relative to the original using the
13415     // provided buffer operation (for example, `insertAfter` will
13416     // insert a new buffer after the "parent buffer").
13417     var tagName = this.tagName;
13418
13419     if (tagName === null || tagName === undefined) {
13420       tagName = 'div';
13421     }
13422
13423     var buffer = this.buffer = parentBuffer && parentBuffer.begin(tagName) || Ember.RenderBuffer(tagName);
13424     this.transitionTo('inBuffer', false);
13425
13426     this.beforeRender(buffer);
13427     this.render(buffer);
13428     this.afterRender(buffer);
13429
13430     return buffer;
13431   },
13432
13433   /**
13434     @private
13435
13436     Override the default event firing from `Ember.Evented` to
13437     also call methods with the given name.
13438
13439     @method trigger
13440     @param name {String}
13441   */
13442   trigger: function(name) {
13443     this._super.apply(this, arguments);
13444     var method = this[name];
13445     if (method) {
13446       var args = [], i, l;
13447       for (i = 1, l = arguments.length; i < l; i++) {
13448         args.push(arguments[i]);
13449       }
13450       return method.apply(this, args);
13451     }
13452   },
13453
13454   has: function(name) {
13455     return Ember.typeOf(this[name]) === 'function' || this._super(name);
13456   },
13457
13458   willDestroy: function() {
13459     var parent = this._parentView;
13460
13461     // destroy the element -- this will avoid each child view destroying
13462     // the element over and over again...
13463     if (!this.removedFromDOM) { this.destroyElement(); }
13464
13465     // remove from parent if found. Don't call removeFromParent,
13466     // as removeFromParent will try to remove the element from
13467     // the DOM again.
13468     if (parent) { parent.removeChild(this); }
13469
13470     this.transitionTo('destroyed');
13471
13472     // next remove view from global hash
13473     if (!this.isVirtual) delete Ember.View.views[this.elementId];
13474   },
13475
13476   clearRenderedChildren: Ember.K,
13477   triggerRecursively: Ember.K,
13478   invokeRecursively: Ember.K,
13479   transitionTo: Ember.K,
13480   destroyElement: Ember.K
13481 });
13482
13483 /**
13484   `Ember.View` is the class in Ember responsible for encapsulating templates of
13485   HTML content, combining templates with data to render as sections of a page's
13486   DOM, and registering and responding to user-initiated events.
13487
13488   ## HTML Tag
13489
13490   The default HTML tag name used for a view's DOM representation is `div`. This
13491   can be customized by setting the `tagName` property. The following view
13492 class:
13493
13494   ```javascript
13495   ParagraphView = Ember.View.extend({
13496     tagName: 'em'
13497   });
13498   ```
13499
13500   Would result in instances with the following HTML:
13501
13502   ```html
13503   <em id="ember1" class="ember-view"></em>
13504   ```
13505
13506   ## HTML `class` Attribute
13507
13508   The HTML `class` attribute of a view's tag can be set by providing a
13509   `classNames` property that is set to an array of strings:
13510
13511   ```javascript
13512   MyView = Ember.View.extend({
13513     classNames: ['my-class', 'my-other-class']
13514   });
13515   ```
13516
13517   Will result in view instances with an HTML representation of:
13518
13519   ```html
13520   <div id="ember1" class="ember-view my-class my-other-class"></div>
13521   ```
13522
13523   `class` attribute values can also be set by providing a `classNameBindings`
13524   property set to an array of properties names for the view. The return value
13525   of these properties will be added as part of the value for the view's `class`
13526   attribute. These properties can be computed properties:
13527
13528   ```javascript
13529   MyView = Ember.View.extend({
13530     classNameBindings: ['propertyA', 'propertyB'],
13531     propertyA: 'from-a',
13532     propertyB: function(){
13533       if(someLogic){ return 'from-b'; }
13534     }.property()
13535   });
13536   ```
13537
13538   Will result in view instances with an HTML representation of:
13539
13540   ```html
13541   <div id="ember1" class="ember-view from-a from-b"></div>
13542   ```
13543
13544   If the value of a class name binding returns a boolean the property name
13545   itself will be used as the class name if the property is true. The class name
13546   will not be added if the value is `false` or `undefined`.
13547
13548   ```javascript
13549   MyView = Ember.View.extend({
13550     classNameBindings: ['hovered'],
13551     hovered: true
13552   });
13553   ```
13554
13555   Will result in view instances with an HTML representation of:
13556
13557   ```html
13558   <div id="ember1" class="ember-view hovered"></div>
13559   ```
13560
13561   When using boolean class name bindings you can supply a string value other
13562   than the property name for use as the `class` HTML attribute by appending the
13563   preferred value after a ":" character when defining the binding:
13564
13565   ```javascript
13566   MyView = Ember.View.extend({
13567     classNameBindings: ['awesome:so-very-cool'],
13568     awesome: true
13569   });
13570   ```
13571
13572   Will result in view instances with an HTML representation of:
13573
13574   ```html
13575   <div id="ember1" class="ember-view so-very-cool"></div>
13576   ```
13577
13578   Boolean value class name bindings whose property names are in a
13579   camelCase-style format will be converted to a dasherized format:
13580
13581   ```javascript
13582   MyView = Ember.View.extend({
13583     classNameBindings: ['isUrgent'],
13584     isUrgent: true
13585   });
13586   ```
13587
13588   Will result in view instances with an HTML representation of:
13589
13590   ```html
13591   <div id="ember1" class="ember-view is-urgent"></div>
13592   ```
13593
13594   Class name bindings can also refer to object values that are found by
13595   traversing a path relative to the view itself:
13596
13597   ```javascript
13598   MyView = Ember.View.extend({
13599     classNameBindings: ['messages.empty']
13600     messages: Ember.Object.create({
13601       empty: true
13602     })
13603   });
13604   ```
13605
13606   Will result in view instances with an HTML representation of:
13607
13608   ```html
13609   <div id="ember1" class="ember-view empty"></div>
13610   ```
13611
13612   If you want to add a class name for a property which evaluates to true and
13613   and a different class name if it evaluates to false, you can pass a binding
13614   like this:
13615
13616   ```javascript
13617   // Applies 'enabled' class when isEnabled is true and 'disabled' when isEnabled is false
13618   Ember.View.create({
13619     classNameBindings: ['isEnabled:enabled:disabled']
13620     isEnabled: true
13621   });
13622   ```
13623
13624   Will result in view instances with an HTML representation of:
13625
13626   ```html
13627   <div id="ember1" class="ember-view enabled"></div>
13628   ```
13629
13630   When isEnabled is `false`, the resulting HTML reprensentation looks like
13631   this:
13632
13633   ```html
13634   <div id="ember1" class="ember-view disabled"></div>
13635   ```
13636
13637   This syntax offers the convenience to add a class if a property is `false`:
13638
13639   ```javascript
13640   // Applies no class when isEnabled is true and class 'disabled' when isEnabled is false
13641   Ember.View.create({
13642     classNameBindings: ['isEnabled::disabled']
13643     isEnabled: true
13644   });
13645   ```
13646
13647   Will result in view instances with an HTML representation of:
13648
13649   ```html
13650   <div id="ember1" class="ember-view"></div>
13651   ```
13652
13653   When the `isEnabled` property on the view is set to `false`, it will result
13654   in view instances with an HTML representation of:
13655
13656   ```html
13657   <div id="ember1" class="ember-view disabled"></div>
13658   ```
13659
13660   Updates to the the value of a class name binding will result in automatic
13661   update of the  HTML `class` attribute in the view's rendered HTML
13662   representation. If the value becomes `false` or `undefined` the class name
13663   will be removed.
13664
13665   Both `classNames` and `classNameBindings` are concatenated properties. See
13666   `Ember.Object` documentation for more information about concatenated
13667   properties.
13668
13669   ## HTML Attributes
13670
13671   The HTML attribute section of a view's tag can be set by providing an
13672   `attributeBindings` property set to an array of property names on the view.
13673   The return value of these properties will be used as the value of the view's
13674   HTML associated attribute:
13675
13676   ```javascript
13677   AnchorView = Ember.View.extend({
13678     tagName: 'a',
13679     attributeBindings: ['href'],
13680     href: 'http://google.com'
13681   });
13682   ```
13683
13684   Will result in view instances with an HTML representation of:
13685
13686   ```html
13687   <a id="ember1" class="ember-view" href="http://google.com"></a>
13688   ```
13689
13690   If the return value of an `attributeBindings` monitored property is a boolean
13691   the property will follow HTML's pattern of repeating the attribute's name as
13692   its value:
13693
13694   ```javascript
13695   MyTextInput = Ember.View.extend({
13696     tagName: 'input',
13697     attributeBindings: ['disabled'],
13698     disabled: true
13699   });
13700   ```
13701
13702   Will result in view instances with an HTML representation of:
13703
13704   ```html
13705   <input id="ember1" class="ember-view" disabled="disabled" />
13706   ```
13707
13708   `attributeBindings` can refer to computed properties:
13709
13710   ```javascript
13711   MyTextInput = Ember.View.extend({
13712     tagName: 'input',
13713     attributeBindings: ['disabled'],
13714     disabled: function(){
13715       if (someLogic) {
13716         return true;
13717       } else {
13718         return false;
13719       }
13720     }.property()
13721   });
13722   ```
13723
13724   Updates to the the property of an attribute binding will result in automatic
13725   update of the  HTML attribute in the view's rendered HTML representation.
13726
13727   `attributeBindings` is a concatenated property. See `Ember.Object`
13728   documentation for more information about concatenated properties.
13729
13730   ## Templates
13731
13732   The HTML contents of a view's rendered representation are determined by its
13733   template. Templates can be any function that accepts an optional context
13734   parameter and returns a string of HTML that will be inserted within the
13735   view's tag. Most typically in Ember this function will be a compiled
13736   `Ember.Handlebars` template.
13737
13738   ```javascript
13739   AView = Ember.View.extend({
13740     template: Ember.Handlebars.compile('I am the template')
13741   });
13742   ```
13743
13744   Will result in view instances with an HTML representation of:
13745
13746   ```html
13747   <div id="ember1" class="ember-view">I am the template</div>
13748   ```
13749
13750   Within an Ember application is more common to define a Handlebars templates as
13751   part of a page:
13752
13753   ```html
13754   <script type='text/x-handlebars' data-template-name='some-template'>
13755     Hello
13756   </script>
13757   ```
13758
13759   And associate it by name using a view's `templateName` property:
13760
13761   ```javascript
13762   AView = Ember.View.extend({
13763     templateName: 'some-template'
13764   });
13765   ```
13766
13767   Using a value for `templateName` that does not have a Handlebars template
13768   with a matching `data-template-name` attribute will throw an error.
13769
13770   Assigning a value to both `template` and `templateName` properties will throw
13771   an error.
13772
13773   For views classes that may have a template later defined (e.g. as the block
13774   portion of a `{{view}}` Handlebars helper call in another template or in
13775   a subclass), you can provide a `defaultTemplate` property set to compiled
13776   template function. If a template is not later provided for the view instance
13777   the `defaultTemplate` value will be used:
13778
13779   ```javascript
13780   AView = Ember.View.extend({
13781     defaultTemplate: Ember.Handlebars.compile('I was the default'),
13782     template: null,
13783     templateName: null
13784   });
13785   ```
13786
13787   Will result in instances with an HTML representation of:
13788
13789   ```html
13790   <div id="ember1" class="ember-view">I was the default</div>
13791   ```
13792
13793   If a `template` or `templateName` is provided it will take precedence over
13794   `defaultTemplate`:
13795
13796   ```javascript
13797   AView = Ember.View.extend({
13798     defaultTemplate: Ember.Handlebars.compile('I was the default')
13799   });
13800
13801   aView = AView.create({
13802     template: Ember.Handlebars.compile('I was the template, not default')
13803   });
13804   ```
13805
13806   Will result in the following HTML representation when rendered:
13807
13808   ```html
13809   <div id="ember1" class="ember-view">I was the template, not default</div>
13810   ```
13811
13812   ## View Context
13813
13814   The default context of the compiled template is the view's controller:
13815
13816   ```javascript
13817   AView = Ember.View.extend({
13818     template: Ember.Handlebars.compile('Hello {{excitedGreeting}}')
13819   });
13820
13821   aController = Ember.Object.create({
13822     firstName: 'Barry',
13823     excitedGreeting: function(){
13824       return this.get("content.firstName") + "!!!"
13825     }.property()
13826   });
13827
13828   aView = AView.create({
13829     controller: aController,
13830   });
13831   ```
13832
13833   Will result in an HTML representation of:
13834
13835   ```html
13836   <div id="ember1" class="ember-view">Hello Barry!!!</div>
13837   ```
13838
13839   A context can also be explicitly supplied through the view's `context`
13840   property. If the view has neither `context` nor `controller` properties, the
13841   `parentView`'s context will be used.
13842
13843   ## Layouts
13844
13845   Views can have a secondary template that wraps their main template. Like
13846   primary templates, layouts can be any function that  accepts an optional
13847   context parameter and returns a string of HTML that will be inserted inside
13848   view's tag. Views whose HTML element is self closing (e.g. `<input />`)
13849   cannot have a layout and this property will be ignored.
13850
13851   Most typically in Ember a layout will be a compiled `Ember.Handlebars`
13852   template.
13853
13854   A view's layout can be set directly with the `layout` property or reference
13855   an existing Handlebars template by name with the `layoutName` property.
13856
13857   A template used as a layout must contain a single use of the Handlebars
13858   `{{yield}}` helper. The HTML contents of a view's rendered `template` will be
13859   inserted at this location:
13860
13861   ```javascript
13862   AViewWithLayout = Ember.View.extend({
13863     layout: Ember.Handlebars.compile("<div class='my-decorative-class'>{{yield}}</div>")
13864     template: Ember.Handlebars.compile("I got wrapped"),
13865   });
13866   ```
13867
13868   Will result in view instances with an HTML representation of:
13869
13870   ```html
13871   <div id="ember1" class="ember-view">
13872     <div class="my-decorative-class">
13873       I got wrapped
13874     </div>
13875   </div>
13876   ```
13877
13878   See `Handlebars.helpers.yield` for more information.
13879
13880   ## Responding to Browser Events
13881
13882   Views can respond to user-initiated events in one of three ways: method
13883   implementation, through an event manager, and through `{{action}}` helper use
13884   in their template or layout.
13885
13886   ### Method Implementation
13887
13888   Views can respond to user-initiated events by implementing a method that
13889   matches the event name. A `jQuery.Event` object will be passed as the
13890   argument to this method.
13891
13892   ```javascript
13893   AView = Ember.View.extend({
13894     click: function(event){
13895       // will be called when when an instance's
13896       // rendered element is clicked
13897     }
13898   });
13899   ```
13900
13901   ### Event Managers
13902
13903   Views can define an object as their `eventManager` property. This object can
13904   then implement methods that match the desired event names. Matching events
13905   that occur on the view's rendered HTML or the rendered HTML of any of its DOM
13906   descendants will trigger this method. A `jQuery.Event` object will be passed
13907   as the first argument to the method and an  `Ember.View` object as the
13908   second. The `Ember.View` will be the view whose rendered HTML was interacted
13909   with. This may be the view with the `eventManager` property or one of its
13910   descendent views.
13911
13912   ```javascript
13913   AView = Ember.View.extend({
13914     eventManager: Ember.Object.create({
13915       doubleClick: function(event, view){
13916         // will be called when when an instance's
13917         // rendered element or any rendering
13918         // of this views's descendent
13919         // elements is clicked
13920       }
13921     })
13922   });
13923   ```
13924
13925   An event defined for an event manager takes precedence over events of the
13926   same name handled through methods on the view.
13927
13928   ```javascript
13929   AView = Ember.View.extend({
13930     mouseEnter: function(event){
13931       // will never trigger.
13932     },
13933     eventManager: Ember.Object.create({
13934       mouseEnter: function(event, view){
13935         // takes presedence over AView#mouseEnter
13936       }
13937     })
13938   });
13939   ```
13940
13941   Similarly a view's event manager will take precedence for events of any views
13942   rendered as a descendent. A method name that matches an event name will not
13943   be called if the view instance was rendered inside the HTML representation of
13944   a view that has an `eventManager` property defined that handles events of the
13945   name. Events not handled by the event manager will still trigger method calls
13946   on the descendent.
13947
13948   ```javascript
13949   OuterView = Ember.View.extend({
13950     template: Ember.Handlebars.compile("outer {{#view InnerView}}inner{{/view}} outer"),
13951     eventManager: Ember.Object.create({
13952       mouseEnter: function(event, view){
13953         // view might be instance of either
13954         // OutsideView or InnerView depending on
13955         // where on the page the user interaction occured
13956       }
13957     })
13958   });
13959
13960   InnerView = Ember.View.extend({
13961     click: function(event){
13962       // will be called if rendered inside
13963       // an OuterView because OuterView's
13964       // eventManager doesn't handle click events
13965     },
13966     mouseEnter: function(event){
13967       // will never be called if rendered inside
13968       // an OuterView.
13969     }
13970   });
13971   ```
13972
13973   ### Handlebars `{{action}}` Helper
13974
13975   See `Handlebars.helpers.action`.
13976
13977   ### Event Names
13978
13979   Possible events names for any of the responding approaches described above
13980   are:
13981
13982   Touch events:
13983
13984   * `touchStart`
13985   * `touchMove`
13986   * `touchEnd`
13987   * `touchCancel`
13988
13989   Keyboard events
13990
13991   * `keyDown`
13992   * `keyUp`
13993   * `keyPress`
13994
13995   Mouse events
13996
13997   * `mouseDown`
13998   * `mouseUp`
13999   * `contextMenu`
14000   * `click`
14001   * `doubleClick`
14002   * `mouseMove`
14003   * `focusIn`
14004   * `focusOut`
14005   * `mouseEnter`
14006   * `mouseLeave`
14007
14008   Form events: 
14009
14010   * `submit`
14011   * `change`
14012   * `focusIn`
14013   * `focusOut`
14014   * `input`
14015
14016   HTML5 drag and drop events: 
14017
14018   * `dragStart`
14019   * `drag`
14020   * `dragEnter`
14021   * `dragLeave`
14022   * `drop`
14023   * `dragEnd`
14024
14025   ## Handlebars `{{view}}` Helper
14026
14027   Other `Ember.View` instances can be included as part of a view's template by
14028   using the `{{view}}` Handlebars helper. See `Handlebars.helpers.view` for
14029   additional information.
14030
14031   @class View
14032   @namespace Ember
14033   @extends Ember.Object
14034   @uses Ember.Evented
14035 */
14036 Ember.View = Ember.CoreView.extend(
14037 /** @scope Ember.View.prototype */ {
14038
14039   concatenatedProperties: ['classNames', 'classNameBindings', 'attributeBindings'],
14040
14041   /**
14042     @property isView
14043     @type Boolean
14044     @default true
14045     @final
14046   */
14047   isView: true,
14048
14049   // ..........................................................
14050   // TEMPLATE SUPPORT
14051   //
14052
14053   /**
14054     The name of the template to lookup if no template is provided.
14055
14056     `Ember.View` will look for a template with this name in this view's
14057     `templates` object. By default, this will be a global object
14058     shared in `Ember.TEMPLATES`.
14059
14060     @property templateName
14061     @type String
14062     @default null
14063   */
14064   templateName: null,
14065
14066   /**
14067     The name of the layout to lookup if no layout is provided.
14068
14069     `Ember.View` will look for a template with this name in this view's
14070     `templates` object. By default, this will be a global object
14071     shared in `Ember.TEMPLATES`.
14072
14073     @property layoutName
14074     @type String
14075     @default null
14076   */
14077   layoutName: null,
14078
14079   /**
14080     The hash in which to look for `templateName`.
14081
14082     @property templates
14083     @type Ember.Object
14084     @default Ember.TEMPLATES
14085   */
14086   templates: Ember.TEMPLATES,
14087
14088   /**
14089     The template used to render the view. This should be a function that
14090     accepts an optional context parameter and returns a string of HTML that
14091     will be inserted into the DOM relative to its parent view.
14092
14093     In general, you should set the `templateName` property instead of setting
14094     the template yourself.
14095
14096     @property template
14097     @type Function
14098   */
14099   template: Ember.computed(function(key, value) {
14100     if (value !== undefined) { return value; }
14101
14102     var templateName = get(this, 'templateName'),
14103         template = this.templateForName(templateName, 'template');
14104
14105     return template || get(this, 'defaultTemplate');
14106   }).property('templateName'),
14107
14108   container: Ember.computed(function() {
14109     var parentView = get(this, '_parentView');
14110
14111     if (parentView) { return get(parentView, 'container'); }
14112
14113     return Ember.Container && Ember.Container.defaultContainer;
14114   }),
14115
14116   /**
14117     The controller managing this view. If this property is set, it will be
14118     made available for use by the template.
14119
14120     @property controller
14121     @type Object
14122   */
14123   controller: Ember.computed(function(key) {
14124     var parentView = get(this, '_parentView');
14125     return parentView ? get(parentView, 'controller') : null;
14126   }).property('_parentView'),
14127
14128   /**
14129     A view may contain a layout. A layout is a regular template but
14130     supersedes the `template` property during rendering. It is the
14131     responsibility of the layout template to retrieve the `template`
14132     property from the view (or alternatively, call `Handlebars.helpers.yield`,
14133     `{{yield}}`) to render it in the correct location.
14134
14135     This is useful for a view that has a shared wrapper, but which delegates
14136     the rendering of the contents of the wrapper to the `template` property
14137     on a subclass.
14138
14139     @property layout
14140     @type Function
14141   */
14142   layout: Ember.computed(function(key) {
14143     var layoutName = get(this, 'layoutName'),
14144         layout = this.templateForName(layoutName, 'layout');
14145
14146     return layout || get(this, 'defaultLayout');
14147   }).property('layoutName'),
14148
14149   templateForName: function(name, type) {
14150     if (!name) { return; }
14151
14152     Ember.assert("templateNames are not allowed to contain periods: "+name, name.indexOf('.') === -1);
14153
14154     var container = get(this, 'container');
14155
14156     if (container) {
14157       return container.lookup('template:' + name);
14158     }
14159   },
14160
14161   /**
14162     The object from which templates should access properties.
14163
14164     This object will be passed to the template function each time the render
14165     method is called, but it is up to the individual function to decide what
14166     to do with it.
14167
14168     By default, this will be the view's controller.
14169
14170     @property context
14171     @type Object
14172   */
14173   context: Ember.computed(function(key, value) {
14174     if (arguments.length === 2) {
14175       set(this, '_context', value);
14176       return value;
14177     } else {
14178       return get(this, '_context');
14179     }
14180   }).volatile(),
14181
14182   /**
14183     @private
14184
14185     Private copy of the view's template context. This can be set directly
14186     by Handlebars without triggering the observer that causes the view
14187     to be re-rendered.
14188
14189     The context of a view is looked up as follows:
14190
14191     1. Supplied context (usually by Handlebars)
14192     2. Specified controller
14193     3. `parentView`'s context (for a child of a ContainerView)
14194
14195     The code in Handlebars that overrides the `_context` property first
14196     checks to see whether the view has a specified controller. This is
14197     something of a hack and should be revisited.
14198
14199     @property _context
14200   */
14201   _context: Ember.computed(function(key) {
14202     var parentView, controller;
14203
14204     if (controller = get(this, 'controller')) {
14205       return controller;
14206     }
14207
14208     parentView = this._parentView;
14209     if (parentView) {
14210       return get(parentView, '_context');
14211     }
14212
14213     return null;
14214   }),
14215
14216   /**
14217     @private
14218
14219     If a value that affects template rendering changes, the view should be
14220     re-rendered to reflect the new value.
14221
14222     @method _displayPropertyDidChange
14223   */
14224   _contextDidChange: Ember.observer(function() {
14225     this.rerender();
14226   }, 'context'),
14227
14228   /**
14229     If `false`, the view will appear hidden in DOM.
14230
14231     @property isVisible
14232     @type Boolean
14233     @default null
14234   */
14235   isVisible: true,
14236
14237   /**
14238     @private
14239
14240     Array of child views. You should never edit this array directly.
14241     Instead, use `appendChild` and `removeFromParent`.
14242
14243     @property childViews
14244     @type Array
14245     @default []
14246   */
14247   childViews: childViewsProperty,
14248
14249   _childViews: [],
14250
14251   // When it's a virtual view, we need to notify the parent that their
14252   // childViews will change.
14253   _childViewsWillChange: Ember.beforeObserver(function() {
14254     if (this.isVirtual) {
14255       var parentView = get(this, 'parentView');
14256       if (parentView) { Ember.propertyWillChange(parentView, 'childViews'); }
14257     }
14258   }, 'childViews'),
14259
14260   // When it's a virtual view, we need to notify the parent that their
14261   // childViews did change.
14262   _childViewsDidChange: Ember.observer(function() {
14263     if (this.isVirtual) {
14264       var parentView = get(this, 'parentView');
14265       if (parentView) { Ember.propertyDidChange(parentView, 'childViews'); }
14266     }
14267   }, 'childViews'),
14268
14269   /**
14270     Return the nearest ancestor that is an instance of the provided
14271     class.
14272
14273     @property nearestInstanceOf
14274     @param {Class} klass Subclass of Ember.View (or Ember.View itself)
14275     @return Ember.View
14276     @deprecated
14277   */
14278   nearestInstanceOf: function(klass) {
14279     Ember.deprecate("nearestInstanceOf is deprecated and will be removed from future releases. Use nearestOfType.");
14280     var view = get(this, 'parentView');
14281
14282     while (view) {
14283       if(view instanceof klass) { return view; }
14284       view = get(view, 'parentView');
14285     }
14286   },
14287
14288   /**
14289     Return the nearest ancestor that is an instance of the provided
14290     class or mixin.
14291
14292     @property nearestOfType
14293     @param {Class,Mixin} klass Subclass of Ember.View (or Ember.View itself),
14294            or an instance of Ember.Mixin.
14295     @return Ember.View
14296   */
14297   nearestOfType: function(klass) {
14298     var view = get(this, 'parentView'),
14299         isOfType = klass instanceof Ember.Mixin ?
14300                    function(view) { return klass.detect(view); } :
14301                    function(view) { return klass.detect(view.constructor); };
14302
14303     while (view) {
14304       if( isOfType(view) ) { return view; }
14305       view = get(view, 'parentView');
14306     }
14307   },
14308
14309   /**
14310     Return the nearest ancestor that has a given property.
14311
14312     @property nearestWithProperty
14313     @param {String} property A property name
14314     @return Ember.View
14315   */
14316   nearestWithProperty: function(property) {
14317     var view = get(this, 'parentView');
14318
14319     while (view) {
14320       if (property in view) { return view; }
14321       view = get(view, 'parentView');
14322     }
14323   },
14324
14325   /**
14326     Return the nearest ancestor whose parent is an instance of
14327     `klass`.
14328
14329     @property nearestChildOf
14330     @param {Class} klass Subclass of Ember.View (or Ember.View itself)
14331     @return Ember.View
14332   */
14333   nearestChildOf: function(klass) {
14334     var view = get(this, 'parentView');
14335
14336     while (view) {
14337       if(get(view, 'parentView') instanceof klass) { return view; }
14338       view = get(view, 'parentView');
14339     }
14340   },
14341
14342   /**
14343     @private
14344
14345     When the parent view changes, recursively invalidate `controller`
14346
14347     @method _parentViewDidChange
14348   */
14349   _parentViewDidChange: Ember.observer(function() {
14350     if (this.isDestroying) { return; }
14351
14352     if (get(this, 'parentView.controller') && !get(this, 'controller')) {
14353       this.notifyPropertyChange('controller');
14354     }
14355   }, '_parentView'),
14356
14357   _controllerDidChange: Ember.observer(function() {
14358     if (this.isDestroying) { return; }
14359
14360     this.rerender();
14361
14362     this.forEachChildView(function(view) {
14363       view.propertyDidChange('controller');
14364     });
14365   }, 'controller'),
14366
14367   cloneKeywords: function() {
14368     var templateData = get(this, 'templateData');
14369
14370     var keywords = templateData ? Ember.copy(templateData.keywords) : {};
14371     set(keywords, 'view', get(this, 'concreteView'));
14372     set(keywords, '_view', this);
14373     set(keywords, 'controller', get(this, 'controller'));
14374
14375     return keywords;
14376   },
14377
14378   /**
14379     Called on your view when it should push strings of HTML into a
14380     `Ember.RenderBuffer`. Most users will want to override the `template`
14381     or `templateName` properties instead of this method.
14382
14383     By default, `Ember.View` will look for a function in the `template`
14384     property and invoke it with the value of `context`. The value of
14385     `context` will be the view's controller unless you override it.
14386
14387     @method render
14388     @param {Ember.RenderBuffer} buffer The render buffer
14389   */
14390   render: function(buffer) {
14391     // If this view has a layout, it is the responsibility of the
14392     // the layout to render the view's template. Otherwise, render the template
14393     // directly.
14394     var template = get(this, 'layout') || get(this, 'template');
14395
14396     if (template) {
14397       var context = get(this, 'context');
14398       var keywords = this.cloneKeywords();
14399       var output;
14400
14401       var data = {
14402         view: this,
14403         buffer: buffer,
14404         isRenderData: true,
14405         keywords: keywords,
14406         insideGroup: get(this, 'templateData.insideGroup')
14407       };
14408
14409       // Invoke the template with the provided template context, which
14410       // is the view's controller by default. A hash of data is also passed that provides
14411       // the template with access to the view and render buffer.
14412
14413       Ember.assert('template must be a function. Did you mean to call Ember.Handlebars.compile("...") or specify templateName instead?', typeof template === 'function');
14414       // The template should write directly to the render buffer instead
14415       // of returning a string.
14416       output = template(context, { data: data });
14417
14418       // If the template returned a string instead of writing to the buffer,
14419       // push the string onto the buffer.
14420       if (output !== undefined) { buffer.push(output); }
14421     }
14422   },
14423
14424   /**
14425     Renders the view again. This will work regardless of whether the
14426     view is already in the DOM or not. If the view is in the DOM, the
14427     rendering process will be deferred to give bindings a chance
14428     to synchronize.
14429
14430     If children were added during the rendering process using `appendChild`,
14431     `rerender` will remove them, because they will be added again
14432     if needed by the next `render`.
14433
14434     In general, if the display of your view changes, you should modify
14435     the DOM element directly instead of manually calling `rerender`, which can
14436     be slow.
14437
14438     @method rerender
14439   */
14440   rerender: function() {
14441     return this.currentState.rerender(this);
14442   },
14443
14444   clearRenderedChildren: function() {
14445     var lengthBefore = this.lengthBeforeRender,
14446         lengthAfter  = this.lengthAfterRender;
14447
14448     // If there were child views created during the last call to render(),
14449     // remove them under the assumption that they will be re-created when
14450     // we re-render.
14451
14452     // VIEW-TODO: Unit test this path.
14453     var childViews = this._childViews;
14454     for (var i=lengthAfter-1; i>=lengthBefore; i--) {
14455       if (childViews[i]) { childViews[i].destroy(); }
14456     }
14457   },
14458
14459   /**
14460     @private
14461
14462     Iterates over the view's `classNameBindings` array, inserts the value
14463     of the specified property into the `classNames` array, then creates an
14464     observer to update the view's element if the bound property ever changes
14465     in the future.
14466
14467     @method _applyClassNameBindings
14468   */
14469   _applyClassNameBindings: function(classBindings) {
14470     var classNames = this.classNames,
14471     elem, newClass, dasherizedClass;
14472
14473     // Loop through all of the configured bindings. These will be either
14474     // property names ('isUrgent') or property paths relative to the view
14475     // ('content.isUrgent')
14476     a_forEach(classBindings, function(binding) {
14477
14478       // Variable in which the old class value is saved. The observer function
14479       // closes over this variable, so it knows which string to remove when
14480       // the property changes.
14481       var oldClass;
14482       // Extract just the property name from bindings like 'foo:bar'
14483       var parsedPath = Ember.View._parsePropertyPath(binding);
14484
14485       // Set up an observer on the context. If the property changes, toggle the
14486       // class name.
14487       var observer = function() {
14488         // Get the current value of the property
14489         newClass = this._classStringForProperty(binding);
14490         elem = this.$();
14491
14492         // If we had previously added a class to the element, remove it.
14493         if (oldClass) {
14494           elem.removeClass(oldClass);
14495           // Also remove from classNames so that if the view gets rerendered,
14496           // the class doesn't get added back to the DOM.
14497           classNames.removeObject(oldClass);
14498         }
14499
14500         // If necessary, add a new class. Make sure we keep track of it so
14501         // it can be removed in the future.
14502         if (newClass) {
14503           elem.addClass(newClass);
14504           oldClass = newClass;
14505         } else {
14506           oldClass = null;
14507         }
14508       };
14509
14510       // Get the class name for the property at its current value
14511       dasherizedClass = this._classStringForProperty(binding);
14512
14513       if (dasherizedClass) {
14514         // Ensure that it gets into the classNames array
14515         // so it is displayed when we render.
14516         a_addObject(classNames, dasherizedClass);
14517
14518         // Save a reference to the class name so we can remove it
14519         // if the observer fires. Remember that this variable has
14520         // been closed over by the observer.
14521         oldClass = dasherizedClass;
14522       }
14523
14524       addObserver(this, parsedPath.path, observer);
14525
14526       this.one('willClearRender', function() {
14527         removeObserver(this, parsedPath.path, observer);
14528       });
14529     }, this);
14530   },
14531
14532   /**
14533     @private
14534
14535     Iterates through the view's attribute bindings, sets up observers for each,
14536     then applies the current value of the attributes to the passed render buffer.
14537
14538     @method _applyAttributeBindings
14539     @param {Ember.RenderBuffer} buffer
14540   */
14541   _applyAttributeBindings: function(buffer, attributeBindings) {
14542     var attributeValue, elem, type;
14543
14544     a_forEach(attributeBindings, function(binding) {
14545       var split = binding.split(':'),
14546           property = split[0],
14547           attributeName = split[1] || property;
14548
14549       // Create an observer to add/remove/change the attribute if the
14550       // JavaScript property changes.
14551       var observer = function() {
14552         elem = this.$();
14553         if (!elem) { return; }
14554
14555         attributeValue = get(this, property);
14556
14557         Ember.View.applyAttributeBindings(elem, attributeName, attributeValue);
14558       };
14559
14560       addObserver(this, property, observer);
14561
14562       this.one('willClearRender', function() {
14563         removeObserver(this, property, observer);
14564       });
14565
14566       // Determine the current value and add it to the render buffer
14567       // if necessary.
14568       attributeValue = get(this, property);
14569       Ember.View.applyAttributeBindings(buffer, attributeName, attributeValue);
14570     }, this);
14571   },
14572
14573   /**
14574     @private
14575
14576     Given a property name, returns a dasherized version of that
14577     property name if the property evaluates to a non-falsy value.
14578
14579     For example, if the view has property `isUrgent` that evaluates to true,
14580     passing `isUrgent` to this method will return `"is-urgent"`.
14581
14582     @method _classStringForProperty
14583     @param property
14584   */
14585   _classStringForProperty: function(property) {
14586     var parsedPath = Ember.View._parsePropertyPath(property);
14587     var path = parsedPath.path;
14588
14589     var val = get(this, path);
14590     if (val === undefined && Ember.isGlobalPath(path)) {
14591       val = get(Ember.lookup, path);
14592     }
14593
14594     return Ember.View._classStringForValue(path, val, parsedPath.className, parsedPath.falsyClassName);
14595   },
14596
14597   // ..........................................................
14598   // ELEMENT SUPPORT
14599   //
14600
14601   /**
14602     Returns the current DOM element for the view.
14603
14604     @property element
14605     @type DOMElement
14606   */
14607   element: Ember.computed(function(key, value) {
14608     if (value !== undefined) {
14609       return this.currentState.setElement(this, value);
14610     } else {
14611       return this.currentState.getElement(this);
14612     }
14613   }).property('_parentView'),
14614
14615   /**
14616     Returns a jQuery object for this view's element. If you pass in a selector
14617     string, this method will return a jQuery object, using the current element
14618     as its buffer.
14619
14620     For example, calling `view.$('li')` will return a jQuery object containing
14621     all of the `li` elements inside the DOM element of this view.
14622
14623     @property $
14624     @param {String} [selector] a jQuery-compatible selector string
14625     @return {jQuery} the CoreQuery object for the DOM node
14626   */
14627   $: function(sel) {
14628     return this.currentState.$(this, sel);
14629   },
14630
14631   mutateChildViews: function(callback) {
14632     var childViews = this._childViews,
14633         idx = childViews.length,
14634         view;
14635
14636     while(--idx >= 0) {
14637       view = childViews[idx];
14638       callback.call(this, view, idx);
14639     }
14640
14641     return this;
14642   },
14643
14644   forEachChildView: function(callback) {
14645     var childViews = this._childViews;
14646
14647     if (!childViews) { return this; }
14648
14649     var len = childViews.length,
14650         view, idx;
14651
14652     for(idx = 0; idx < len; idx++) {
14653       view = childViews[idx];
14654       callback.call(this, view);
14655     }
14656
14657     return this;
14658   },
14659
14660   /**
14661     Appends the view's element to the specified parent element.
14662
14663     If the view does not have an HTML representation yet, `createElement()`
14664     will be called automatically.
14665
14666     Note that this method just schedules the view to be appended; the DOM
14667     element will not be appended to the given element until all bindings have
14668     finished synchronizing.
14669
14670     This is not typically a function that you will need to call directly when
14671     building your application. You might consider using `Ember.ContainerView`
14672     instead. If you do need to use `appendTo`, be sure that the target element
14673     you are providing is associated with an `Ember.Application` and does not
14674     have an ancestor element that is associated with an Ember view.
14675
14676     @method appendTo
14677     @param {String|DOMElement|jQuery} A selector, element, HTML string, or jQuery object
14678     @return {Ember.View} receiver
14679   */
14680   appendTo: function(target) {
14681     // Schedule the DOM element to be created and appended to the given
14682     // element after bindings have synchronized.
14683     this._insertElementLater(function() {
14684       Ember.assert("You cannot append to an existing Ember.View. Consider using Ember.ContainerView instead.", !Ember.$(target).is('.ember-view') && !Ember.$(target).parents().is('.ember-view'));
14685       this.$().appendTo(target);
14686     });
14687
14688     return this;
14689   },
14690
14691   /**
14692     Replaces the content of the specified parent element with this view's
14693     element. If the view does not have an HTML representation yet,
14694     `createElement()` will be called automatically.
14695
14696     Note that this method just schedules the view to be appended; the DOM
14697     element will not be appended to the given element until all bindings have
14698     finished synchronizing
14699
14700     @method replaceIn
14701     @param {String|DOMElement|jQuery} A selector, element, HTML string, or jQuery object
14702     @return {Ember.View} received
14703   */
14704   replaceIn: function(target) {
14705     Ember.assert("You cannot replace an existing Ember.View. Consider using Ember.ContainerView instead.", !Ember.$(target).is('.ember-view') && !Ember.$(target).parents().is('.ember-view'));
14706
14707     this._insertElementLater(function() {
14708       Ember.$(target).empty();
14709       this.$().appendTo(target);
14710     });
14711
14712     return this;
14713   },
14714
14715   /**
14716     @private
14717
14718     Schedules a DOM operation to occur during the next render phase. This
14719     ensures that all bindings have finished synchronizing before the view is
14720     rendered.
14721
14722     To use, pass a function that performs a DOM operation.
14723
14724     Before your function is called, this view and all child views will receive
14725     the `willInsertElement` event. After your function is invoked, this view
14726     and all of its child views will receive the `didInsertElement` event.
14727
14728     ```javascript
14729     view._insertElementLater(function() {
14730       this.createElement();
14731       this.$().appendTo('body');
14732     });
14733     ```
14734
14735     @method _insertElementLater
14736     @param {Function} fn the function that inserts the element into the DOM
14737   */
14738   _insertElementLater: function(fn) {
14739     this._scheduledInsert = Ember.run.scheduleOnce('render', this, '_insertElement', fn);
14740   },
14741
14742   _insertElement: function (fn) {
14743     this._scheduledInsert = null;
14744     this.currentState.insertElement(this, fn);
14745   },
14746
14747   /**
14748     Appends the view's element to the document body. If the view does
14749     not have an HTML representation yet, `createElement()` will be called
14750     automatically.
14751
14752     Note that this method just schedules the view to be appended; the DOM
14753     element will not be appended to the document body until all bindings have
14754     finished synchronizing.
14755
14756     @method append
14757     @return {Ember.View} receiver
14758   */
14759   append: function() {
14760     return this.appendTo(document.body);
14761   },
14762
14763   /**
14764     Removes the view's element from the element to which it is attached.
14765
14766     @method remove
14767     @return {Ember.View} receiver
14768   */
14769   remove: function() {
14770     // What we should really do here is wait until the end of the run loop
14771     // to determine if the element has been re-appended to a different
14772     // element.
14773     // In the interim, we will just re-render if that happens. It is more
14774     // important than elements get garbage collected.
14775     this.destroyElement();
14776     this.invokeRecursively(function(view) {
14777       if (view.clearRenderedChildren) { view.clearRenderedChildren(); }
14778     });
14779   },
14780
14781   elementId: null,
14782
14783   /**
14784     Attempts to discover the element in the parent element. The default
14785     implementation looks for an element with an ID of `elementId` (or the
14786     view's guid if `elementId` is null). You can override this method to
14787     provide your own form of lookup. For example, if you want to discover your
14788     element using a CSS class name instead of an ID.
14789
14790     @method findElementInParentElement
14791     @param {DOMElement} parentElement The parent's DOM element
14792     @return {DOMElement} The discovered element
14793   */
14794   findElementInParentElement: function(parentElem) {
14795     var id = "#" + this.elementId;
14796     return Ember.$(id)[0] || Ember.$(id, parentElem)[0];
14797   },
14798
14799   /**
14800     Creates a DOM representation of the view and all of its
14801     child views by recursively calling the `render()` method.
14802
14803     After the element has been created, `didInsertElement` will
14804     be called on this view and all of its child views.
14805
14806     @method createElement
14807     @return {Ember.View} receiver
14808   */
14809   createElement: function() {
14810     if (get(this, 'element')) { return this; }
14811
14812     var buffer = this.renderToBuffer();
14813     set(this, 'element', buffer.element());
14814
14815     return this;
14816   },
14817
14818   /**
14819     Called when a view is going to insert an element into the DOM.
14820
14821     @event willInsertElement
14822   */
14823   willInsertElement: Ember.K,
14824
14825   /**
14826     Called when the element of the view has been inserted into the DOM.
14827     Override this function to do any set up that requires an element in the
14828     document body.
14829
14830     @event didInsertElement
14831   */
14832   didInsertElement: Ember.K,
14833
14834   /**
14835     Called when the view is about to rerender, but before anything has
14836     been torn down. This is a good opportunity to tear down any manual
14837     observers you have installed based on the DOM state
14838
14839     @event willClearRender
14840   */
14841   willClearRender: Ember.K,
14842
14843   /**
14844     @private
14845
14846     Run this callback on the current view and recursively on child views.
14847
14848     @method invokeRecursively
14849     @param fn {Function}
14850   */
14851   invokeRecursively: function(fn) {
14852     var childViews = [this], currentViews, view;
14853
14854     while (childViews.length) {
14855       currentViews = childViews.slice();
14856       childViews = [];
14857
14858       for (var i=0, l=currentViews.length; i<l; i++) {
14859         view = currentViews[i];
14860         fn.call(view, view);
14861         if (view._childViews) {
14862           childViews.push.apply(childViews, view._childViews);
14863         }
14864       }
14865     }
14866   },
14867
14868   triggerRecursively: function(eventName) {
14869     var childViews = [this], currentViews, view;
14870
14871     while (childViews.length) {
14872       currentViews = childViews.slice();
14873       childViews = [];
14874
14875       for (var i=0, l=currentViews.length; i<l; i++) {
14876         view = currentViews[i];
14877         if (view.trigger) { view.trigger(eventName); }
14878         if (view._childViews) {
14879           childViews.push.apply(childViews, view._childViews);
14880         }
14881       }
14882     }
14883   },
14884
14885   /**
14886     Destroys any existing element along with the element for any child views
14887     as well. If the view does not currently have a element, then this method
14888     will do nothing.
14889
14890     If you implement `willDestroyElement()` on your view, then this method will
14891     be invoked on your view before your element is destroyed to give you a
14892     chance to clean up any event handlers, etc.
14893
14894     If you write a `willDestroyElement()` handler, you can assume that your
14895     `didInsertElement()` handler was called earlier for the same element.
14896
14897     Normally you will not call or override this method yourself, but you may
14898     want to implement the above callbacks when it is run.
14899
14900     @method destroyElement
14901     @return {Ember.View} receiver
14902   */
14903   destroyElement: function() {
14904     return this.currentState.destroyElement(this);
14905   },
14906
14907   /**
14908     Called when the element of the view is going to be destroyed. Override
14909     this function to do any teardown that requires an element, like removing
14910     event listeners.
14911
14912     @event willDestroyElement
14913   */
14914   willDestroyElement: function() {},
14915
14916   /**
14917     @private
14918
14919     Triggers the `willDestroyElement` event (which invokes the
14920     `willDestroyElement()` method if it exists) on this view and all child
14921     views.
14922
14923     Before triggering `willDestroyElement`, it first triggers the
14924     `willClearRender` event recursively.
14925
14926     @method _notifyWillDestroyElement
14927   */
14928   _notifyWillDestroyElement: function() {
14929     this.triggerRecursively('willClearRender');
14930     this.triggerRecursively('willDestroyElement');
14931   },
14932
14933   _elementWillChange: Ember.beforeObserver(function() {
14934     this.forEachChildView(function(view) {
14935       Ember.propertyWillChange(view, 'element');
14936     });
14937   }, 'element'),
14938
14939   /**
14940     @private
14941
14942     If this view's element changes, we need to invalidate the caches of our
14943     child views so that we do not retain references to DOM elements that are
14944     no longer needed.
14945
14946     @method _elementDidChange
14947   */
14948   _elementDidChange: Ember.observer(function() {
14949     this.forEachChildView(function(view) {
14950       Ember.propertyDidChange(view, 'element');
14951     });
14952   }, 'element'),
14953
14954   /**
14955     Called when the parentView property has changed.
14956
14957     @event parentViewDidChange
14958   */
14959   parentViewDidChange: Ember.K,
14960
14961   instrumentName: 'view',
14962
14963   instrumentDetails: function(hash) {
14964     hash.template = get(this, 'templateName');
14965     this._super(hash);
14966   },
14967
14968   _renderToBuffer: function(parentBuffer, bufferOperation) {
14969     this.lengthBeforeRender = this._childViews.length;
14970     var buffer = this._super(parentBuffer, bufferOperation);
14971     this.lengthAfterRender = this._childViews.length;
14972
14973     return buffer;
14974   },
14975
14976   renderToBufferIfNeeded: function () {
14977     return this.currentState.renderToBufferIfNeeded(this, this);
14978   },
14979
14980   beforeRender: function(buffer) {
14981     this.applyAttributesToBuffer(buffer);
14982     buffer.pushOpeningTag();
14983   },
14984
14985   afterRender: function(buffer) {
14986     buffer.pushClosingTag();
14987   },
14988
14989   applyAttributesToBuffer: function(buffer) {
14990     // Creates observers for all registered class name and attribute bindings,
14991     // then adds them to the element.
14992     var classNameBindings = get(this, 'classNameBindings');
14993     if (classNameBindings.length) {
14994       this._applyClassNameBindings(classNameBindings);
14995     }
14996
14997     // Pass the render buffer so the method can apply attributes directly.
14998     // This isn't needed for class name bindings because they use the
14999     // existing classNames infrastructure.
15000     var attributeBindings = get(this, 'attributeBindings');
15001     if (attributeBindings.length) {
15002       this._applyAttributeBindings(buffer, attributeBindings);
15003     }
15004
15005     buffer.setClasses(this.classNames);
15006     buffer.id(this.elementId);
15007
15008     var role = get(this, 'ariaRole');
15009     if (role) {
15010       buffer.attr('role', role);
15011     }
15012
15013     if (get(this, 'isVisible') === false) {
15014       buffer.style('display', 'none');
15015     }
15016   },
15017
15018   // ..........................................................
15019   // STANDARD RENDER PROPERTIES
15020   //
15021
15022   /**
15023     Tag name for the view's outer element. The tag name is only used when an
15024     element is first created. If you change the `tagName` for an element, you
15025     must destroy and recreate the view element.
15026
15027     By default, the render buffer will use a `<div>` tag for views.
15028
15029     @property tagName
15030     @type String
15031     @default null
15032   */
15033
15034   // We leave this null by default so we can tell the difference between
15035   // the default case and a user-specified tag.
15036   tagName: null,
15037
15038   /**
15039     The WAI-ARIA role of the control represented by this view. For example, a
15040     button may have a role of type 'button', or a pane may have a role of
15041     type 'alertdialog'. This property is used by assistive software to help
15042     visually challenged users navigate rich web applications.
15043
15044     The full list of valid WAI-ARIA roles is available at:
15045     http://www.w3.org/TR/wai-aria/roles#roles_categorization
15046
15047     @property ariaRole
15048     @type String
15049     @default null
15050   */
15051   ariaRole: null,
15052
15053   /**
15054     Standard CSS class names to apply to the view's outer element. This
15055     property automatically inherits any class names defined by the view's
15056     superclasses as well.
15057
15058     @property classNames
15059     @type Array
15060     @default ['ember-view']
15061   */
15062   classNames: ['ember-view'],
15063
15064   /**
15065     A list of properties of the view to apply as class names. If the property
15066     is a string value, the value of that string will be applied as a class
15067     name.
15068
15069     ```javascript
15070     // Applies the 'high' class to the view element
15071     Ember.View.create({
15072       classNameBindings: ['priority']
15073       priority: 'high'
15074     });
15075     ```
15076
15077     If the value of the property is a Boolean, the name of that property is
15078     added as a dasherized class name.
15079
15080     ```javascript
15081     // Applies the 'is-urgent' class to the view element
15082     Ember.View.create({
15083       classNameBindings: ['isUrgent']
15084       isUrgent: true
15085     });
15086     ```
15087
15088     If you would prefer to use a custom value instead of the dasherized
15089     property name, you can pass a binding like this:
15090
15091     ```javascript
15092     // Applies the 'urgent' class to the view element
15093     Ember.View.create({
15094       classNameBindings: ['isUrgent:urgent']
15095       isUrgent: true
15096     });
15097     ```
15098
15099     This list of properties is inherited from the view's superclasses as well.
15100
15101     @property classNameBindings
15102     @type Array
15103     @default []
15104   */
15105   classNameBindings: [],
15106
15107   /**
15108     A list of properties of the view to apply as attributes. If the property is
15109     a string value, the value of that string will be applied as the attribute.
15110
15111     ```javascript
15112     // Applies the type attribute to the element
15113     // with the value "button", like <div type="button">
15114     Ember.View.create({
15115       attributeBindings: ['type'],
15116       type: 'button'
15117     });
15118     ```
15119
15120     If the value of the property is a Boolean, the name of that property is
15121     added as an attribute.
15122
15123     ```javascript
15124     // Renders something like <div enabled="enabled">
15125     Ember.View.create({
15126       attributeBindings: ['enabled'],
15127       enabled: true
15128     });
15129     ```
15130
15131     @property attributeBindings
15132   */
15133   attributeBindings: [],
15134
15135   // .......................................................
15136   // CORE DISPLAY METHODS
15137   //
15138
15139   /**
15140     @private
15141
15142     Setup a view, but do not finish waking it up.
15143     - configure `childViews`
15144     - register the view with the global views hash, which is used for event
15145       dispatch
15146
15147     @method init
15148   */
15149   init: function() {
15150     this.elementId = this.elementId || guidFor(this);
15151
15152     this._super();
15153
15154     // setup child views. be sure to clone the child views array first
15155     this._childViews = this._childViews.slice();
15156
15157     Ember.assert("Only arrays are allowed for 'classNameBindings'", Ember.typeOf(this.classNameBindings) === 'array');
15158     this.classNameBindings = Ember.A(this.classNameBindings.slice());
15159
15160     Ember.assert("Only arrays are allowed for 'classNames'", Ember.typeOf(this.classNames) === 'array');
15161     this.classNames = Ember.A(this.classNames.slice());
15162
15163     var viewController = get(this, 'viewController');
15164     if (viewController) {
15165       viewController = get(viewController);
15166       if (viewController) {
15167         set(viewController, 'view', this);
15168       }
15169     }
15170   },
15171
15172   appendChild: function(view, options) {
15173     return this.currentState.appendChild(this, view, options);
15174   },
15175
15176   /**
15177     Removes the child view from the parent view.
15178
15179     @method removeChild
15180     @param {Ember.View} view
15181     @return {Ember.View} receiver
15182   */
15183   removeChild: function(view) {
15184     // If we're destroying, the entire subtree will be
15185     // freed, and the DOM will be handled separately,
15186     // so no need to mess with childViews.
15187     if (this.isDestroying) { return; }
15188
15189     // update parent node
15190     set(view, '_parentView', null);
15191
15192     // remove view from childViews array.
15193     var childViews = this._childViews;
15194
15195     Ember.EnumerableUtils.removeObject(childViews, view);
15196
15197     this.propertyDidChange('childViews'); // HUH?! what happened to will change?
15198
15199     return this;
15200   },
15201
15202   /**
15203     Removes all children from the `parentView`.
15204
15205     @method removeAllChildren
15206     @return {Ember.View} receiver
15207   */
15208   removeAllChildren: function() {
15209     return this.mutateChildViews(function(view) {
15210       this.removeChild(view);
15211     });
15212   },
15213
15214   destroyAllChildren: function() {
15215     return this.mutateChildViews(function(view) {
15216       view.destroy();
15217     });
15218   },
15219
15220   /**
15221     Removes the view from its `parentView`, if one is found. Otherwise
15222     does nothing.
15223
15224     @method removeFromParent
15225     @return {Ember.View} receiver
15226   */
15227   removeFromParent: function() {
15228     var parent = this._parentView;
15229
15230     // Remove DOM element from parent
15231     this.remove();
15232
15233     if (parent) { parent.removeChild(this); }
15234     return this;
15235   },
15236
15237   /**
15238     You must call `destroy` on a view to destroy the view (and all of its
15239     child views). This will remove the view from any parent node, then make
15240     sure that the DOM element managed by the view can be released by the
15241     memory manager.
15242
15243     @method willDestroy
15244   */
15245   willDestroy: function() {
15246     // calling this._super() will nuke computed properties and observers,
15247     // so collect any information we need before calling super.
15248     var childViews = this._childViews,
15249         parent = this._parentView,
15250         childLen;
15251
15252     // destroy the element -- this will avoid each child view destroying
15253     // the element over and over again...
15254     if (!this.removedFromDOM) { this.destroyElement(); }
15255
15256     // remove from non-virtual parent view if viewName was specified
15257     if (this.viewName) {
15258       var nonVirtualParentView = get(this, 'parentView');
15259       if (nonVirtualParentView) {
15260         set(nonVirtualParentView, this.viewName, null);
15261       }
15262     }
15263
15264     // remove from parent if found. Don't call removeFromParent,
15265     // as removeFromParent will try to remove the element from
15266     // the DOM again.
15267     if (parent) { parent.removeChild(this); }
15268
15269     this.transitionTo('destroyed');
15270
15271     childLen = childViews.length;
15272     for (var i=childLen-1; i>=0; i--) {
15273       childViews[i].removedFromDOM = true;
15274       childViews[i].destroy();
15275     }
15276
15277     // next remove view from global hash
15278     if (!this.isVirtual) delete Ember.View.views[get(this, 'elementId')];
15279   },
15280
15281   /**
15282     Instantiates a view to be added to the childViews array during view
15283     initialization. You generally will not call this method directly unless
15284     you are overriding `createChildViews()`. Note that this method will
15285     automatically configure the correct settings on the new view instance to
15286     act as a child of the parent.
15287
15288     @method createChildView
15289     @param {Class} viewClass
15290     @param {Hash} [attrs] Attributes to add
15291     @return {Ember.View} new instance
15292   */
15293   createChildView: function(view, attrs) {
15294     if (view.isView && view._parentView === this) { return view; }
15295
15296     if (Ember.CoreView.detect(view)) {
15297       attrs = attrs || {};
15298       attrs._parentView = this;
15299       attrs.templateData = attrs.templateData || get(this, 'templateData');
15300
15301       view = view.create(attrs);
15302
15303       // don't set the property on a virtual view, as they are invisible to
15304       // consumers of the view API
15305       if (view.viewName) { set(get(this, 'concreteView'), view.viewName, view); }
15306     } else {
15307       Ember.assert('You must pass instance or subclass of View', view.isView);
15308
15309       if (attrs) {
15310         view.setProperties(attrs);
15311       }
15312
15313       if (!get(view, 'templateData')) {
15314         set(view, 'templateData', get(this, 'templateData'));
15315       }
15316
15317       set(view, '_parentView', this);
15318     }
15319
15320     return view;
15321   },
15322
15323   becameVisible: Ember.K,
15324   becameHidden: Ember.K,
15325
15326   /**
15327     @private
15328
15329     When the view's `isVisible` property changes, toggle the visibility
15330     element of the actual DOM element.
15331
15332     @method _isVisibleDidChange
15333   */
15334   _isVisibleDidChange: Ember.observer(function() {
15335     var $el = this.$();
15336     if (!$el) { return; }
15337
15338     var isVisible = get(this, 'isVisible');
15339
15340     $el.toggle(isVisible);
15341
15342     if (this._isAncestorHidden()) { return; }
15343
15344     if (isVisible) {
15345       this._notifyBecameVisible();
15346     } else {
15347       this._notifyBecameHidden();
15348     }
15349   }, 'isVisible'),
15350
15351   _notifyBecameVisible: function() {
15352     this.trigger('becameVisible');
15353
15354     this.forEachChildView(function(view) {
15355       var isVisible = get(view, 'isVisible');
15356
15357       if (isVisible || isVisible === null) {
15358         view._notifyBecameVisible();
15359       }
15360     });
15361   },
15362
15363   _notifyBecameHidden: function() {
15364     this.trigger('becameHidden');
15365     this.forEachChildView(function(view) {
15366       var isVisible = get(view, 'isVisible');
15367
15368       if (isVisible || isVisible === null) {
15369         view._notifyBecameHidden();
15370       }
15371     });
15372   },
15373
15374   _isAncestorHidden: function() {
15375     var parent = get(this, 'parentView');
15376
15377     while (parent) {
15378       if (get(parent, 'isVisible') === false) { return true; }
15379
15380       parent = get(parent, 'parentView');
15381     }
15382
15383     return false;
15384   },
15385
15386   clearBuffer: function() {
15387     this.invokeRecursively(function(view) {
15388       view.buffer = null;
15389     });
15390   },
15391
15392   transitionTo: function(state, children) {
15393     this.currentState = this.states[state];
15394     this.state = state;
15395
15396     if (children !== false) {
15397       this.forEachChildView(function(view) {
15398         view.transitionTo(state);
15399       });
15400     }
15401   },
15402
15403   // .......................................................
15404   // EVENT HANDLING
15405   //
15406
15407   /**
15408     @private
15409
15410     Handle events from `Ember.EventDispatcher`
15411
15412     @method handleEvent
15413     @param eventName {String}
15414     @param evt {Event}
15415   */
15416   handleEvent: function(eventName, evt) {
15417     return this.currentState.handleEvent(this, eventName, evt);
15418   }
15419
15420 });
15421
15422 /*
15423   Describe how the specified actions should behave in the various
15424   states that a view can exist in. Possible states:
15425
15426   * preRender: when a view is first instantiated, and after its
15427     element was destroyed, it is in the preRender state
15428   * inBuffer: once a view has been rendered, but before it has
15429     been inserted into the DOM, it is in the inBuffer state
15430   * inDOM: once a view has been inserted into the DOM it is in
15431     the inDOM state. A view spends the vast majority of its
15432     existence in this state.
15433   * destroyed: once a view has been destroyed (using the destroy
15434     method), it is in this state. No further actions can be invoked
15435     on a destroyed view.
15436 */
15437
15438   // in the destroyed state, everything is illegal
15439
15440   // before rendering has begun, all legal manipulations are noops.
15441
15442   // inside the buffer, legal manipulations are done on the buffer
15443
15444   // once the view has been inserted into the DOM, legal manipulations
15445   // are done on the DOM element.
15446
15447 var DOMManager = {
15448   prepend: function(view, html) {
15449     view.$().prepend(html);
15450   },
15451
15452   after: function(view, html) {
15453     view.$().after(html);
15454   },
15455
15456   html: function(view, html) {
15457     view.$().html(html);
15458   },
15459
15460   replace: function(view) {
15461     var element = get(view, 'element');
15462
15463     set(view, 'element', null);
15464
15465     view._insertElementLater(function() {
15466       Ember.$(element).replaceWith(get(view, 'element'));
15467     });
15468   },
15469
15470   remove: function(view) {
15471     view.$().remove();
15472   },
15473
15474   empty: function(view) {
15475     view.$().empty();
15476   }
15477 };
15478
15479 Ember.View.reopen({
15480   domManager: DOMManager
15481 });
15482
15483 Ember.View.reopenClass({
15484
15485   /**
15486     @private
15487
15488     Parse a path and return an object which holds the parsed properties.
15489
15490     For example a path like "content.isEnabled:enabled:disabled" wil return the
15491     following object:
15492
15493     ```javascript
15494     {
15495       path: "content.isEnabled",
15496       className: "enabled",
15497       falsyClassName: "disabled",
15498       classNames: ":enabled:disabled"
15499     }
15500     ```
15501
15502     @method _parsePropertyPath
15503     @static
15504   */
15505   _parsePropertyPath: function(path) {
15506     var split = path.split(':'),
15507         propertyPath = split[0],
15508         classNames = "",
15509         className,
15510         falsyClassName;
15511
15512     // check if the property is defined as prop:class or prop:trueClass:falseClass
15513     if (split.length > 1) {
15514       className = split[1];
15515       if (split.length === 3) { falsyClassName = split[2]; }
15516
15517       classNames = ':' + className;
15518       if (falsyClassName) { classNames += ":" + falsyClassName; }
15519     }
15520
15521     return {
15522       path: propertyPath,
15523       classNames: classNames,
15524       className: (className === '') ? undefined : className,
15525       falsyClassName: falsyClassName
15526     };
15527   },
15528
15529   /**
15530     @private
15531
15532     Get the class name for a given value, based on the path, optional
15533     `className` and optional `falsyClassName`.
15534
15535     - if a `className` or `falsyClassName` has been specified:
15536       - if the value is truthy and `className` has been specified, 
15537         `className` is returned
15538       - if the value is falsy and `falsyClassName` has been specified, 
15539         `falsyClassName` is returned
15540       - otherwise `null` is returned
15541     - if the value is `true`, the dasherized last part of the supplied path 
15542       is returned
15543     - if the value is not `false`, `undefined` or `null`, the `value` 
15544       is returned
15545     - if none of the above rules apply, `null` is returned
15546
15547     @method _classStringForValue
15548     @param path
15549     @param val
15550     @param className
15551     @param falsyClassName
15552     @static
15553   */
15554   _classStringForValue: function(path, val, className, falsyClassName) {
15555     // When using the colon syntax, evaluate the truthiness or falsiness
15556     // of the value to determine which className to return
15557     if (className || falsyClassName) {
15558       if (className && !!val) {
15559         return className;
15560
15561       } else if (falsyClassName && !val) {
15562         return falsyClassName;
15563
15564       } else {
15565         return null;
15566       }
15567
15568     // If value is a Boolean and true, return the dasherized property
15569     // name.
15570     } else if (val === true) {
15571       // Normalize property path to be suitable for use
15572       // as a class name. For exaple, content.foo.barBaz
15573       // becomes bar-baz.
15574       var parts = path.split('.');
15575       return Ember.String.dasherize(parts[parts.length-1]);
15576
15577     // If the value is not false, undefined, or null, return the current
15578     // value of the property.
15579     } else if (val !== false && val !== undefined && val !== null) {
15580       return val;
15581
15582     // Nothing to display. Return null so that the old class is removed
15583     // but no new class is added.
15584     } else {
15585       return null;
15586     }
15587   }
15588 });
15589
15590 /**
15591   Global views hash
15592
15593   @property views
15594   @static
15595   @type Hash
15596 */
15597 Ember.View.views = {};
15598
15599 // If someone overrides the child views computed property when
15600 // defining their class, we want to be able to process the user's
15601 // supplied childViews and then restore the original computed property
15602 // at view initialization time. This happens in Ember.ContainerView's init
15603 // method.
15604 Ember.View.childViewsProperty = childViewsProperty;
15605
15606 Ember.View.applyAttributeBindings = function(elem, name, value) {
15607   var type = Ember.typeOf(value);
15608   var currentValue = elem.attr(name);
15609
15610   // if this changes, also change the logic in ember-handlebars/lib/helpers/binding.js
15611   if ((type === 'string' || (type === 'number' && !isNaN(value))) && value !== currentValue) {
15612     elem.attr(name, value);
15613   } else if (value && type === 'boolean') {
15614     elem.attr(name, name);
15615   } else if (!value) {
15616     elem.removeAttr(name);
15617   }
15618 };
15619
15620 Ember.View.states = states;
15621
15622 })();
15623
15624
15625
15626 (function() {
15627 /**
15628 @module ember
15629 @submodule ember-views
15630 */
15631
15632 var get = Ember.get, set = Ember.set;
15633
15634 Ember.View.states._default = {
15635   // appendChild is only legal while rendering the buffer.
15636   appendChild: function() {
15637     throw "You can't use appendChild outside of the rendering process";
15638   },
15639
15640   $: function() {
15641     return undefined;
15642   },
15643
15644   getElement: function() {
15645     return null;
15646   },
15647
15648   // Handle events from `Ember.EventDispatcher`
15649   handleEvent: function() {
15650     return true; // continue event propagation
15651   },
15652
15653   destroyElement: function(view) {
15654     set(view, 'element', null);
15655     if (view._scheduledInsert) {
15656       Ember.run.cancel(view._scheduledInsert);
15657       view._scheduledInsert = null;
15658     }
15659     return view;
15660   },
15661
15662   renderToBufferIfNeeded: function () {
15663     return false;
15664   },
15665
15666   rerender: Ember.K
15667 };
15668
15669 })();
15670
15671
15672
15673 (function() {
15674 /**
15675 @module ember
15676 @submodule ember-views
15677 */
15678
15679 var preRender = Ember.View.states.preRender = Ember.create(Ember.View.states._default);
15680
15681 Ember.merge(preRender, {
15682   // a view leaves the preRender state once its element has been
15683   // created (createElement).
15684   insertElement: function(view, fn) {
15685     view.createElement();
15686     view.triggerRecursively('willInsertElement');
15687     // after createElement, the view will be in the hasElement state.
15688     fn.call(view);
15689     view.transitionTo('inDOM');
15690     view.triggerRecursively('didInsertElement');
15691   },
15692
15693   renderToBufferIfNeeded: function(view) {
15694     return view.renderToBuffer();
15695   },
15696
15697   empty: Ember.K,
15698
15699   setElement: function(view, value) {
15700     if (value !== null) {
15701       view.transitionTo('hasElement');
15702     }
15703     return value;
15704   }
15705 });
15706
15707 })();
15708
15709
15710
15711 (function() {
15712 /**
15713 @module ember
15714 @submodule ember-views
15715 */
15716
15717 var get = Ember.get, set = Ember.set, meta = Ember.meta;
15718
15719 var inBuffer = Ember.View.states.inBuffer = Ember.create(Ember.View.states._default);
15720
15721 Ember.merge(inBuffer, {
15722   $: function(view, sel) {
15723     // if we don't have an element yet, someone calling this.$() is
15724     // trying to update an element that isn't in the DOM. Instead,
15725     // rerender the view to allow the render method to reflect the
15726     // changes.
15727     view.rerender();
15728     return Ember.$();
15729   },
15730
15731   // when a view is rendered in a buffer, rerendering it simply
15732   // replaces the existing buffer with a new one
15733   rerender: function(view) {
15734     throw new Ember.Error("Something you did caused a view to re-render after it rendered but before it was inserted into the DOM.");
15735   },
15736
15737   // when a view is rendered in a buffer, appending a child
15738   // view will render that view and append the resulting
15739   // buffer into its buffer.
15740   appendChild: function(view, childView, options) {
15741     var buffer = view.buffer;
15742
15743     childView = view.createChildView(childView, options);
15744     view._childViews.push(childView);
15745
15746     childView.renderToBuffer(buffer);
15747
15748     view.propertyDidChange('childViews');
15749
15750     return childView;
15751   },
15752
15753   // when a view is rendered in a buffer, destroying the
15754   // element will simply destroy the buffer and put the
15755   // state back into the preRender state.
15756   destroyElement: function(view) {
15757     view.clearBuffer();
15758     view._notifyWillDestroyElement();
15759     view.transitionTo('preRender');
15760
15761     return view;
15762   },
15763
15764   empty: function() {
15765     Ember.assert("Emptying a view in the inBuffer state is not allowed and should not happen under normal circumstances. Most likely there is a bug in your application. This may be due to excessive property change notifications.");
15766   },
15767
15768   renderToBufferIfNeeded: function (view) {
15769     return view.buffer;
15770   },
15771
15772   // It should be impossible for a rendered view to be scheduled for
15773   // insertion.
15774   insertElement: function() {
15775     throw "You can't insert an element that has already been rendered";
15776   },
15777
15778   setElement: function(view, value) {
15779     if (value === null) {
15780       view.transitionTo('preRender');
15781     } else {
15782       view.clearBuffer();
15783       view.transitionTo('hasElement');
15784     }
15785
15786     return value;
15787   }
15788 });
15789
15790
15791 })();
15792
15793
15794
15795 (function() {
15796 /**
15797 @module ember
15798 @submodule ember-views
15799 */
15800
15801 var get = Ember.get, set = Ember.set, meta = Ember.meta;
15802
15803 var hasElement = Ember.View.states.hasElement = Ember.create(Ember.View.states._default);
15804
15805 Ember.merge(hasElement, {
15806   $: function(view, sel) {
15807     var elem = get(view, 'element');
15808     return sel ? Ember.$(sel, elem) : Ember.$(elem);
15809   },
15810
15811   getElement: function(view) {
15812     var parent = get(view, 'parentView');
15813     if (parent) { parent = get(parent, 'element'); }
15814     if (parent) { return view.findElementInParentElement(parent); }
15815     return Ember.$("#" + get(view, 'elementId'))[0];
15816   },
15817
15818   setElement: function(view, value) {
15819     if (value === null) {
15820       view.transitionTo('preRender');
15821     } else {
15822       throw "You cannot set an element to a non-null value when the element is already in the DOM.";
15823     }
15824
15825     return value;
15826   },
15827
15828   // once the view has been inserted into the DOM, rerendering is
15829   // deferred to allow bindings to synchronize.
15830   rerender: function(view) {
15831     view.triggerRecursively('willClearRender');
15832
15833     view.clearRenderedChildren();
15834
15835     view.domManager.replace(view);
15836     return view;
15837   },
15838
15839   // once the view is already in the DOM, destroying it removes it
15840   // from the DOM, nukes its element, and puts it back into the
15841   // preRender state if inDOM.
15842
15843   destroyElement: function(view) {
15844     view._notifyWillDestroyElement();
15845     view.domManager.remove(view);
15846     set(view, 'element', null);
15847     if (view._scheduledInsert) {
15848       Ember.run.cancel(view._scheduledInsert);
15849       view._scheduledInsert = null;
15850     }
15851     return view;
15852   },
15853
15854   empty: function(view) {
15855     var _childViews = view._childViews, len, idx;
15856     if (_childViews) {
15857       len = _childViews.length;
15858       for (idx = 0; idx < len; idx++) {
15859         _childViews[idx]._notifyWillDestroyElement();
15860       }
15861     }
15862     view.domManager.empty(view);
15863   },
15864
15865   // Handle events from `Ember.EventDispatcher`
15866   handleEvent: function(view, eventName, evt) {
15867     if (view.has(eventName)) {
15868       // Handler should be able to re-dispatch events, so we don't
15869       // preventDefault or stopPropagation.
15870       return view.trigger(eventName, evt);
15871     } else {
15872       return true; // continue event propagation
15873     }
15874   }
15875 });
15876
15877 var inDOM = Ember.View.states.inDOM = Ember.create(hasElement);
15878
15879 Ember.merge(inDOM, {
15880   insertElement: function(view, fn) {
15881     throw "You can't insert an element into the DOM that has already been inserted";
15882   }
15883 });
15884
15885 })();
15886
15887
15888
15889 (function() {
15890 /**
15891 @module ember
15892 @submodule ember-views
15893 */
15894
15895 var destroyedError = "You can't call %@ on a destroyed view", fmt = Ember.String.fmt;
15896
15897 var destroyed = Ember.View.states.destroyed = Ember.create(Ember.View.states._default);
15898
15899 Ember.merge(destroyed, {
15900   appendChild: function() {
15901     throw fmt(destroyedError, ['appendChild']);
15902   },
15903   rerender: function() {
15904     throw fmt(destroyedError, ['rerender']);
15905   },
15906   destroyElement: function() {
15907     throw fmt(destroyedError, ['destroyElement']);
15908   },
15909   empty: function() {
15910     throw fmt(destroyedError, ['empty']);
15911   },
15912
15913   setElement: function() {
15914     throw fmt(destroyedError, ["set('element', ...)"]);
15915   },
15916
15917   renderToBufferIfNeeded: function() {
15918     throw fmt(destroyedError, ["renderToBufferIfNeeded"]);
15919   },
15920
15921   // Since element insertion is scheduled, don't do anything if
15922   // the view has been destroyed between scheduling and execution
15923   insertElement: Ember.K
15924 });
15925
15926
15927 })();
15928
15929
15930
15931 (function() {
15932 Ember.View.cloneStates = function(from) {
15933   var into = {};
15934
15935   into._default = {};
15936   into.preRender = Ember.create(into._default);
15937   into.destroyed = Ember.create(into._default);
15938   into.inBuffer = Ember.create(into._default);
15939   into.hasElement = Ember.create(into._default);
15940   into.inDOM = Ember.create(into.hasElement);
15941
15942   var viewState;
15943
15944   for (var stateName in from) {
15945     if (!from.hasOwnProperty(stateName)) { continue; }
15946     Ember.merge(into[stateName], from[stateName]);
15947   }
15948
15949   return into;
15950 };
15951
15952 })();
15953
15954
15955
15956 (function() {
15957 var states = Ember.View.cloneStates(Ember.View.states);
15958
15959 /**
15960 @module ember
15961 @submodule ember-views
15962 */
15963
15964 var get = Ember.get, set = Ember.set, meta = Ember.meta;
15965 var forEach = Ember.EnumerableUtils.forEach;
15966
15967 var childViewsProperty = Ember.computed(function() {
15968   return get(this, '_childViews');
15969 }).property('_childViews');
15970
15971 /**
15972   A `ContainerView` is an `Ember.View` subclass that allows for manual or
15973   programatic management of a view's `childViews` array that will correctly
15974   update the `ContainerView` instance's rendered DOM representation.
15975
15976   ## Setting Initial Child Views
15977
15978   The initial array of child views can be set in one of two ways. You can
15979   provide a `childViews` property at creation time that contains instance of
15980   `Ember.View`:
15981
15982   ```javascript
15983   aContainer = Ember.ContainerView.create({
15984     childViews: [Ember.View.create(), Ember.View.create()]
15985   });
15986   ```
15987
15988   You can also provide a list of property names whose values are instances of
15989   `Ember.View`:
15990
15991   ```javascript
15992   aContainer = Ember.ContainerView.create({
15993     childViews: ['aView', 'bView', 'cView'],
15994     aView: Ember.View.create(),
15995     bView: Ember.View.create(),
15996     cView: Ember.View.create()
15997   });
15998   ```
15999
16000   The two strategies can be combined:
16001
16002   ```javascript
16003   aContainer = Ember.ContainerView.create({
16004     childViews: ['aView', Ember.View.create()],
16005     aView: Ember.View.create()
16006   });
16007   ```
16008
16009   Each child view's rendering will be inserted into the container's rendered
16010   HTML in the same order as its position in the `childViews` property.
16011
16012   ## Adding and Removing Child Views
16013
16014   The views in a container's `childViews` array should be added and removed by
16015   manipulating the `childViews` property directly.
16016
16017   To remove a view pass that view into a `removeObject` call on the container's
16018   `childViews` property.
16019
16020   Given an empty `<body>` the following code
16021
16022   ```javascript
16023   aContainer = Ember.ContainerView.create({
16024     classNames: ['the-container'],
16025     childViews: ['aView', 'bView'],
16026     aView: Ember.View.create({
16027       template: Ember.Handlebars.compile("A")
16028     }),
16029     bView: Ember.View.create({
16030       template: Ember.Handlebars.compile("B")
16031     })
16032   });
16033
16034   aContainer.appendTo('body');
16035   ```
16036
16037   Results in the HTML
16038
16039   ```html
16040   <div class="ember-view the-container">
16041     <div class="ember-view">A</div>
16042     <div class="ember-view">B</div>
16043   </div>
16044   ```
16045
16046   Removing a view
16047
16048   ```javascript
16049   aContainer.get('childViews');  // [aContainer.aView, aContainer.bView]
16050   aContainer.get('childViews').removeObject(aContainer.get('bView'));
16051   aContainer.get('childViews');  // [aContainer.aView]
16052   ```
16053
16054   Will result in the following HTML
16055
16056   ```html
16057   <div class="ember-view the-container">
16058     <div class="ember-view">A</div>
16059   </div>
16060   ```
16061
16062   Similarly, adding a child view is accomplished by adding `Ember.View` instances to the
16063   container's `childViews` property.
16064
16065   Given an empty `<body>` the following code
16066
16067   ```javascript
16068   aContainer = Ember.ContainerView.create({
16069     classNames: ['the-container'],
16070     childViews: ['aView', 'bView'],
16071     aView: Ember.View.create({
16072       template: Ember.Handlebars.compile("A")
16073     }),
16074     bView: Ember.View.create({
16075       template: Ember.Handlebars.compile("B")
16076     })
16077   });
16078
16079   aContainer.appendTo('body');
16080   ```
16081
16082   Results in the HTML
16083
16084   ```html
16085   <div class="ember-view the-container">
16086     <div class="ember-view">A</div>
16087     <div class="ember-view">B</div>
16088   </div>
16089   ```
16090
16091   Adding a view
16092
16093   ```javascript
16094   AnotherViewClass = Ember.View.extend({
16095     template: Ember.Handlebars.compile("Another view")
16096   });
16097
16098   aContainer.get('childViews');  // [aContainer.aView, aContainer.bView]
16099   aContainer.get('childViews').pushObject(AnotherViewClass.create());
16100   aContainer.get('childViews');  // [aContainer.aView, aContainer.bView, <AnotherViewClass instance>]
16101   ```
16102
16103   Will result in the following HTML
16104
16105   ```html
16106   <div class="ember-view the-container">
16107     <div class="ember-view">A</div>
16108     <div class="ember-view">B</div>
16109     <div class="ember-view">Another view</div>
16110   </div>
16111   ```
16112
16113   Direct manipulation of `childViews` presence or absence in the DOM via calls
16114   to `remove` or `removeFromParent` or calls to a container's `removeChild` may
16115   not behave correctly.
16116
16117   Calling `remove()` on a child view will remove the view's HTML, but it will
16118   remain as part of its container's `childView`s property.
16119
16120   Calling `removeChild()` on the container will remove the passed view instance
16121   from the container's `childView`s but keep its HTML within the container's
16122   rendered view.
16123
16124   Calling `removeFromParent()` behaves as expected but should be avoided in
16125   favor of direct manipulation of a container's `childViews` property.
16126
16127   ```javascript
16128   aContainer = Ember.ContainerView.create({
16129     classNames: ['the-container'],
16130     childViews: ['aView', 'bView'],
16131     aView: Ember.View.create({
16132       template: Ember.Handlebars.compile("A")
16133     }),
16134     bView: Ember.View.create({
16135       template: Ember.Handlebars.compile("B")
16136     })
16137   });
16138
16139   aContainer.appendTo('body');
16140   ```
16141
16142   Results in the HTML
16143
16144   ```html
16145   <div class="ember-view the-container">
16146     <div class="ember-view">A</div>
16147     <div class="ember-view">B</div>
16148   </div>
16149   ```
16150
16151   Calling `aContainer.get('aView').removeFromParent()` will result in the
16152   following HTML
16153
16154   ```html
16155   <div class="ember-view the-container">
16156     <div class="ember-view">B</div>
16157   </div>
16158   ```
16159
16160   And the `Ember.View` instance stored in `aContainer.aView` will be removed from `aContainer`'s
16161   `childViews` array.
16162
16163   ## Templates and Layout
16164
16165   A `template`, `templateName`, `defaultTemplate`, `layout`, `layoutName` or
16166   `defaultLayout` property on a container view will not result in the template
16167   or layout being rendered. The HTML contents of a `Ember.ContainerView`'s DOM
16168   representation will only be the rendered HTML of its child views.
16169
16170   ## Binding a View to Display
16171
16172   If you would like to display a single view in your ContainerView, you can set
16173   its `currentView` property. When the `currentView` property is set to a view
16174   instance, it will be added to the ContainerView's `childViews` array. If the
16175   `currentView` property is later changed to a different view, the new view
16176   will replace the old view. If `currentView` is set to `null`, the last
16177   `currentView` will be removed.
16178
16179   This functionality is useful for cases where you want to bind the display of
16180   a ContainerView to a controller or state manager. For example, you can bind
16181   the `currentView` of a container to a controller like this:
16182
16183   ```javascript
16184   App.appController = Ember.Object.create({
16185     view: Ember.View.create({
16186       templateName: 'person_template'
16187     })
16188   });
16189   ```
16190
16191   ```handlebars
16192   {{view Ember.ContainerView currentViewBinding="App.appController.view"}}
16193   ```
16194
16195   @class ContainerView
16196   @namespace Ember
16197   @extends Ember.View
16198 */
16199
16200 Ember.ContainerView = Ember.View.extend({
16201   states: states,
16202
16203   init: function() {
16204     this._super();
16205
16206     var childViews = get(this, 'childViews');
16207     Ember.defineProperty(this, 'childViews', childViewsProperty);
16208
16209     var _childViews = this._childViews;
16210
16211     forEach(childViews, function(viewName, idx) {
16212       var view;
16213
16214       if ('string' === typeof viewName) {
16215         view = get(this, viewName);
16216         view = this.createChildView(view);
16217         set(this, viewName, view);
16218       } else {
16219         view = this.createChildView(viewName);
16220       }
16221
16222       _childViews[idx] = view;
16223     }, this);
16224
16225     var currentView = get(this, 'currentView');
16226     if (currentView) _childViews.push(this.createChildView(currentView));
16227
16228     // Make the _childViews array observable
16229     Ember.A(_childViews);
16230
16231     // Sets up an array observer on the child views array. This
16232     // observer will detect when child views are added or removed
16233     // and update the DOM to reflect the mutation.
16234     get(this, 'childViews').addArrayObserver(this, {
16235       willChange: 'childViewsWillChange',
16236       didChange: 'childViewsDidChange'
16237     });
16238   },
16239
16240   /**
16241     @private
16242
16243     Instructs each child view to render to the passed render buffer.
16244
16245     @method render
16246     @param {Ember.RenderBuffer} buffer the buffer to render to
16247   */
16248   render: function(buffer) {
16249     this.forEachChildView(function(view) {
16250       view.renderToBuffer(buffer);
16251     });
16252   },
16253
16254   instrumentName: 'render.container',
16255
16256   /**
16257     @private
16258
16259     When the container view is destroyed, tear down the child views
16260     array observer.
16261
16262     @method willDestroy
16263   */
16264   willDestroy: function() {
16265     get(this, 'childViews').removeArrayObserver(this, {
16266       willChange: 'childViewsWillChange',
16267       didChange: 'childViewsDidChange'
16268     });
16269
16270     this._super();
16271   },
16272
16273   /**
16274     @private
16275
16276     When a child view is removed, destroy its element so that
16277     it is removed from the DOM.
16278
16279     The array observer that triggers this action is set up in the
16280     `renderToBuffer` method.
16281
16282     @method childViewsWillChange
16283     @param {Ember.Array} views the child views array before mutation
16284     @param {Number} start the start position of the mutation
16285     @param {Number} removed the number of child views removed
16286   **/
16287   childViewsWillChange: function(views, start, removed) {
16288     if (removed === 0) { return; }
16289
16290     var changedViews = views.slice(start, start+removed);
16291     this.initializeViews(changedViews, null, null);
16292
16293     this.currentState.childViewsWillChange(this, views, start, removed);
16294   },
16295
16296   /**
16297     @private
16298
16299     When a child view is added, make sure the DOM gets updated appropriately.
16300
16301     If the view has already rendered an element, we tell the child view to
16302     create an element and insert it into the DOM. If the enclosing container
16303     view has already written to a buffer, but not yet converted that buffer
16304     into an element, we insert the string representation of the child into the
16305     appropriate place in the buffer.
16306
16307     @method childViewsDidChange
16308     @param {Ember.Array} views the array of child views afte the mutation has occurred
16309     @param {Number} start the start position of the mutation
16310     @param {Number} removed the number of child views removed
16311     @param {Number} the number of child views added
16312   */
16313   childViewsDidChange: function(views, start, removed, added) {
16314     var len = get(views, 'length');
16315
16316     // No new child views were added; bail out.
16317     if (added === 0) return;
16318
16319     var changedViews = views.slice(start, start+added);
16320     this.initializeViews(changedViews, this, get(this, 'templateData'));
16321
16322     // Let the current state handle the changes
16323     this.currentState.childViewsDidChange(this, views, start, added);
16324   },
16325
16326   initializeViews: function(views, parentView, templateData) {
16327     forEach(views, function(view) {
16328       set(view, '_parentView', parentView);
16329
16330       if (!get(view, 'templateData')) {
16331         set(view, 'templateData', templateData);
16332       }
16333     });
16334   },
16335
16336   currentView: null,
16337
16338   _currentViewWillChange: Ember.beforeObserver(function() {
16339     var childViews = get(this, 'childViews'),
16340         currentView = get(this, 'currentView');
16341
16342     if (currentView) {
16343       currentView.destroy();
16344       childViews.removeObject(currentView);
16345     }
16346   }, 'currentView'),
16347
16348   _currentViewDidChange: Ember.observer(function() {
16349     var childViews = get(this, 'childViews'),
16350         currentView = get(this, 'currentView');
16351
16352     if (currentView) {
16353       childViews.pushObject(currentView);
16354     }
16355   }, 'currentView'),
16356
16357   _ensureChildrenAreInDOM: function () {
16358     this.currentState.ensureChildrenAreInDOM(this);
16359   }
16360 });
16361
16362 Ember.merge(states._default, {
16363   childViewsWillChange: Ember.K,
16364   childViewsDidChange: Ember.K,
16365   ensureChildrenAreInDOM: Ember.K
16366 });
16367
16368 Ember.merge(states.inBuffer, {
16369   childViewsDidChange: function(parentView, views, start, added) {
16370     throw new Error('You cannot modify child views while in the inBuffer state');
16371   }
16372 });
16373
16374 Ember.merge(states.hasElement, {
16375   childViewsWillChange: function(view, views, start, removed) {
16376     for (var i=start; i<start+removed; i++) {
16377       views[i].remove();
16378     }
16379   },
16380
16381   childViewsDidChange: function(view, views, start, added) {
16382     Ember.run.scheduleOnce('render', view, '_ensureChildrenAreInDOM');
16383   },
16384
16385   ensureChildrenAreInDOM: function(view) {
16386     var childViews = view.get('childViews'), i, len, childView, previous, buffer;
16387     for (i = 0, len = childViews.length; i < len; i++) {
16388       childView = childViews[i];
16389       buffer = childView.renderToBufferIfNeeded();
16390       if (buffer) {
16391         childView.triggerRecursively('willInsertElement');
16392         if (previous) {
16393           previous.domManager.after(previous, buffer.string());
16394         } else {
16395           view.domManager.prepend(view, buffer.string());
16396         }
16397         childView.transitionTo('inDOM');
16398         childView.propertyDidChange('element');
16399         childView.triggerRecursively('didInsertElement');
16400       }
16401       previous = childView;
16402     }
16403   }
16404 });
16405
16406 })();
16407
16408
16409
16410 (function() {
16411 /**
16412 @module ember
16413 @submodule ember-views
16414 */
16415
16416 var get = Ember.get, set = Ember.set, fmt = Ember.String.fmt;
16417
16418 /**
16419   `Ember.CollectionView` is an `Ember.View` descendent responsible for managing
16420   a collection (an array or array-like object) by maintaing a child view object
16421   and associated DOM representation for each item in the array and ensuring
16422   that child views and their associated rendered HTML are updated when items in
16423   the array are added, removed, or replaced.
16424
16425   ## Setting content
16426
16427   The managed collection of objects is referenced as the `Ember.CollectionView`
16428   instance's `content` property.
16429
16430   ```javascript
16431   someItemsView = Ember.CollectionView.create({
16432     content: ['A', 'B','C']
16433   })
16434   ```
16435
16436   The view for each item in the collection will have its `content` property set
16437   to the item.
16438
16439   ## Specifying itemViewClass
16440
16441   By default the view class for each item in the managed collection will be an
16442   instance of `Ember.View`. You can supply a different class by setting the
16443   `CollectionView`'s `itemViewClass` property.
16444
16445   Given an empty `<body>` and the following code:
16446
16447   ```javascript 
16448   someItemsView = Ember.CollectionView.create({
16449     classNames: ['a-collection'],
16450     content: ['A','B','C'],
16451     itemViewClass: Ember.View.extend({
16452       template: Ember.Handlebars.compile("the letter: {{view.content}}")
16453     })
16454   });
16455
16456   someItemsView.appendTo('body');
16457   ```
16458
16459   Will result in the following HTML structure
16460
16461   ```html
16462   <div class="ember-view a-collection">
16463     <div class="ember-view">the letter: A</div>
16464     <div class="ember-view">the letter: B</div>
16465     <div class="ember-view">the letter: C</div>
16466   </div>
16467   ```
16468
16469   ## Automatic matching of parent/child tagNames
16470
16471   Setting the `tagName` property of a `CollectionView` to any of
16472   "ul", "ol", "table", "thead", "tbody", "tfoot", "tr", or "select" will result
16473   in the item views receiving an appropriately matched `tagName` property.
16474
16475   Given an empty `<body>` and the following code:
16476
16477   ```javascript
16478   anUndorderedListView = Ember.CollectionView.create({
16479     tagName: 'ul',
16480     content: ['A','B','C'],
16481     itemViewClass: Ember.View.extend({
16482       template: Ember.Handlebars.compile("the letter: {{view.content}}")
16483     })
16484   });
16485
16486   anUndorderedListView.appendTo('body');
16487   ```
16488
16489   Will result in the following HTML structure
16490
16491   ```html
16492   <ul class="ember-view a-collection">
16493     <li class="ember-view">the letter: A</li>
16494     <li class="ember-view">the letter: B</li>
16495     <li class="ember-view">the letter: C</li>
16496   </ul>
16497   ```
16498
16499   Additional `tagName` pairs can be provided by adding to
16500   `Ember.CollectionView.CONTAINER_MAP `
16501
16502   ```javascript
16503   Ember.CollectionView.CONTAINER_MAP['article'] = 'section'
16504   ```
16505
16506   ## Programatic creation of child views
16507
16508   For cases where additional customization beyond the use of a single
16509   `itemViewClass` or `tagName` matching is required CollectionView's
16510   `createChildView` method can be overidden:
16511
16512   ```javascript
16513   CustomCollectionView = Ember.CollectionView.extend({
16514     createChildView: function(viewClass, attrs) {
16515       if (attrs.content.kind == 'album') {
16516         viewClass = App.AlbumView;
16517       } else {
16518         viewClass = App.SongView;
16519       }
16520       this._super(viewClass, attrs);
16521     }
16522   });
16523   ```
16524
16525   ## Empty View
16526
16527   You can provide an `Ember.View` subclass to the `Ember.CollectionView`
16528   instance as its `emptyView` property. If the `content` property of a
16529   `CollectionView` is set to `null` or an empty array, an instance of this view
16530   will be the `CollectionView`s only child.
16531
16532   ```javascript
16533   aListWithNothing = Ember.CollectionView.create({
16534     classNames: ['nothing']
16535     content: null,
16536     emptyView: Ember.View.extend({
16537       template: Ember.Handlebars.compile("The collection is empty")
16538     })
16539   });
16540
16541   aListWithNothing.appendTo('body');
16542   ```
16543
16544   Will result in the following HTML structure
16545
16546   ```html
16547   <div class="ember-view nothing">
16548     <div class="ember-view">
16549       The collection is empty
16550     </div>
16551   </div>
16552   ```
16553
16554   ## Adding and Removing items
16555
16556   The `childViews` property of a `CollectionView` should not be directly
16557   manipulated. Instead, add, remove, replace items from its `content` property.
16558   This will trigger appropriate changes to its rendered HTML.
16559
16560   ## Use in templates via the `{{collection}}` `Ember.Handlebars` helper
16561
16562   `Ember.Handlebars` provides a helper specifically for adding
16563   `CollectionView`s to templates. See `Ember.Handlebars.collection` for more
16564   details
16565
16566   @class CollectionView
16567   @namespace Ember
16568   @extends Ember.ContainerView
16569   @since Ember 0.9
16570 */
16571 Ember.CollectionView = Ember.ContainerView.extend(
16572 /** @scope Ember.CollectionView.prototype */ {
16573
16574   /**
16575     A list of items to be displayed by the `Ember.CollectionView`.
16576
16577     @property content
16578     @type Ember.Array
16579     @default null
16580   */
16581   content: null,
16582
16583   /**
16584     @private
16585
16586     This provides metadata about what kind of empty view class this
16587     collection would like if it is being instantiated from another
16588     system (like Handlebars)
16589
16590     @property emptyViewClass
16591   */
16592   emptyViewClass: Ember.View,
16593
16594   /**
16595     An optional view to display if content is set to an empty array.
16596
16597     @property emptyView
16598     @type Ember.View
16599     @default null
16600   */
16601   emptyView: null,
16602
16603   /**
16604     @property itemViewClass
16605     @type Ember.View
16606     @default Ember.View
16607   */
16608   itemViewClass: Ember.View,
16609
16610   init: function() {
16611     var ret = this._super();
16612     this._contentDidChange();
16613     return ret;
16614   },
16615
16616   _contentWillChange: Ember.beforeObserver(function() {
16617     var content = this.get('content');
16618
16619     if (content) { content.removeArrayObserver(this); }
16620     var len = content ? get(content, 'length') : 0;
16621     this.arrayWillChange(content, 0, len);
16622   }, 'content'),
16623
16624   /**
16625     @private
16626
16627     Check to make sure that the content has changed, and if so,
16628     update the children directly. This is always scheduled
16629     asynchronously, to allow the element to be created before
16630     bindings have synchronized and vice versa.
16631
16632     @method _contentDidChange
16633   */
16634   _contentDidChange: Ember.observer(function() {
16635     var content = get(this, 'content');
16636
16637     if (content) {
16638       Ember.assert(fmt("an Ember.CollectionView's content must implement Ember.Array. You passed %@", [content]), Ember.Array.detect(content));
16639       content.addArrayObserver(this);
16640     }
16641
16642     var len = content ? get(content, 'length') : 0;
16643     this.arrayDidChange(content, 0, null, len);
16644   }, 'content'),
16645
16646   willDestroy: function() {
16647     var content = get(this, 'content');
16648     if (content) { content.removeArrayObserver(this); }
16649
16650     this._super();
16651   },
16652
16653   arrayWillChange: function(content, start, removedCount) {
16654     // If the contents were empty before and this template collection has an
16655     // empty view remove it now.
16656     var emptyView = get(this, 'emptyView');
16657     if (emptyView && emptyView instanceof Ember.View) {
16658       emptyView.removeFromParent();
16659     }
16660
16661     // Loop through child views that correspond with the removed items.
16662     // Note that we loop from the end of the array to the beginning because
16663     // we are mutating it as we go.
16664     var childViews = get(this, 'childViews'), childView, idx, len;
16665
16666     len = get(childViews, 'length');
16667
16668     var removingAll = removedCount === len;
16669
16670     if (removingAll) {
16671       this.currentState.empty(this);
16672     }
16673
16674     for (idx = start + removedCount - 1; idx >= start; idx--) {
16675       childView = childViews[idx];
16676       if (removingAll) { childView.removedFromDOM = true; }
16677       childView.destroy();
16678     }
16679   },
16680
16681   /**
16682     Called when a mutation to the underlying content array occurs.
16683
16684     This method will replay that mutation against the views that compose the
16685     `Ember.CollectionView`, ensuring that the view reflects the model.
16686
16687     This array observer is added in `contentDidChange`.
16688
16689     @method arrayDidChange
16690     @param {Array} addedObjects the objects that were added to the content
16691     @param {Array} removedObjects the objects that were removed from the content
16692     @param {Number} changeIndex the index at which the changes occurred
16693   */
16694   arrayDidChange: function(content, start, removed, added) {
16695     var itemViewClass = get(this, 'itemViewClass'),
16696         childViews = get(this, 'childViews'),
16697         addedViews = [], view, item, idx, len, itemTagName;
16698
16699     if ('string' === typeof itemViewClass) {
16700       itemViewClass = get(itemViewClass);
16701     }
16702
16703     Ember.assert(fmt("itemViewClass must be a subclass of Ember.View, not %@", [itemViewClass]), Ember.View.detect(itemViewClass));
16704
16705     len = content ? get(content, 'length') : 0;
16706     if (len) {
16707       for (idx = start; idx < start+added; idx++) {
16708         item = content.objectAt(idx);
16709
16710         view = this.createChildView(itemViewClass, {
16711           content: item,
16712           contentIndex: idx
16713         });
16714
16715         addedViews.push(view);
16716       }
16717     } else {
16718       var emptyView = get(this, 'emptyView');
16719       if (!emptyView) { return; }
16720
16721       emptyView = this.createChildView(emptyView);
16722       addedViews.push(emptyView);
16723       set(this, 'emptyView', emptyView);
16724     }
16725     childViews.replace(start, 0, addedViews);
16726   },
16727
16728   createChildView: function(view, attrs) {
16729     view = this._super(view, attrs);
16730
16731     var itemTagName = get(view, 'tagName');
16732     var tagName = (itemTagName === null || itemTagName === undefined) ? Ember.CollectionView.CONTAINER_MAP[get(this, 'tagName')] : itemTagName;
16733
16734     set(view, 'tagName', tagName);
16735
16736     return view;
16737   }
16738 });
16739
16740 /**
16741   A map of parent tags to their default child tags. You can add
16742   additional parent tags if you want collection views that use
16743   a particular parent tag to default to a child tag.
16744
16745   @property CONTAINER_MAP
16746   @type Hash
16747   @static
16748   @final
16749 */
16750 Ember.CollectionView.CONTAINER_MAP = {
16751   ul: 'li',
16752   ol: 'li',
16753   table: 'tr',
16754   thead: 'tr',
16755   tbody: 'tr',
16756   tfoot: 'tr',
16757   tr: 'td',
16758   select: 'option'
16759 };
16760
16761 })();
16762
16763
16764
16765 (function() {
16766
16767 })();
16768
16769
16770
16771 (function() {
16772 /*globals jQuery*/
16773 /**
16774 Ember Views
16775
16776 @module ember
16777 @submodule ember-views
16778 @requires ember-runtime
16779 @main ember-views
16780 */
16781
16782 })();
16783
16784 (function() {
16785 define("metamorph",
16786   [],
16787   function() {
16788     "use strict";
16789     // ==========================================================================
16790     // Project:   metamorph
16791     // Copyright: Â©2011 My Company Inc. All rights reserved.
16792     // ==========================================================================
16793
16794     var K = function(){},
16795         guid = 0,
16796         document = window.document,
16797
16798         // Feature-detect the W3C range API, the extended check is for IE9 which only partially supports ranges
16799         supportsRange = ('createRange' in document) && (typeof Range !== 'undefined') && Range.prototype.createContextualFragment,
16800
16801         // Internet Explorer prior to 9 does not allow setting innerHTML if the first element
16802         // is a "zero-scope" element. This problem can be worked around by making
16803         // the first node an invisible text node. We, like Modernizr, use &shy;
16804         needsShy = (function(){
16805           var testEl = document.createElement('div');
16806           testEl.innerHTML = "<div></div>";
16807           testEl.firstChild.innerHTML = "<script></script>";
16808           return testEl.firstChild.innerHTML === '';
16809         })(),
16810
16811
16812         // IE 8 (and likely earlier) likes to move whitespace preceeding
16813         // a script tag to appear after it. This means that we can
16814         // accidentally remove whitespace when updating a morph.
16815         movesWhitespace = (function() {
16816           var testEl = document.createElement('div');
16817           testEl.innerHTML = "Test: <script type='text/x-placeholder'></script>Value";
16818           return testEl.childNodes[0].nodeValue === 'Test:' &&
16819                   testEl.childNodes[2].nodeValue === ' Value';
16820         })();
16821
16822     // Constructor that supports either Metamorph('foo') or new
16823     // Metamorph('foo');
16824     //
16825     // Takes a string of HTML as the argument.
16826
16827     var Metamorph = function(html) {
16828       var self;
16829
16830       if (this instanceof Metamorph) {
16831         self = this;
16832       } else {
16833         self = new K();
16834       }
16835
16836       self.innerHTML = html;
16837       var myGuid = 'metamorph-'+(guid++);
16838       self.start = myGuid + '-start';
16839       self.end = myGuid + '-end';
16840
16841       return self;
16842     };
16843
16844     K.prototype = Metamorph.prototype;
16845
16846     var rangeFor, htmlFunc, removeFunc, outerHTMLFunc, appendToFunc, afterFunc, prependFunc, startTagFunc, endTagFunc;
16847
16848     outerHTMLFunc = function() {
16849       return this.startTag() + this.innerHTML + this.endTag();
16850     };
16851
16852     startTagFunc = function() {
16853       /*
16854        * We replace chevron by its hex code in order to prevent escaping problems.
16855        * Check this thread for more explaination:
16856        * http://stackoverflow.com/questions/8231048/why-use-x3c-instead-of-when-generating-html-from-javascript
16857        */
16858       return "<script id='" + this.start + "' type='text/x-placeholder'>\x3C/script>";
16859     };
16860
16861     endTagFunc = function() {
16862       /*
16863        * We replace chevron by its hex code in order to prevent escaping problems.
16864        * Check this thread for more explaination:
16865        * http://stackoverflow.com/questions/8231048/why-use-x3c-instead-of-when-generating-html-from-javascript
16866        */
16867       return "<script id='" + this.end + "' type='text/x-placeholder'>\x3C/script>";
16868     };
16869
16870     // If we have the W3C range API, this process is relatively straight forward.
16871     if (supportsRange) {
16872
16873       // Get a range for the current morph. Optionally include the starting and
16874       // ending placeholders.
16875       rangeFor = function(morph, outerToo) {
16876         var range = document.createRange();
16877         var before = document.getElementById(morph.start);
16878         var after = document.getElementById(morph.end);
16879
16880         if (outerToo) {
16881           range.setStartBefore(before);
16882           range.setEndAfter(after);
16883         } else {
16884           range.setStartAfter(before);
16885           range.setEndBefore(after);
16886         }
16887
16888         return range;
16889       };
16890
16891       htmlFunc = function(html, outerToo) {
16892         // get a range for the current metamorph object
16893         var range = rangeFor(this, outerToo);
16894
16895         // delete the contents of the range, which will be the
16896         // nodes between the starting and ending placeholder.
16897         range.deleteContents();
16898
16899         // create a new document fragment for the HTML
16900         var fragment = range.createContextualFragment(html);
16901
16902         // insert the fragment into the range
16903         range.insertNode(fragment);
16904       };
16905
16906       removeFunc = function() {
16907         // get a range for the current metamorph object including
16908         // the starting and ending placeholders.
16909         var range = rangeFor(this, true);
16910
16911         // delete the entire range.
16912         range.deleteContents();
16913       };
16914
16915       appendToFunc = function(node) {
16916         var range = document.createRange();
16917         range.setStart(node);
16918         range.collapse(false);
16919         var frag = range.createContextualFragment(this.outerHTML());
16920         node.appendChild(frag);
16921       };
16922
16923       afterFunc = function(html) {
16924         var range = document.createRange();
16925         var after = document.getElementById(this.end);
16926
16927         range.setStartAfter(after);
16928         range.setEndAfter(after);
16929
16930         var fragment = range.createContextualFragment(html);
16931         range.insertNode(fragment);
16932       };
16933
16934       prependFunc = function(html) {
16935         var range = document.createRange();
16936         var start = document.getElementById(this.start);
16937
16938         range.setStartAfter(start);
16939         range.setEndAfter(start);
16940
16941         var fragment = range.createContextualFragment(html);
16942         range.insertNode(fragment);
16943       };
16944
16945     } else {
16946       /**
16947        * This code is mostly taken from jQuery, with one exception. In jQuery's case, we
16948        * have some HTML and we need to figure out how to convert it into some nodes.
16949        *
16950        * In this case, jQuery needs to scan the HTML looking for an opening tag and use
16951        * that as the key for the wrap map. In our case, we know the parent node, and
16952        * can use its type as the key for the wrap map.
16953        **/
16954       var wrapMap = {
16955         select: [ 1, "<select multiple='multiple'>", "</select>" ],
16956         fieldset: [ 1, "<fieldset>", "</fieldset>" ],
16957         table: [ 1, "<table>", "</table>" ],
16958         tbody: [ 2, "<table><tbody>", "</tbody></table>" ],
16959         tr: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
16960         colgroup: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
16961         map: [ 1, "<map>", "</map>" ],
16962         _default: [ 0, "", "" ]
16963       };
16964
16965       var findChildById = function(element, id) {
16966         if (element.getAttribute('id') === id) { return element; }
16967
16968         var len = element.childNodes.length, idx, node, found;
16969         for (idx=0; idx<len; idx++) {
16970           node = element.childNodes[idx];
16971           found = node.nodeType === 1 && findChildById(node, id);
16972           if (found) { return found; }
16973         }
16974       };
16975
16976       var setInnerHTML = function(element, html) {
16977         var matches = [];
16978         if (movesWhitespace) {
16979           // Right now we only check for script tags with ids with the
16980           // goal of targeting morphs.
16981           html = html.replace(/(\s+)(<script id='([^']+)')/g, function(match, spaces, tag, id) {
16982             matches.push([id, spaces]);
16983             return tag;
16984           });
16985         }
16986
16987         element.innerHTML = html;
16988
16989         // If we have to do any whitespace adjustments do them now
16990         if (matches.length > 0) {
16991           var len = matches.length, idx;
16992           for (idx=0; idx<len; idx++) {
16993             var script = findChildById(element, matches[idx][0]),
16994                 node = document.createTextNode(matches[idx][1]);
16995             script.parentNode.insertBefore(node, script);
16996           }
16997         }
16998       };
16999
17000       /**
17001        * Given a parent node and some HTML, generate a set of nodes. Return the first
17002        * node, which will allow us to traverse the rest using nextSibling.
17003        *
17004        * We need to do this because innerHTML in IE does not really parse the nodes.
17005        **/
17006       var firstNodeFor = function(parentNode, html) {
17007         var arr = wrapMap[parentNode.tagName.toLowerCase()] || wrapMap._default;
17008         var depth = arr[0], start = arr[1], end = arr[2];
17009
17010         if (needsShy) { html = '&shy;'+html; }
17011
17012         var element = document.createElement('div');
17013
17014         setInnerHTML(element, start + html + end);
17015
17016         for (var i=0; i<=depth; i++) {
17017           element = element.firstChild;
17018         }
17019
17020         // Look for &shy; to remove it.
17021         if (needsShy) {
17022           var shyElement = element;
17023
17024           // Sometimes we get nameless elements with the shy inside
17025           while (shyElement.nodeType === 1 && !shyElement.nodeName) {
17026             shyElement = shyElement.firstChild;
17027           }
17028
17029           // At this point it's the actual unicode character.
17030           if (shyElement.nodeType === 3 && shyElement.nodeValue.charAt(0) === "\u00AD") {
17031             shyElement.nodeValue = shyElement.nodeValue.slice(1);
17032           }
17033         }
17034
17035         return element;
17036       };
17037
17038       /**
17039        * In some cases, Internet Explorer can create an anonymous node in
17040        * the hierarchy with no tagName. You can create this scenario via:
17041        *
17042        *     div = document.createElement("div");
17043        *     div.innerHTML = "<table>&shy<script></script><tr><td>hi</td></tr></table>";
17044        *     div.firstChild.firstChild.tagName //=> ""
17045        *
17046        * If our script markers are inside such a node, we need to find that
17047        * node and use *it* as the marker.
17048        **/
17049       var realNode = function(start) {
17050         while (start.parentNode.tagName === "") {
17051           start = start.parentNode;
17052         }
17053
17054         return start;
17055       };
17056
17057       /**
17058        * When automatically adding a tbody, Internet Explorer inserts the
17059        * tbody immediately before the first <tr>. Other browsers create it
17060        * before the first node, no matter what.
17061        *
17062        * This means the the following code:
17063        *
17064        *     div = document.createElement("div");
17065        *     div.innerHTML = "<table><script id='first'></script><tr><td>hi</td></tr><script id='last'></script></table>
17066        *
17067        * Generates the following DOM in IE:
17068        *
17069        *     + div
17070        *       + table
17071        *         - script id='first'
17072        *         + tbody
17073        *           + tr
17074        *             + td
17075        *               - "hi"
17076        *           - script id='last'
17077        *
17078        * Which means that the two script tags, even though they were
17079        * inserted at the same point in the hierarchy in the original
17080        * HTML, now have different parents.
17081        *
17082        * This code reparents the first script tag by making it the tbody's
17083        * first child.
17084        **/
17085       var fixParentage = function(start, end) {
17086         if (start.parentNode !== end.parentNode) {
17087           end.parentNode.insertBefore(start, end.parentNode.firstChild);
17088         }
17089       };
17090
17091       htmlFunc = function(html, outerToo) {
17092         // get the real starting node. see realNode for details.
17093         var start = realNode(document.getElementById(this.start));
17094         var end = document.getElementById(this.end);
17095         var parentNode = end.parentNode;
17096         var node, nextSibling, last;
17097
17098         // make sure that the start and end nodes share the same
17099         // parent. If not, fix it.
17100         fixParentage(start, end);
17101
17102         // remove all of the nodes after the starting placeholder and
17103         // before the ending placeholder.
17104         node = start.nextSibling;
17105         while (node) {
17106           nextSibling = node.nextSibling;
17107           last = node === end;
17108
17109           // if this is the last node, and we want to remove it as well,
17110           // set the `end` node to the next sibling. This is because
17111           // for the rest of the function, we insert the new nodes
17112           // before the end (note that insertBefore(node, null) is
17113           // the same as appendChild(node)).
17114           //
17115           // if we do not want to remove it, just break.
17116           if (last) {
17117             if (outerToo) { end = node.nextSibling; } else { break; }
17118           }
17119
17120           node.parentNode.removeChild(node);
17121
17122           // if this is the last node and we didn't break before
17123           // (because we wanted to remove the outer nodes), break
17124           // now.
17125           if (last) { break; }
17126
17127           node = nextSibling;
17128         }
17129
17130         // get the first node for the HTML string, even in cases like
17131         // tables and lists where a simple innerHTML on a div would
17132         // swallow some of the content.
17133         node = firstNodeFor(start.parentNode, html);
17134
17135         // copy the nodes for the HTML between the starting and ending
17136         // placeholder.
17137         while (node) {
17138           nextSibling = node.nextSibling;
17139           parentNode.insertBefore(node, end);
17140           node = nextSibling;
17141         }
17142       };
17143
17144       // remove the nodes in the DOM representing this metamorph.
17145       //
17146       // this includes the starting and ending placeholders.
17147       removeFunc = function() {
17148         var start = realNode(document.getElementById(this.start));
17149         var end = document.getElementById(this.end);
17150
17151         this.html('');
17152         start.parentNode.removeChild(start);
17153         end.parentNode.removeChild(end);
17154       };
17155
17156       appendToFunc = function(parentNode) {
17157         var node = firstNodeFor(parentNode, this.outerHTML());
17158         var nextSibling;
17159
17160         while (node) {
17161           nextSibling = node.nextSibling;
17162           parentNode.appendChild(node);
17163           node = nextSibling;
17164         }
17165       };
17166
17167       afterFunc = function(html) {
17168         // get the real starting node. see realNode for details.
17169         var end = document.getElementById(this.end);
17170         var insertBefore = end.nextSibling;
17171         var parentNode = end.parentNode;
17172         var nextSibling;
17173         var node;
17174
17175         // get the first node for the HTML string, even in cases like
17176         // tables and lists where a simple innerHTML on a div would
17177         // swallow some of the content.
17178         node = firstNodeFor(parentNode, html);
17179
17180         // copy the nodes for the HTML between the starting and ending
17181         // placeholder.
17182         while (node) {
17183           nextSibling = node.nextSibling;
17184           parentNode.insertBefore(node, insertBefore);
17185           node = nextSibling;
17186         }
17187       };
17188
17189       prependFunc = function(html) {
17190         var start = document.getElementById(this.start);
17191         var parentNode = start.parentNode;
17192         var nextSibling;
17193         var node;
17194
17195         node = firstNodeFor(parentNode, html);
17196         var insertBefore = start.nextSibling;
17197
17198         while (node) {
17199           nextSibling = node.nextSibling;
17200           parentNode.insertBefore(node, insertBefore);
17201           node = nextSibling;
17202         }
17203       };
17204     }
17205
17206     Metamorph.prototype.html = function(html) {
17207       this.checkRemoved();
17208       if (html === undefined) { return this.innerHTML; }
17209
17210       htmlFunc.call(this, html);
17211
17212       this.innerHTML = html;
17213     };
17214
17215     Metamorph.prototype.replaceWith = function(html) {
17216       this.checkRemoved();
17217       htmlFunc.call(this, html, true);
17218     };
17219
17220     Metamorph.prototype.remove = removeFunc;
17221     Metamorph.prototype.outerHTML = outerHTMLFunc;
17222     Metamorph.prototype.appendTo = appendToFunc;
17223     Metamorph.prototype.after = afterFunc;
17224     Metamorph.prototype.prepend = prependFunc;
17225     Metamorph.prototype.startTag = startTagFunc;
17226     Metamorph.prototype.endTag = endTagFunc;
17227
17228     Metamorph.prototype.isRemoved = function() {
17229       var before = document.getElementById(this.start);
17230       var after = document.getElementById(this.end);
17231
17232       return !before || !after;
17233     };
17234
17235     Metamorph.prototype.checkRemoved = function() {
17236       if (this.isRemoved()) {
17237         throw new Error("Cannot perform operations on a Metamorph that is not in the DOM.");
17238       }
17239     };
17240
17241     return Metamorph;
17242   });
17243
17244 })();
17245
17246 (function() {
17247 /**
17248 @module ember
17249 @submodule ember-handlebars
17250 */
17251
17252 // Eliminate dependency on any Ember to simplify precompilation workflow
17253 var objectCreate = Object.create || function(parent) {
17254   function F() {}
17255   F.prototype = parent;
17256   return new F();
17257 };
17258
17259 var Handlebars = this.Handlebars || Ember.imports.Handlebars;
17260 Ember.assert("Ember Handlebars requires Handlebars 1.0.beta.5 or greater", Handlebars && Handlebars.VERSION.match(/^1\.0\.beta\.[56789]$|^1\.0\.rc\.[123456789]+/));
17261
17262 /**
17263   Prepares the Handlebars templating library for use inside Ember's view
17264   system.
17265
17266   The `Ember.Handlebars` object is the standard Handlebars library, extended to
17267   use Ember's `get()` method instead of direct property access, which allows
17268   computed properties to be used inside templates.
17269
17270   To create an `Ember.Handlebars` template, call `Ember.Handlebars.compile()`.
17271   This will return a function that can be used by `Ember.View` for rendering.
17272
17273   @class Handlebars
17274   @namespace Ember
17275 */
17276 Ember.Handlebars = objectCreate(Handlebars);
17277
17278 /**
17279 @class helpers
17280 @namespace Ember.Handlebars
17281 */
17282 Ember.Handlebars.helpers = objectCreate(Handlebars.helpers);
17283
17284 /**
17285   Override the the opcode compiler and JavaScript compiler for Handlebars.
17286
17287   @class Compiler
17288   @namespace Ember.Handlebars
17289   @private
17290   @constructor
17291 */
17292 Ember.Handlebars.Compiler = function() {};
17293
17294 // Handlebars.Compiler doesn't exist in runtime-only
17295 if (Handlebars.Compiler) {
17296   Ember.Handlebars.Compiler.prototype = objectCreate(Handlebars.Compiler.prototype);
17297 }
17298
17299 Ember.Handlebars.Compiler.prototype.compiler = Ember.Handlebars.Compiler;
17300
17301 /**
17302   @class JavaScriptCompiler
17303   @namespace Ember.Handlebars
17304   @private
17305   @constructor
17306 */
17307 Ember.Handlebars.JavaScriptCompiler = function() {};
17308
17309 // Handlebars.JavaScriptCompiler doesn't exist in runtime-only
17310 if (Handlebars.JavaScriptCompiler) {
17311   Ember.Handlebars.JavaScriptCompiler.prototype = objectCreate(Handlebars.JavaScriptCompiler.prototype);
17312   Ember.Handlebars.JavaScriptCompiler.prototype.compiler = Ember.Handlebars.JavaScriptCompiler;
17313 }
17314
17315
17316 Ember.Handlebars.JavaScriptCompiler.prototype.namespace = "Ember.Handlebars";
17317
17318
17319 Ember.Handlebars.JavaScriptCompiler.prototype.initializeBuffer = function() {
17320   return "''";
17321 };
17322
17323 /**
17324   @private
17325
17326   Override the default buffer for Ember Handlebars. By default, Handlebars
17327   creates an empty String at the beginning of each invocation and appends to
17328   it. Ember's Handlebars overrides this to append to a single shared buffer.
17329
17330   @method appendToBuffer
17331   @param string {String}
17332 */
17333 Ember.Handlebars.JavaScriptCompiler.prototype.appendToBuffer = function(string) {
17334   return "data.buffer.push("+string+");";
17335 };
17336
17337 /**
17338   @private
17339
17340   Rewrite simple mustaches from `{{foo}}` to `{{bind "foo"}}`. This means that
17341   all simple mustaches in Ember's Handlebars will also set up an observer to
17342   keep the DOM up to date when the underlying property changes.
17343
17344   @method mustache
17345   @for Ember.Handlebars.Compiler
17346   @param mustache
17347 */
17348 Ember.Handlebars.Compiler.prototype.mustache = function(mustache) {
17349   if (mustache.params.length || mustache.hash) {
17350     return Handlebars.Compiler.prototype.mustache.call(this, mustache);
17351   } else {
17352     var id = new Handlebars.AST.IdNode(['_triageMustache']);
17353
17354     // Update the mustache node to include a hash value indicating whether the original node
17355     // was escaped. This will allow us to properly escape values when the underlying value
17356     // changes and we need to re-render the value.
17357     if(!mustache.escaped) {
17358       mustache.hash = mustache.hash || new Handlebars.AST.HashNode([]);
17359       mustache.hash.pairs.push(["unescaped", new Handlebars.AST.StringNode("true")]);
17360     }
17361     mustache = new Handlebars.AST.MustacheNode([id].concat([mustache.id]), mustache.hash, !mustache.escaped);
17362     return Handlebars.Compiler.prototype.mustache.call(this, mustache);
17363   }
17364 };
17365
17366 /**
17367   Used for precompilation of Ember Handlebars templates. This will not be used
17368   during normal app execution.
17369
17370   @method precompile
17371   @for Ember.Handlebars
17372   @static
17373   @param {String} string The template to precompile
17374 */
17375 Ember.Handlebars.precompile = function(string) {
17376   var ast = Handlebars.parse(string);
17377
17378   var options = {
17379     knownHelpers: {
17380       action: true,
17381       unbound: true,
17382       bindAttr: true,
17383       template: true,
17384       view: true,
17385       _triageMustache: true
17386     },
17387     data: true,
17388     stringParams: true
17389   };
17390
17391   var environment = new Ember.Handlebars.Compiler().compile(ast, options);
17392   return new Ember.Handlebars.JavaScriptCompiler().compile(environment, options, undefined, true);
17393 };
17394
17395 // We don't support this for Handlebars runtime-only
17396 if (Handlebars.compile) {
17397   /**
17398     The entry point for Ember Handlebars. This replaces the default
17399     `Handlebars.compile` and turns on template-local data and String
17400     parameters.
17401
17402     @method compile
17403     @for Ember.Handlebars
17404     @static
17405     @param {String} string The template to compile
17406     @return {Function}
17407   */
17408   Ember.Handlebars.compile = function(string) {
17409     var ast = Handlebars.parse(string);
17410     var options = { data: true, stringParams: true };
17411     var environment = new Ember.Handlebars.Compiler().compile(ast, options);
17412     var templateSpec = new Ember.Handlebars.JavaScriptCompiler().compile(environment, options, undefined, true);
17413
17414     return Ember.Handlebars.template(templateSpec);
17415   };
17416 }
17417
17418
17419 })();
17420
17421 (function() {
17422 /**
17423   @private
17424
17425   If a path starts with a reserved keyword, returns the root
17426   that should be used.
17427
17428   @method normalizePath
17429   @for Ember
17430   @param root {Object}
17431   @param path {String}
17432   @param data {Hash}
17433 */
17434 var normalizePath = Ember.Handlebars.normalizePath = function(root, path, data) {
17435   var keywords = (data && data.keywords) || {},
17436       keyword, isKeyword;
17437
17438   // Get the first segment of the path. For example, if the
17439   // path is "foo.bar.baz", returns "foo".
17440   keyword = path.split('.', 1)[0];
17441
17442   // Test to see if the first path is a keyword that has been
17443   // passed along in the view's data hash. If so, we will treat
17444   // that object as the new root.
17445   if (keywords.hasOwnProperty(keyword)) {
17446     // Look up the value in the template's data hash.
17447     root = keywords[keyword];
17448     isKeyword = true;
17449
17450     // Handle cases where the entire path is the reserved
17451     // word. In that case, return the object itself.
17452     if (path === keyword) {
17453       path = '';
17454     } else {
17455       // Strip the keyword from the path and look up
17456       // the remainder from the newly found root.
17457       path = path.substr(keyword.length+1);
17458     }
17459   }
17460
17461   return { root: root, path: path, isKeyword: isKeyword };
17462 };
17463
17464
17465 /**
17466   Lookup both on root and on window. If the path starts with
17467   a keyword, the corresponding object will be looked up in the
17468   template's data hash and used to resolve the path.
17469
17470   @method get
17471   @for Ember.Handlebars
17472   @param {Object} root The object to look up the property on
17473   @param {String} path The path to be lookedup
17474   @param {Object} options The template's option hash
17475 */
17476 Ember.Handlebars.get = function(root, path, options) {
17477   var data = options && options.data,
17478       normalizedPath = normalizePath(root, path, data),
17479       value;
17480
17481   // In cases where the path begins with a keyword, change the
17482   // root to the value represented by that keyword, and ensure
17483   // the path is relative to it.
17484   root = normalizedPath.root;
17485   path = normalizedPath.path;
17486
17487   value = Ember.get(root, path);
17488
17489   // If the path starts with a capital letter, look it up on Ember.lookup,
17490   // which defaults to the `window` object in browsers.
17491   if (value === undefined && root !== Ember.lookup && Ember.isGlobalPath(path)) {
17492     value = Ember.get(Ember.lookup, path);
17493   }
17494   return value;
17495 };
17496 Ember.Handlebars.getPath = Ember.deprecateFunc('`Ember.Handlebars.getPath` has been changed to `Ember.Handlebars.get` for consistency.', Ember.Handlebars.get);
17497
17498 /**
17499   @private
17500
17501   Registers a helper in Handlebars that will be called if no property with the
17502   given name can be found on the current context object, and no helper with
17503   that name is registered.
17504
17505   This throws an exception with a more helpful error message so the user can
17506   track down where the problem is happening.
17507
17508   @method helperMissing
17509   @for Ember.Handlebars.helpers
17510   @param {String} path
17511   @param {Hash} options
17512 */
17513 Ember.Handlebars.registerHelper('helperMissing', function(path, options) {
17514   var error, view = "";
17515
17516   error = "%@ Handlebars error: Could not find property '%@' on object %@.";
17517   if (options.data){
17518     view = options.data.view;
17519   }
17520   throw new Ember.Error(Ember.String.fmt(error, [view, path, this]));
17521 });
17522
17523 /**
17524   Register a bound handlebars helper. Bound helpers behave similarly to regular
17525   handlebars helpers, with the added ability to re-render when the underlying data
17526   changes.
17527
17528   ## Simple example
17529
17530   ```javascript
17531   Ember.Handlebars.registerBoundHelper('capitalize', function(value) {
17532     return value.toUpperCase();
17533   });
17534   ```
17535
17536   The above bound helper can be used inside of templates as follows:
17537
17538   ```handlebars
17539   {{capitalize name}}
17540   ```
17541
17542   In this case, when the `name` property of the template's context changes,
17543   the rendered value of the helper will update to reflect this change.
17544
17545   ## Example with options
17546
17547   Like normal handlebars helpers, bound helpers have access to the options
17548   passed into the helper call.
17549
17550   ```javascript
17551   Ember.Handlebars.registerBoundHelper('repeat', function(value, options) {
17552     var count = options.hash.count;
17553     var a = [];
17554     while(a.length < count){
17555         a.push(value);
17556     }
17557     return a.join('');
17558   });
17559   ```
17560
17561   This helper could be used in a template as follows:
17562
17563   ```handlebars
17564   {{repeat text count=3}}
17565   ```
17566
17567   ## Example with extra dependencies
17568
17569   The `Ember.Handlebars.registerBoundHelper` method takes a variable length
17570   third parameter which indicates extra dependencies on the passed in value.
17571   This allows the handlebars helper to update when these dependencies change.
17572
17573   ```javascript
17574   Ember.Handlebars.registerBoundHelper('capitalizeName', function(value) {
17575     return value.get('name').toUpperCase();
17576   }, 'name');
17577   ```
17578
17579   @method registerBoundHelper
17580   @for Ember.Handlebars
17581   @param {String} name
17582   @param {Function} function
17583   @param {String} dependentKeys*
17584 */
17585 Ember.Handlebars.registerBoundHelper = function(name, fn) {
17586   var dependentKeys = Array.prototype.slice.call(arguments, 2);
17587   Ember.Handlebars.registerHelper(name, function(property, options) {
17588     var data = options.data,
17589       view = data.view,
17590       currentContext = (options.contexts && options.contexts[0]) || this,
17591       pathRoot, path, normalized,
17592       observer, loc;
17593
17594     normalized = Ember.Handlebars.normalizePath(currentContext, property, data);
17595
17596     pathRoot = normalized.root;
17597     path = normalized.path;
17598
17599     var bindView = new Ember._SimpleHandlebarsView(
17600       path, pathRoot, !options.hash.unescaped, options.data
17601     );
17602
17603     bindView.normalizedValue = function() {
17604       var value = Ember._SimpleHandlebarsView.prototype.normalizedValue.call(bindView);
17605       return fn.call(view, value, options);
17606     };
17607
17608     view.appendChild(bindView);
17609
17610     observer = function() {
17611       Ember.run.scheduleOnce('render', bindView, 'rerender');
17612     };
17613
17614     Ember.addObserver(pathRoot, path, observer);
17615     loc = 0;
17616     while(loc < dependentKeys.length) {
17617       Ember.addObserver(pathRoot, path + '.' + dependentKeys[loc], observer);
17618       loc += 1;
17619     }
17620
17621     view.one('willClearRender', function() {
17622       Ember.removeObserver(pathRoot, path, observer);
17623       loc = 0;
17624       while(loc < dependentKeys.length) {
17625         Ember.removeObserver(pathRoot, path + '.' + dependentKeys[loc], observer);
17626         loc += 1;
17627       }
17628     });
17629   });
17630 };
17631
17632 /**
17633   @private
17634
17635   Overrides Handlebars.template so that we can distinguish
17636   user-created, top-level templates from inner contexts.
17637
17638   @method template
17639   @for Ember.Handlebars
17640   @param {String} template spec
17641 */
17642 Ember.Handlebars.template = function(spec){
17643   var t = Handlebars.template(spec);
17644   t.isTop = true;
17645   return t;
17646 };
17647
17648
17649 })();
17650
17651
17652
17653 (function() {
17654 /**
17655   @method htmlSafe
17656   @for Ember.String
17657   @static
17658 */
17659 Ember.String.htmlSafe = function(str) {
17660   return new Handlebars.SafeString(str);
17661 };
17662
17663 var htmlSafe = Ember.String.htmlSafe;
17664
17665 if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {
17666
17667   /**
17668     See {{#crossLink "Ember.String/htmlSafe"}}{{/crossLink}}
17669
17670     @method htmlSafe
17671     @for String
17672   */
17673   String.prototype.htmlSafe = function() {
17674     return htmlSafe(this);
17675   };
17676 }
17677
17678 })();
17679
17680
17681
17682 (function() {
17683 Ember.Handlebars.resolvePaths = function(options) {
17684   var ret = [],
17685       contexts = options.contexts,
17686       roots = options.roots,
17687       data = options.data;
17688
17689   for (var i=0, l=contexts.length; i<l; i++) {
17690     ret.push( Ember.Handlebars.get(roots[i], contexts[i], { data: data }) );
17691   }
17692
17693   return ret;
17694 };
17695
17696 })();
17697
17698
17699
17700 (function() {
17701 /*jshint newcap:false*/
17702 /**
17703 @module ember
17704 @submodule ember-handlebars
17705 */
17706
17707 var set = Ember.set, get = Ember.get;
17708 var Metamorph = requireModule('metamorph');
17709
17710 // DOMManager should just abstract dom manipulation between jquery and metamorph
17711 var DOMManager = {
17712   remove: function(view) {
17713     view.morph.remove();
17714   },
17715
17716   prepend: function(view, html) {
17717     view.morph.prepend(html);
17718   },
17719
17720   after: function(view, html) {
17721     view.morph.after(html);
17722   },
17723
17724   html: function(view, html) {
17725     view.morph.html(html);
17726   },
17727
17728   // This is messed up.
17729   replace: function(view) {
17730     var morph = view.morph;
17731
17732     view.transitionTo('preRender');
17733
17734     Ember.run.schedule('render', this, function() {
17735       if (get(view, 'isDestroyed')) { return; }
17736
17737       view.clearRenderedChildren();
17738       var buffer = view.renderToBuffer();
17739
17740       view.invokeRecursively(function(view) {
17741         view.propertyDidChange('element');
17742       });
17743
17744       view.triggerRecursively('willInsertElement');
17745       morph.replaceWith(buffer.string());
17746       view.transitionTo('inDOM');
17747       view.triggerRecursively('didInsertElement');
17748     });
17749   },
17750
17751   empty: function(view) {
17752     view.morph.html("");
17753   }
17754 };
17755
17756 // The `morph` and `outerHTML` properties are internal only
17757 // and not observable.
17758
17759 /**
17760   @class _Metamorph
17761   @namespace Ember
17762   @extends Ember.Mixin
17763   @private
17764 */
17765 Ember._Metamorph = Ember.Mixin.create({
17766   isVirtual: true,
17767   tagName: '',
17768
17769   instrumentName: 'render.metamorph',
17770
17771   init: function() {
17772     this._super();
17773     this.morph = Metamorph();
17774   },
17775
17776   beforeRender: function(buffer) {
17777     buffer.push(this.morph.startTag());
17778     buffer.pushOpeningTag();
17779   },
17780
17781   afterRender: function(buffer) {
17782     buffer.pushClosingTag();
17783     buffer.push(this.morph.endTag());
17784   },
17785
17786   createElement: function() {
17787     var buffer = this.renderToBuffer();
17788     this.outerHTML = buffer.string();
17789     this.clearBuffer();
17790   },
17791
17792   domManager: DOMManager
17793 });
17794
17795 /**
17796   @class _MetamorphView
17797   @namespace Ember
17798   @extends Ember.View
17799   @uses Ember._Metamorph
17800   @private
17801 */
17802 Ember._MetamorphView = Ember.View.extend(Ember._Metamorph);
17803
17804 /**
17805   @class _SimpleMetamorphView
17806   @namespace Ember
17807   @extends Ember.View
17808   @uses Ember._Metamorph
17809   @private
17810 */
17811 Ember._SimpleMetamorphView = Ember.CoreView.extend(Ember._Metamorph);
17812
17813
17814 })();
17815
17816
17817
17818 (function() {
17819 /*globals Handlebars */
17820 /*jshint newcap:false*/
17821 /**
17822 @module ember
17823 @submodule ember-handlebars
17824 */
17825
17826 var get = Ember.get, set = Ember.set, handlebarsGet = Ember.Handlebars.get;
17827 var Metamorph = requireModule('metamorph');
17828 function SimpleHandlebarsView(path, pathRoot, isEscaped, templateData) {
17829   this.path = path;
17830   this.pathRoot = pathRoot;
17831   this.isEscaped = isEscaped;
17832   this.templateData = templateData;
17833
17834   this.morph = Metamorph();
17835   this.state = 'preRender';
17836   this.updateId = null;
17837 }
17838
17839 Ember._SimpleHandlebarsView = SimpleHandlebarsView;
17840
17841 SimpleHandlebarsView.prototype = {
17842   isVirtual: true,
17843   isView: true,
17844
17845   destroy: function () {
17846     if (this.updateId) {
17847       Ember.run.cancel(this.updateId);
17848       this.updateId = null;
17849     }
17850     this.morph = null;
17851   },
17852
17853   propertyDidChange: Ember.K,
17854
17855   normalizedValue: function() {
17856     var path = this.path,
17857         pathRoot = this.pathRoot,
17858         result, templateData;
17859
17860     // Use the pathRoot as the result if no path is provided. This
17861     // happens if the path is `this`, which gets normalized into
17862     // a `pathRoot` of the current Handlebars context and a path
17863     // of `''`.
17864     if (path === '') {
17865       result = pathRoot;
17866     } else {
17867       templateData = this.templateData;
17868       result = handlebarsGet(pathRoot, path, { data: templateData });
17869     }
17870
17871     return result;
17872   },
17873
17874   renderToBuffer: function(buffer) {
17875     var string = '';
17876
17877     string += this.morph.startTag();
17878     string += this.render();
17879     string += this.morph.endTag();
17880
17881     buffer.push(string);
17882   },
17883
17884   render: function() {
17885     // If not invoked via a triple-mustache ({{{foo}}}), escape
17886     // the content of the template.
17887     var escape = this.isEscaped;
17888     var result = this.normalizedValue();
17889
17890     if (result === null || result === undefined) {
17891       result = "";
17892     } else if (!(result instanceof Handlebars.SafeString)) {
17893       result = String(result);
17894     }
17895
17896     if (escape) { result = Handlebars.Utils.escapeExpression(result); }
17897     return result;
17898   },
17899
17900   rerender: function() {
17901     switch(this.state) {
17902       case 'preRender':
17903       case 'destroyed':
17904         break;
17905       case 'inBuffer':
17906         throw new Ember.Error("Something you did tried to replace an {{expression}} before it was inserted into the DOM.");
17907       case 'hasElement':
17908       case 'inDOM':
17909         this.updateId = Ember.run.scheduleOnce('render', this, 'update');
17910         break;
17911     }
17912
17913     return this;
17914   },
17915
17916   update: function () {
17917     this.updateId = null;
17918     this.morph.html(this.render());
17919   },
17920
17921   transitionTo: function(state) {
17922     this.state = state;
17923   }
17924 };
17925
17926 var states = Ember.View.cloneStates(Ember.View.states), merge = Ember.merge;
17927
17928 merge(states._default, {
17929   rerenderIfNeeded: Ember.K
17930 });
17931
17932 merge(states.inDOM, {
17933   rerenderIfNeeded: function(view) {
17934     if (get(view, 'normalizedValue') !== view._lastNormalizedValue) {
17935       view.rerender();
17936     }
17937   }
17938 });
17939
17940 /**
17941   `Ember._HandlebarsBoundView` is a private view created by the Handlebars
17942   `{{bind}}` helpers that is used to keep track of bound properties.
17943
17944   Every time a property is bound using a `{{mustache}}`, an anonymous subclass
17945   of `Ember._HandlebarsBoundView` is created with the appropriate sub-template
17946   and context set up. When the associated property changes, just the template
17947   for this view will re-render.
17948
17949   @class _HandlebarsBoundView
17950   @namespace Ember
17951   @extends Ember._MetamorphView
17952   @private
17953 */
17954 Ember._HandlebarsBoundView = Ember._MetamorphView.extend({
17955   instrumentName: 'render.boundHandlebars',
17956   states: states,
17957
17958   /**
17959     The function used to determine if the `displayTemplate` or
17960     `inverseTemplate` should be rendered. This should be a function that takes
17961     a value and returns a Boolean.
17962
17963     @property shouldDisplayFunc
17964     @type Function
17965     @default null
17966   */
17967   shouldDisplayFunc: null,
17968
17969   /**
17970     Whether the template rendered by this view gets passed the context object
17971     of its parent template, or gets passed the value of retrieving `path`
17972     from the `pathRoot`.
17973
17974     For example, this is true when using the `{{#if}}` helper, because the
17975     template inside the helper should look up properties relative to the same
17976     object as outside the block. This would be `false` when used with `{{#with
17977     foo}}` because the template should receive the object found by evaluating
17978     `foo`.
17979
17980     @property preserveContext
17981     @type Boolean
17982     @default false
17983   */
17984   preserveContext: false,
17985
17986   /**
17987     If `preserveContext` is true, this is the object that will be used
17988     to render the template.
17989
17990     @property previousContext
17991     @type Object
17992   */
17993   previousContext: null,
17994
17995   /**
17996     The template to render when `shouldDisplayFunc` evaluates to `true`.
17997
17998     @property displayTemplate
17999     @type Function
18000     @default null
18001   */
18002   displayTemplate: null,
18003
18004   /**
18005     The template to render when `shouldDisplayFunc` evaluates to `false`.
18006
18007     @property inverseTemplate
18008     @type Function
18009     @default null
18010   */
18011   inverseTemplate: null,
18012
18013
18014   /**
18015     The path to look up on `pathRoot` that is passed to
18016     `shouldDisplayFunc` to determine which template to render.
18017
18018     In addition, if `preserveContext` is `false,` the object at this path will
18019     be passed to the template when rendering.
18020
18021     @property path
18022     @type String
18023     @default null
18024   */
18025   path: null,
18026
18027   /**
18028     The object from which the `path` will be looked up. Sometimes this is the
18029     same as the `previousContext`, but in cases where this view has been
18030     generated for paths that start with a keyword such as `view` or
18031     `controller`, the path root will be that resolved object.
18032
18033     @property pathRoot
18034     @type Object
18035   */
18036   pathRoot: null,
18037
18038   normalizedValue: Ember.computed(function() {
18039     var path = get(this, 'path'),
18040         pathRoot  = get(this, 'pathRoot'),
18041         valueNormalizer = get(this, 'valueNormalizerFunc'),
18042         result, templateData;
18043
18044     // Use the pathRoot as the result if no path is provided. This
18045     // happens if the path is `this`, which gets normalized into
18046     // a `pathRoot` of the current Handlebars context and a path
18047     // of `''`.
18048     if (path === '') {
18049       result = pathRoot;
18050     } else {
18051       templateData = get(this, 'templateData');
18052       result = handlebarsGet(pathRoot, path, { data: templateData });
18053     }
18054
18055     return valueNormalizer ? valueNormalizer(result) : result;
18056   }).property('path', 'pathRoot', 'valueNormalizerFunc').volatile(),
18057
18058   rerenderIfNeeded: function() {
18059     this.currentState.rerenderIfNeeded(this);
18060   },
18061
18062   /**
18063     Determines which template to invoke, sets up the correct state based on
18064     that logic, then invokes the default `Ember.View` `render` implementation.
18065
18066     This method will first look up the `path` key on `pathRoot`,
18067     then pass that value to the `shouldDisplayFunc` function. If that returns
18068     `true,` the `displayTemplate` function will be rendered to DOM. Otherwise,
18069     `inverseTemplate`, if specified, will be rendered.
18070
18071     For example, if this `Ember._HandlebarsBoundView` represented the `{{#with
18072     foo}}` helper, it would look up the `foo` property of its context, and
18073     `shouldDisplayFunc` would always return true. The object found by looking
18074     up `foo` would be passed to `displayTemplate`.
18075
18076     @method render
18077     @param {Ember.RenderBuffer} buffer
18078   */
18079   render: function(buffer) {
18080     // If not invoked via a triple-mustache ({{{foo}}}), escape
18081     // the content of the template.
18082     var escape = get(this, 'isEscaped');
18083
18084     var shouldDisplay = get(this, 'shouldDisplayFunc'),
18085         preserveContext = get(this, 'preserveContext'),
18086         context = get(this, 'previousContext');
18087
18088     var inverseTemplate = get(this, 'inverseTemplate'),
18089         displayTemplate = get(this, 'displayTemplate');
18090
18091     var result = get(this, 'normalizedValue');
18092     this._lastNormalizedValue = result;
18093
18094     // First, test the conditional to see if we should
18095     // render the template or not.
18096     if (shouldDisplay(result)) {
18097       set(this, 'template', displayTemplate);
18098
18099       // If we are preserving the context (for example, if this
18100       // is an #if block, call the template with the same object.
18101       if (preserveContext) {
18102         set(this, '_context', context);
18103       } else {
18104       // Otherwise, determine if this is a block bind or not.
18105       // If so, pass the specified object to the template
18106         if (displayTemplate) {
18107           set(this, '_context', result);
18108         } else {
18109         // This is not a bind block, just push the result of the
18110         // expression to the render context and return.
18111           if (result === null || result === undefined) {
18112             result = "";
18113           } else if (!(result instanceof Handlebars.SafeString)) {
18114             result = String(result);
18115           }
18116
18117           if (escape) { result = Handlebars.Utils.escapeExpression(result); }
18118           buffer.push(result);
18119           return;
18120         }
18121       }
18122     } else if (inverseTemplate) {
18123       set(this, 'template', inverseTemplate);
18124
18125       if (preserveContext) {
18126         set(this, '_context', context);
18127       } else {
18128         set(this, '_context', result);
18129       }
18130     } else {
18131       set(this, 'template', function() { return ''; });
18132     }
18133
18134     return this._super(buffer);
18135   }
18136 });
18137
18138 })();
18139
18140
18141
18142 (function() {
18143 /**
18144 @module ember
18145 @submodule ember-handlebars
18146 */
18147
18148 var get = Ember.get, set = Ember.set, fmt = Ember.String.fmt;
18149 var handlebarsGet = Ember.Handlebars.get, normalizePath = Ember.Handlebars.normalizePath;
18150 var forEach = Ember.ArrayPolyfills.forEach;
18151
18152 var EmberHandlebars = Ember.Handlebars, helpers = EmberHandlebars.helpers;
18153
18154 // Binds a property into the DOM. This will create a hook in DOM that the
18155 // KVO system will look for and update if the property changes.
18156 function bind(property, options, preserveContext, shouldDisplay, valueNormalizer) {
18157   var data = options.data,
18158       fn = options.fn,
18159       inverse = options.inverse,
18160       view = data.view,
18161       currentContext = this,
18162       pathRoot, path, normalized,
18163       observer;
18164
18165   normalized = normalizePath(currentContext, property, data);
18166
18167   pathRoot = normalized.root;
18168   path = normalized.path;
18169
18170   // Set up observers for observable objects
18171   if ('object' === typeof this) {
18172     if (data.insideGroup) {
18173       observer = function() {
18174         Ember.run.once(view, 'rerender');
18175       };
18176
18177       var template, context, result = handlebarsGet(pathRoot, path, options);
18178
18179       result = valueNormalizer(result);
18180
18181       context = preserveContext ? currentContext : result;
18182       if (shouldDisplay(result)) {
18183         template = fn;
18184       } else if (inverse) {
18185         template = inverse;
18186       }
18187
18188       template(context, { data: options.data });
18189     } else {
18190       // Create the view that will wrap the output of this template/property
18191       // and add it to the nearest view's childViews array.
18192       // See the documentation of Ember._HandlebarsBoundView for more.
18193       var bindView = view.createChildView(Ember._HandlebarsBoundView, {
18194         preserveContext: preserveContext,
18195         shouldDisplayFunc: shouldDisplay,
18196         valueNormalizerFunc: valueNormalizer,
18197         displayTemplate: fn,
18198         inverseTemplate: inverse,
18199         path: path,
18200         pathRoot: pathRoot,
18201         previousContext: currentContext,
18202         isEscaped: !options.hash.unescaped,
18203         templateData: options.data
18204       });
18205
18206       view.appendChild(bindView);
18207
18208       observer = function() {
18209         Ember.run.scheduleOnce('render', bindView, 'rerenderIfNeeded');
18210       };
18211     }
18212
18213     // Observes the given property on the context and
18214     // tells the Ember._HandlebarsBoundView to re-render. If property
18215     // is an empty string, we are printing the current context
18216     // object ({{this}}) so updating it is not our responsibility.
18217     if (path !== '') {
18218       Ember.addObserver(pathRoot, path, observer);
18219
18220       view.one('willClearRender', function() {
18221         Ember.removeObserver(pathRoot, path, observer);
18222       });
18223     }
18224   } else {
18225     // The object is not observable, so just render it out and
18226     // be done with it.
18227     data.buffer.push(handlebarsGet(pathRoot, path, options));
18228   }
18229 }
18230
18231 function simpleBind(property, options) {
18232   var data = options.data,
18233       view = data.view,
18234       currentContext = this,
18235       pathRoot, path, normalized,
18236       observer;
18237
18238   normalized = normalizePath(currentContext, property, data);
18239
18240   pathRoot = normalized.root;
18241   path = normalized.path;
18242
18243   // Set up observers for observable objects
18244   if ('object' === typeof this) {
18245     if (data.insideGroup) {
18246       observer = function() {
18247         Ember.run.once(view, 'rerender');
18248       };
18249
18250       var result = handlebarsGet(pathRoot, path, options);
18251       if (result === null || result === undefined) { result = ""; }
18252       data.buffer.push(result);
18253     } else {
18254       var bindView = new Ember._SimpleHandlebarsView(
18255         path, pathRoot, !options.hash.unescaped, options.data
18256       );
18257
18258       bindView._parentView = view;
18259       view.appendChild(bindView);
18260
18261       observer = function() {
18262         Ember.run.scheduleOnce('render', bindView, 'rerender');
18263       };
18264     }
18265
18266     // Observes the given property on the context and
18267     // tells the Ember._HandlebarsBoundView to re-render. If property
18268     // is an empty string, we are printing the current context
18269     // object ({{this}}) so updating it is not our responsibility.
18270     if (path !== '') {
18271       Ember.addObserver(pathRoot, path, observer);
18272
18273       view.one('willClearRender', function() {
18274         Ember.removeObserver(pathRoot, path, observer);
18275       });
18276     }
18277   } else {
18278     // The object is not observable, so just render it out and
18279     // be done with it.
18280     data.buffer.push(handlebarsGet(pathRoot, path, options));
18281   }
18282 }
18283
18284 /**
18285   @private
18286
18287   '_triageMustache' is used internally select between a binding and helper for
18288   the given context. Until this point, it would be hard to determine if the
18289   mustache is a property reference or a regular helper reference. This triage
18290   helper resolves that.
18291
18292   This would not be typically invoked by directly.
18293
18294   @method _triageMustache
18295   @for Ember.Handlebars.helpers
18296   @param {String} property Property/helperID to triage
18297   @param {Function} fn Context to provide for rendering
18298   @return {String} HTML string
18299 */
18300 EmberHandlebars.registerHelper('_triageMustache', function(property, fn) {
18301   Ember.assert("You cannot pass more than one argument to the _triageMustache helper", arguments.length <= 2);
18302   if (helpers[property]) {
18303     return helpers[property].call(this, fn);
18304   }
18305   else {
18306     return helpers.bind.apply(this, arguments);
18307   }
18308 });
18309
18310 /**
18311   @private
18312
18313   `bind` can be used to display a value, then update that value if it
18314   changes. For example, if you wanted to print the `title` property of
18315   `content`:
18316
18317   ```handlebars
18318   {{bind "content.title"}}
18319   ```
18320
18321   This will return the `title` property as a string, then create a new observer
18322   at the specified path. If it changes, it will update the value in DOM. Note
18323   that if you need to support IE7 and IE8 you must modify the model objects
18324   properties using `Ember.get()` and `Ember.set()` for this to work as it
18325   relies on Ember's KVO system. For all other browsers this will be handled for
18326   you automatically.
18327
18328   @method bind
18329   @for Ember.Handlebars.helpers
18330   @param {String} property Property to bind
18331   @param {Function} fn Context to provide for rendering
18332   @return {String} HTML string
18333 */
18334 EmberHandlebars.registerHelper('bind', function(property, options) {
18335   Ember.assert("You cannot pass more than one argument to the bind helper", arguments.length <= 2);
18336
18337   var context = (options.contexts && options.contexts[0]) || this;
18338
18339   if (!options.fn) {
18340     return simpleBind.call(context, property, options);
18341   }
18342
18343   return bind.call(context, property, options, false, function(result) {
18344     return !Ember.isNone(result);
18345   });
18346 });
18347
18348 /**
18349   @private
18350
18351   Use the `boundIf` helper to create a conditional that re-evaluates
18352   whenever the truthiness of the bound value changes.
18353
18354   ```handlebars
18355   {{#boundIf "content.shouldDisplayTitle"}}
18356     {{content.title}}
18357   {{/boundIf}}
18358   ```
18359
18360   @method boundIf
18361   @for Ember.Handlebars.helpers
18362   @param {String} property Property to bind
18363   @param {Function} fn Context to provide for rendering
18364   @return {String} HTML string
18365 */
18366 EmberHandlebars.registerHelper('boundIf', function(property, fn) {
18367   var context = (fn.contexts && fn.contexts[0]) || this;
18368   var func = function(result) {
18369     if (Ember.typeOf(result) === 'array') {
18370       return get(result, 'length') !== 0;
18371     } else {
18372       return !!result;
18373     }
18374   };
18375
18376   return bind.call(context, property, fn, true, func, func);
18377 });
18378
18379 /**
18380   @method with
18381   @for Ember.Handlebars.helpers
18382   @param {Function} context
18383   @param {Hash} options
18384   @return {String} HTML string
18385 */
18386 EmberHandlebars.registerHelper('with', function(context, options) {
18387   if (arguments.length === 4) {
18388     var keywordName, path, rootPath, normalized;
18389
18390     Ember.assert("If you pass more than one argument to the with helper, it must be in the form #with foo as bar", arguments[1] === "as");
18391     options = arguments[3];
18392     keywordName = arguments[2];
18393     path = arguments[0];
18394
18395     Ember.assert("You must pass a block to the with helper", options.fn && options.fn !== Handlebars.VM.noop);
18396
18397     if (Ember.isGlobalPath(path)) {
18398       Ember.bind(options.data.keywords, keywordName, path);
18399     } else {
18400       normalized = normalizePath(this, path, options.data);
18401       path = normalized.path;
18402       rootPath = normalized.root;
18403
18404       // This is a workaround for the fact that you cannot bind separate objects
18405       // together. When we implement that functionality, we should use it here.
18406       var contextKey = Ember.$.expando + Ember.guidFor(rootPath);
18407       options.data.keywords[contextKey] = rootPath;
18408
18409       // if the path is '' ("this"), just bind directly to the current context
18410       var contextPath = path ? contextKey + '.' + path : contextKey;
18411       Ember.bind(options.data.keywords, keywordName, contextPath);
18412     }
18413
18414     return bind.call(this, path, options, true, function(result) {
18415       return !Ember.isNone(result);
18416     });
18417   } else {
18418     Ember.assert("You must pass exactly one argument to the with helper", arguments.length === 2);
18419     Ember.assert("You must pass a block to the with helper", options.fn && options.fn !== Handlebars.VM.noop);
18420     return helpers.bind.call(options.contexts[0], context, options);
18421   }
18422 });
18423
18424
18425 /**
18426   See `boundIf`
18427
18428   @method if
18429   @for Ember.Handlebars.helpers
18430   @param {Function} context
18431   @param {Hash} options
18432   @return {String} HTML string
18433 */
18434 EmberHandlebars.registerHelper('if', function(context, options) {
18435   Ember.assert("You must pass exactly one argument to the if helper", arguments.length === 2);
18436   Ember.assert("You must pass a block to the if helper", options.fn && options.fn !== Handlebars.VM.noop);
18437
18438   return helpers.boundIf.call(options.contexts[0], context, options);
18439 });
18440
18441 /**
18442   @method unless
18443   @for Ember.Handlebars.helpers
18444   @param {Function} context
18445   @param {Hash} options
18446   @return {String} HTML string
18447 */
18448 EmberHandlebars.registerHelper('unless', function(context, options) {
18449   Ember.assert("You must pass exactly one argument to the unless helper", arguments.length === 2);
18450   Ember.assert("You must pass a block to the unless helper", options.fn && options.fn !== Handlebars.VM.noop);
18451
18452   var fn = options.fn, inverse = options.inverse;
18453
18454   options.fn = inverse;
18455   options.inverse = fn;
18456
18457   return helpers.boundIf.call(options.contexts[0], context, options);
18458 });
18459
18460 /**
18461   `bindAttr` allows you to create a binding between DOM element attributes and
18462   Ember objects. For example:
18463
18464   ```handlebars
18465   <img {{bindAttr src="imageUrl" alt="imageTitle"}}>
18466   ```
18467
18468   The above handlebars template will fill the `<img>`'s `src` attribute will
18469   the value of the property referenced with `"imageUrl"` and its `alt`
18470   attribute with the value of the property referenced with `"imageTitle"`.
18471
18472   If the rendering context of this template is the following object:
18473
18474   ```javascript
18475   {
18476     imageUrl: 'http://lolcats.info/haz-a-funny',
18477     imageTitle: 'A humorous image of a cat'
18478   }
18479   ```
18480
18481   The resulting HTML output will be:
18482
18483   ```html
18484   <img src="http://lolcats.info/haz-a-funny" alt="A humorous image of a cat">
18485   ```
18486
18487   `bindAttr` cannot redeclare existing DOM element attributes. The use of `src`
18488   in the following `bindAttr` example will be ignored and the hard coded value
18489   of `src="/failwhale.gif"` will take precedence:
18490
18491   ```handlebars
18492   <img src="/failwhale.gif" {{bindAttr src="imageUrl" alt="imageTitle"}}>
18493   ```
18494
18495   ### `bindAttr` and the `class` attribute
18496
18497   `bindAttr` supports a special syntax for handling a number of cases unique
18498   to the `class` DOM element attribute. The `class` attribute combines
18499   multiple discreet values into a single attribute as a space-delimited
18500   list of strings. Each string can be:
18501
18502   * a string return value of an object's property.
18503   * a boolean return value of an object's property
18504   * a hard-coded value
18505
18506   A string return value works identically to other uses of `bindAttr`. The
18507   return value of the property will become the value of the attribute. For
18508   example, the following view and template:
18509
18510   ```javascript
18511     AView = Ember.View.extend({
18512       someProperty: function(){
18513         return "aValue";
18514       }.property()
18515     })
18516   ```
18517
18518   ```handlebars
18519   <img {{bindAttr class="view.someProperty}}>
18520   ```
18521
18522   Result in the following rendered output:
18523
18524   ```html 
18525   <img class="aValue">
18526   ```
18527
18528   A boolean return value will insert a specified class name if the property
18529   returns `true` and remove the class name if the property returns `false`.
18530
18531   A class name is provided via the syntax 
18532   `somePropertyName:class-name-if-true`.
18533
18534   ```javascript
18535   AView = Ember.View.extend({
18536     someBool: true
18537   })
18538   ```
18539
18540   ```handlebars
18541   <img {{bindAttr class="view.someBool:class-name-if-true"}}>
18542   ```
18543
18544   Result in the following rendered output:
18545
18546   ```html
18547   <img class="class-name-if-true">
18548   ```
18549
18550   An additional section of the binding can be provided if you want to
18551   replace the existing class instead of removing it when the boolean
18552   value changes:
18553
18554   ```handlebars
18555   <img {{bindAttr class="view.someBool:class-name-if-true:class-name-if-false"}}>
18556   ```
18557
18558   A hard-coded value can be used by prepending `:` to the desired
18559   class name: `:class-name-to-always-apply`.
18560
18561   ```handlebars
18562   <img {{bindAttr class=":class-name-to-always-apply"}}>
18563   ```
18564
18565   Results in the following rendered output:
18566
18567   ```html
18568   <img class=":class-name-to-always-apply">
18569   ```
18570
18571   All three strategies - string return value, boolean return value, and
18572   hard-coded value â€“ can be combined in a single declaration:
18573
18574   ```handlebars
18575   <img {{bindAttr class=":class-name-to-always-apply view.someBool:class-name-if-true view.someProperty"}}>
18576   ```
18577
18578   @method bindAttr
18579   @for Ember.Handlebars.helpers
18580   @param {Hash} options
18581   @return {String} HTML string
18582 */
18583 EmberHandlebars.registerHelper('bindAttr', function(options) {
18584
18585   var attrs = options.hash;
18586
18587   Ember.assert("You must specify at least one hash argument to bindAttr", !!Ember.keys(attrs).length);
18588
18589   var view = options.data.view;
18590   var ret = [];
18591   var ctx = this;
18592
18593   // Generate a unique id for this element. This will be added as a
18594   // data attribute to the element so it can be looked up when
18595   // the bound property changes.
18596   var dataId = ++Ember.uuid;
18597
18598   // Handle classes differently, as we can bind multiple classes
18599   var classBindings = attrs['class'];
18600   if (classBindings !== null && classBindings !== undefined) {
18601     var classResults = EmberHandlebars.bindClasses(this, classBindings, view, dataId, options);
18602
18603     ret.push('class="' + Handlebars.Utils.escapeExpression(classResults.join(' ')) + '"');
18604     delete attrs['class'];
18605   }
18606
18607   var attrKeys = Ember.keys(attrs);
18608
18609   // For each attribute passed, create an observer and emit the
18610   // current value of the property as an attribute.
18611   forEach.call(attrKeys, function(attr) {
18612     var path = attrs[attr],
18613         pathRoot, normalized;
18614
18615     Ember.assert(fmt("You must provide a String for a bound attribute, not %@", [path]), typeof path === 'string');
18616
18617     normalized = normalizePath(ctx, path, options.data);
18618
18619     pathRoot = normalized.root;
18620     path = normalized.path;
18621
18622     var value = (path === 'this') ? pathRoot : handlebarsGet(pathRoot, path, options),
18623         type = Ember.typeOf(value);
18624
18625     Ember.assert(fmt("Attributes must be numbers, strings or booleans, not %@", [value]), value === null || value === undefined || type === 'number' || type === 'string' || type === 'boolean');
18626
18627     var observer, invoker;
18628
18629     observer = function observer() {
18630       var result = handlebarsGet(pathRoot, path, options);
18631
18632       Ember.assert(fmt("Attributes must be numbers, strings or booleans, not %@", [result]), result === null || result === undefined || typeof result === 'number' || typeof result === 'string' || typeof result === 'boolean');
18633
18634       var elem = view.$("[data-bindattr-" + dataId + "='" + dataId + "']");
18635
18636       // If we aren't able to find the element, it means the element
18637       // to which we were bound has been removed from the view.
18638       // In that case, we can assume the template has been re-rendered
18639       // and we need to clean up the observer.
18640       if (!elem || elem.length === 0) {
18641         Ember.removeObserver(pathRoot, path, invoker);
18642         return;
18643       }
18644
18645       Ember.View.applyAttributeBindings(elem, attr, result);
18646     };
18647
18648     invoker = function() {
18649       Ember.run.scheduleOnce('render', observer);
18650     };
18651
18652     // Add an observer to the view for when the property changes.
18653     // When the observer fires, find the element using the
18654     // unique data id and update the attribute to the new value.
18655     if (path !== 'this') {
18656       Ember.addObserver(pathRoot, path, invoker);
18657
18658       view.one('willClearRender', function() {
18659         Ember.removeObserver(pathRoot, path, invoker);
18660       });
18661     }
18662
18663     // if this changes, also change the logic in ember-views/lib/views/view.js
18664     if ((type === 'string' || (type === 'number' && !isNaN(value)))) {
18665       ret.push(attr + '="' + Handlebars.Utils.escapeExpression(value) + '"');
18666     } else if (value && type === 'boolean') {
18667       // The developer controls the attr name, so it should always be safe
18668       ret.push(attr + '="' + attr + '"');
18669     }
18670   }, this);
18671
18672   // Add the unique identifier
18673   // NOTE: We use all lower-case since Firefox has problems with mixed case in SVG
18674   ret.push('data-bindattr-' + dataId + '="' + dataId + '"');
18675   return new EmberHandlebars.SafeString(ret.join(' '));
18676 });
18677
18678 /**
18679   @private
18680
18681   Helper that, given a space-separated string of property paths and a context,
18682   returns an array of class names. Calling this method also has the side
18683   effect of setting up observers at those property paths, such that if they
18684   change, the correct class name will be reapplied to the DOM element.
18685
18686   For example, if you pass the string "fooBar", it will first look up the
18687   "fooBar" value of the context. If that value is true, it will add the
18688   "foo-bar" class to the current element (i.e., the dasherized form of
18689   "fooBar"). If the value is a string, it will add that string as the class.
18690   Otherwise, it will not add any new class name.
18691
18692   @method bindClasses
18693   @for Ember.Handlebars
18694   @param {Ember.Object} context The context from which to lookup properties
18695   @param {String} classBindings A string, space-separated, of class bindings 
18696     to use
18697   @param {Ember.View} view The view in which observers should look for the 
18698     element to update
18699   @param {Srting} bindAttrId Optional bindAttr id used to lookup elements
18700   @return {Array} An array of class names to add
18701 */
18702 EmberHandlebars.bindClasses = function(context, classBindings, view, bindAttrId, options) {
18703   var ret = [], newClass, value, elem;
18704
18705   // Helper method to retrieve the property from the context and
18706   // determine which class string to return, based on whether it is
18707   // a Boolean or not.
18708   var classStringForPath = function(root, parsedPath, options) {
18709     var val,
18710         path = parsedPath.path;
18711
18712     if (path === 'this') {
18713       val = root;
18714     } else if (path === '') {
18715       val = true;
18716     } else {
18717       val = handlebarsGet(root, path, options);
18718     }
18719
18720     return Ember.View._classStringForValue(path, val, parsedPath.className, parsedPath.falsyClassName);
18721   };
18722
18723   // For each property passed, loop through and setup
18724   // an observer.
18725   forEach.call(classBindings.split(' '), function(binding) {
18726
18727     // Variable in which the old class value is saved. The observer function
18728     // closes over this variable, so it knows which string to remove when
18729     // the property changes.
18730     var oldClass;
18731
18732     var observer, invoker;
18733
18734     var parsedPath = Ember.View._parsePropertyPath(binding),
18735         path = parsedPath.path,
18736         pathRoot = context,
18737         normalized;
18738
18739     if (path !== '' && path !== 'this') {
18740       normalized = normalizePath(context, path, options.data);
18741
18742       pathRoot = normalized.root;
18743       path = normalized.path;
18744     }
18745
18746     // Set up an observer on the context. If the property changes, toggle the
18747     // class name.
18748     observer = function() {
18749       // Get the current value of the property
18750       newClass = classStringForPath(pathRoot, parsedPath, options);
18751       elem = bindAttrId ? view.$("[data-bindattr-" + bindAttrId + "='" + bindAttrId + "']") : view.$();
18752
18753       // If we can't find the element anymore, a parent template has been
18754       // re-rendered and we've been nuked. Remove the observer.
18755       if (!elem || elem.length === 0) {
18756         Ember.removeObserver(pathRoot, path, invoker);
18757       } else {
18758         // If we had previously added a class to the element, remove it.
18759         if (oldClass) {
18760           elem.removeClass(oldClass);
18761         }
18762
18763         // If necessary, add a new class. Make sure we keep track of it so
18764         // it can be removed in the future.
18765         if (newClass) {
18766           elem.addClass(newClass);
18767           oldClass = newClass;
18768         } else {
18769           oldClass = null;
18770         }
18771       }
18772     };
18773
18774     invoker = function() {
18775       Ember.run.scheduleOnce('render', observer);
18776     };
18777
18778     if (path !== '' && path !== 'this') {
18779       Ember.addObserver(pathRoot, path, invoker);
18780
18781       view.one('willClearRender', function() {
18782         Ember.removeObserver(pathRoot, path, invoker);
18783       });
18784     }
18785
18786     // We've already setup the observer; now we just need to figure out the
18787     // correct behavior right now on the first pass through.
18788     value = classStringForPath(pathRoot, parsedPath, options);
18789
18790     if (value) {
18791       ret.push(value);
18792
18793       // Make sure we save the current value so that it can be removed if the
18794       // observer fires.
18795       oldClass = value;
18796     }
18797   });
18798
18799   return ret;
18800 };
18801
18802
18803 })();
18804
18805
18806
18807 (function() {
18808 /*globals Handlebars */
18809
18810 // TODO: Don't require the entire module
18811 /**
18812 @module ember
18813 @submodule ember-handlebars
18814 */
18815
18816 var get = Ember.get, set = Ember.set;
18817 var PARENT_VIEW_PATH = /^parentView\./;
18818 var EmberHandlebars = Ember.Handlebars;
18819
18820 EmberHandlebars.ViewHelper = Ember.Object.create({
18821
18822   propertiesFromHTMLOptions: function(options, thisContext) {
18823     var hash = options.hash, data = options.data;
18824     var extensions = {},
18825         classes = hash['class'],
18826         dup = false;
18827
18828     if (hash.id) {
18829       extensions.elementId = hash.id;
18830       dup = true;
18831     }
18832
18833     if (classes) {
18834       classes = classes.split(' ');
18835       extensions.classNames = classes;
18836       dup = true;
18837     }
18838
18839     if (hash.classBinding) {
18840       extensions.classNameBindings = hash.classBinding.split(' ');
18841       dup = true;
18842     }
18843
18844     if (hash.classNameBindings) {
18845       if (extensions.classNameBindings === undefined) extensions.classNameBindings = [];
18846       extensions.classNameBindings = extensions.classNameBindings.concat(hash.classNameBindings.split(' '));
18847       dup = true;
18848     }
18849
18850     if (hash.attributeBindings) {
18851       Ember.assert("Setting 'attributeBindings' via Handlebars is not allowed. Please subclass Ember.View and set it there instead.");
18852       extensions.attributeBindings = null;
18853       dup = true;
18854     }
18855
18856     if (dup) {
18857       hash = Ember.$.extend({}, hash);
18858       delete hash.id;
18859       delete hash['class'];
18860       delete hash.classBinding;
18861     }
18862
18863     // Set the proper context for all bindings passed to the helper. This applies to regular attribute bindings
18864     // as well as class name bindings. If the bindings are local, make them relative to the current context
18865     // instead of the view.
18866     var path;
18867
18868     // Evaluate the context of regular attribute bindings:
18869     for (var prop in hash) {
18870       if (!hash.hasOwnProperty(prop)) { continue; }
18871
18872       // Test if the property ends in "Binding"
18873       if (Ember.IS_BINDING.test(prop) && typeof hash[prop] === 'string') {
18874         path = this.contextualizeBindingPath(hash[prop], data);
18875         if (path) { hash[prop] = path; }
18876       }
18877     }
18878
18879     // Evaluate the context of class name bindings:
18880     if (extensions.classNameBindings) {
18881       for (var b in extensions.classNameBindings) {
18882         var full = extensions.classNameBindings[b];
18883         if (typeof full === 'string') {
18884           // Contextualize the path of classNameBinding so this:
18885           //
18886           //     classNameBinding="isGreen:green"
18887           //
18888           // is converted to this:
18889           //
18890           //     classNameBinding="_parentView.context.isGreen:green"
18891           var parsedPath = Ember.View._parsePropertyPath(full);
18892           path = this.contextualizeBindingPath(parsedPath.path, data);
18893           if (path) { extensions.classNameBindings[b] = path + parsedPath.classNames; }
18894         }
18895       }
18896     }
18897
18898     return Ember.$.extend(hash, extensions);
18899   },
18900
18901   // Transform bindings from the current context to a context that can be evaluated within the view.
18902   // Returns null if the path shouldn't be changed.
18903   //
18904   // TODO: consider the addition of a prefix that would allow this method to return `path`.
18905   contextualizeBindingPath: function(path, data) {
18906     var normalized = Ember.Handlebars.normalizePath(null, path, data);
18907     if (normalized.isKeyword) {
18908       return 'templateData.keywords.' + path;
18909     } else if (Ember.isGlobalPath(path)) {
18910       return null;
18911     } else if (path === 'this') {
18912       return '_parentView.context';
18913     } else {
18914       return '_parentView.context.' + path;
18915     }
18916   },
18917
18918   helper: function(thisContext, path, options) {
18919     var inverse = options.inverse,
18920         data = options.data,
18921         view = data.view,
18922         fn = options.fn,
18923         hash = options.hash,
18924         newView;
18925
18926     if ('string' === typeof path) {
18927       newView = EmberHandlebars.get(thisContext, path, options);
18928       Ember.assert("Unable to find view at path '" + path + "'", !!newView);
18929     } else {
18930       newView = path;
18931     }
18932
18933     Ember.assert(Ember.String.fmt('You must pass a view to the #view helper, not %@ (%@)', [path, newView]), Ember.View.detect(newView) || Ember.View.detectInstance(newView));
18934
18935     var viewOptions = this.propertiesFromHTMLOptions(options, thisContext);
18936     var currentView = data.view;
18937     viewOptions.templateData = options.data;
18938     var newViewProto = newView.proto ? newView.proto() : newView;
18939
18940     if (fn) {
18941       Ember.assert("You cannot provide a template block if you also specified a templateName", !get(viewOptions, 'templateName') && !get(newViewProto, 'templateName'));
18942       viewOptions.template = fn;
18943     }
18944
18945     // We only want to override the `_context` computed property if there is
18946     // no specified controller. See View#_context for more information.
18947     if (!newViewProto.controller && !newViewProto.controllerBinding && !viewOptions.controller && !viewOptions.controllerBinding) {
18948       viewOptions._context = thisContext;
18949     }
18950
18951     currentView.appendChild(newView, viewOptions);
18952   }
18953 });
18954
18955 /**
18956   `{{view}}` inserts a new instance of `Ember.View` into a template passing its
18957   options to the `Ember.View`'s `create` method and using the supplied block as
18958   the view's own template.
18959
18960   An empty `<body>` and the following template:
18961
18962   ```handlebars
18963   A span:
18964   {{#view tagName="span"}}
18965     hello.
18966   {{/view}}
18967   ```
18968
18969   Will result in HTML structure:
18970
18971   ```html
18972   <body>
18973     <!-- Note: the handlebars template script
18974          also results in a rendered Ember.View
18975          which is the outer <div> here -->
18976
18977     <div class="ember-view">
18978       A span:
18979       <span id="ember1" class="ember-view">
18980         Hello.
18981       </span>
18982     </div>
18983   </body>
18984   ```
18985
18986   ### `parentView` setting
18987
18988   The `parentView` property of the new `Ember.View` instance created through
18989   `{{view}}` will be set to the `Ember.View` instance of the template where
18990   `{{view}}` was called.
18991
18992   ```javascript
18993   aView = Ember.View.create({
18994     template: Ember.Handlebars.compile("{{#view}} my parent: {{parentView.elementId}} {{/view}}")
18995   });
18996
18997   aView.appendTo('body');
18998   ```
18999
19000   Will result in HTML structure:
19001
19002   ```html
19003   <div id="ember1" class="ember-view">
19004     <div id="ember2" class="ember-view">
19005       my parent: ember1
19006     </div>
19007   </div>
19008   ```
19009
19010   ### Setting CSS id and class attributes
19011
19012   The HTML `id` attribute can be set on the `{{view}}`'s resulting element with
19013   the `id` option. This option will _not_ be passed to `Ember.View.create`.
19014
19015   ```handlebars
19016   {{#view tagName="span" id="a-custom-id"}}
19017     hello.
19018   {{/view}}
19019   ```
19020
19021   Results in the following HTML structure:
19022
19023   ```html
19024   <div class="ember-view">
19025     <span id="a-custom-id" class="ember-view">
19026       hello.
19027     </span>
19028   </div>
19029   ```
19030
19031   The HTML `class` attribute can be set on the `{{view}}`'s resulting element
19032   with the `class` or `classNameBindings` options. The `class` option will
19033   directly set the CSS `class` attribute and will not be passed to
19034   `Ember.View.create`. `classNameBindings` will be passed to `create` and use
19035   `Ember.View`'s class name binding functionality:
19036
19037   ```handlebars
19038   {{#view tagName="span" class="a-custom-class"}}
19039     hello.
19040   {{/view}}
19041   ```
19042
19043   Results in the following HTML structure:
19044
19045   ```html
19046   <div class="ember-view">
19047     <span id="ember2" class="ember-view a-custom-class">
19048       hello.
19049     </span>
19050   </div>
19051   ```
19052
19053   ### Supplying a different view class
19054
19055   `{{view}}` can take an optional first argument before its supplied options to
19056   specify a path to a custom view class.
19057
19058   ```handlebars
19059   {{#view "MyApp.CustomView"}}
19060     hello.
19061   {{/view}}
19062   ```
19063
19064   The first argument can also be a relative path. Ember will search for the
19065   view class starting at the `Ember.View` of the template where `{{view}}` was
19066   used as the root object:
19067
19068   ```javascript
19069   MyApp = Ember.Application.create({});
19070   MyApp.OuterView = Ember.View.extend({
19071     innerViewClass: Ember.View.extend({
19072       classNames: ['a-custom-view-class-as-property']
19073     }),
19074     template: Ember.Handlebars.compile('{{#view "innerViewClass"}} hi {{/view}}')
19075   });
19076
19077   MyApp.OuterView.create().appendTo('body');
19078   ```
19079
19080   Will result in the following HTML:
19081
19082   ```html
19083   <div id="ember1" class="ember-view">
19084     <div id="ember2" class="ember-view a-custom-view-class-as-property">
19085       hi
19086     </div>
19087   </div>
19088   ```
19089
19090   ### Blockless use
19091
19092   If you supply a custom `Ember.View` subclass that specifies its own template
19093   or provide a `templateName` option to `{{view}}` it can be used without
19094   supplying a block. Attempts to use both a `templateName` option and supply a
19095   block will throw an error.
19096
19097   ```handlebars
19098   {{view "MyApp.ViewWithATemplateDefined"}}
19099   ```
19100
19101   ### `viewName` property
19102
19103   You can supply a `viewName` option to `{{view}}`. The `Ember.View` instance
19104   will be referenced as a property of its parent view by this name.
19105
19106   ```javascript
19107   aView = Ember.View.create({
19108     template: Ember.Handlebars.compile('{{#view viewName="aChildByName"}} hi {{/view}}')
19109   });
19110
19111   aView.appendTo('body');
19112   aView.get('aChildByName') // the instance of Ember.View created by {{view}} helper
19113   ```
19114
19115   @method view
19116   @for Ember.Handlebars.helpers
19117   @param {String} path
19118   @param {Hash} options
19119   @return {String} HTML string
19120 */
19121 EmberHandlebars.registerHelper('view', function(path, options) {
19122   Ember.assert("The view helper only takes a single argument", arguments.length <= 2);
19123
19124   // If no path is provided, treat path param as options.
19125   if (path && path.data && path.data.isRenderData) {
19126     options = path;
19127     path = "Ember.View";
19128   }
19129
19130   return EmberHandlebars.ViewHelper.helper(this, path, options);
19131 });
19132
19133
19134 })();
19135
19136
19137
19138 (function() {
19139 /*globals Handlebars */
19140
19141 // TODO: Don't require all of this module
19142 /**
19143 @module ember
19144 @submodule ember-handlebars
19145 */
19146
19147 var get = Ember.get, handlebarsGet = Ember.Handlebars.get, fmt = Ember.String.fmt;
19148
19149 /**
19150   `{{collection}}` is a `Ember.Handlebars` helper for adding instances of
19151   `Ember.CollectionView` to a template. See `Ember.CollectionView` for
19152   additional information on how a `CollectionView` functions.
19153
19154   `{{collection}}`'s primary use is as a block helper with a `contentBinding`
19155   option pointing towards an `Ember.Array`-compatible object. An `Ember.View`
19156   instance will be created for each item in its `content` property. Each view
19157   will have its own `content` property set to the appropriate item in the
19158   collection.
19159
19160   The provided block will be applied as the template for each item's view.
19161
19162   Given an empty `<body>` the following template:
19163
19164   ```handlebars
19165   {{#collection contentBinding="App.items"}}
19166     Hi {{view.content.name}}
19167   {{/collection}}
19168   ```
19169
19170   And the following application code
19171
19172   ```javascript
19173   App = Ember.Application.create()
19174   App.items = [
19175     Ember.Object.create({name: 'Dave'}),
19176     Ember.Object.create({name: 'Mary'}),
19177     Ember.Object.create({name: 'Sara'})
19178   ]
19179   ```
19180
19181   Will result in the HTML structure below
19182
19183   ```html
19184   <div class="ember-view">
19185     <div class="ember-view">Hi Dave</div>
19186     <div class="ember-view">Hi Mary</div>
19187     <div class="ember-view">Hi Sara</div>
19188   </div>
19189   ```
19190
19191   ### Blockless Use
19192
19193   If you provide an `itemViewClass` option that has its own `template` you can
19194   omit the block.
19195
19196   The following template:
19197
19198   ```handlebars
19199   {{collection contentBinding="App.items" itemViewClass="App.AnItemView"}}
19200   ```
19201
19202   And application code
19203
19204   ```javascript
19205   App = Ember.Application.create();
19206   App.items = [
19207     Ember.Object.create({name: 'Dave'}),
19208     Ember.Object.create({name: 'Mary'}),
19209     Ember.Object.create({name: 'Sara'})
19210   ];
19211
19212   App.AnItemView = Ember.View.extend({
19213     template: Ember.Handlebars.compile("Greetings {{view.content.name}}")
19214   });
19215   ```
19216
19217   Will result in the HTML structure below
19218
19219   ```html
19220   <div class="ember-view">
19221     <div class="ember-view">Greetings Dave</div>
19222     <div class="ember-view">Greetings Mary</div>
19223     <div class="ember-view">Greetings Sara</div>
19224   </div>
19225   ```
19226
19227   ### Specifying a CollectionView subclass
19228
19229   By default the `{{collection}}` helper will create an instance of
19230   `Ember.CollectionView`. You can supply a `Ember.CollectionView` subclass to
19231   the helper by passing it as the first argument:
19232
19233   ```handlebars
19234   {{#collection App.MyCustomCollectionClass contentBinding="App.items"}}
19235     Hi {{view.content.name}}
19236   {{/collection}}
19237   ```
19238
19239   ### Forwarded `item.*`-named Options
19240
19241   As with the `{{view}}`, helper options passed to the `{{collection}}` will be
19242   set on the resulting `Ember.CollectionView` as properties. Additionally,
19243   options prefixed with `item` will be applied to the views rendered for each
19244   item (note the camelcasing):
19245
19246   ```handlebars
19247   {{#collection contentBinding="App.items"
19248                 itemTagName="p"
19249                 itemClassNames="greeting"}}
19250     Howdy {{view.content.name}}
19251   {{/collection}}
19252   ```
19253
19254   Will result in the following HTML structure:
19255
19256   ```html
19257   <div class="ember-view">
19258     <p class="ember-view greeting">Howdy Dave</p>
19259     <p class="ember-view greeting">Howdy Mary</p>
19260     <p class="ember-view greeting">Howdy Sara</p>
19261   </div>
19262   ```
19263
19264   @method collection
19265   @for Ember.Handlebars.helpers
19266   @param {String} path
19267   @param {Hash} options
19268   @return {String} HTML string
19269   @deprecated Use `{{each}}` helper instead.
19270 */
19271 Ember.Handlebars.registerHelper('collection', function(path, options) {
19272   Ember.deprecate("Using the {{collection}} helper without specifying a class has been deprecated as the {{each}} helper now supports the same functionality.", path !== 'collection');
19273
19274   // If no path is provided, treat path param as options.
19275   if (path && path.data && path.data.isRenderData) {
19276     options = path;
19277     path = undefined;
19278     Ember.assert("You cannot pass more than one argument to the collection helper", arguments.length === 1);
19279   } else {
19280     Ember.assert("You cannot pass more than one argument to the collection helper", arguments.length === 2);
19281   }
19282
19283   var fn = options.fn;
19284   var data = options.data;
19285   var inverse = options.inverse;
19286   var view = options.data.view;
19287
19288   // If passed a path string, convert that into an object.
19289   // Otherwise, just default to the standard class.
19290   var collectionClass;
19291   collectionClass = path ? handlebarsGet(this, path, options) : Ember.CollectionView;
19292   Ember.assert(fmt("%@ #collection: Could not find collection class %@", [data.view, path]), !!collectionClass);
19293
19294   var hash = options.hash, itemHash = {}, match;
19295
19296   // Extract item view class if provided else default to the standard class
19297   var itemViewClass, itemViewPath = hash.itemViewClass;
19298   var collectionPrototype = collectionClass.proto();
19299   delete hash.itemViewClass;
19300   itemViewClass = itemViewPath ? handlebarsGet(collectionPrototype, itemViewPath, options) : collectionPrototype.itemViewClass;
19301   Ember.assert(fmt("%@ #collection: Could not find itemViewClass %@", [data.view, itemViewPath]), !!itemViewClass);
19302
19303   // Go through options passed to the {{collection}} helper and extract options
19304   // that configure item views instead of the collection itself.
19305   for (var prop in hash) {
19306     if (hash.hasOwnProperty(prop)) {
19307       match = prop.match(/^item(.)(.*)$/);
19308
19309       if(match) {
19310         // Convert itemShouldFoo -> shouldFoo
19311         itemHash[match[1].toLowerCase() + match[2]] = hash[prop];
19312         // Delete from hash as this will end up getting passed to the
19313         // {{view}} helper method.
19314         delete hash[prop];
19315       }
19316     }
19317   }
19318
19319   var tagName = hash.tagName || collectionPrototype.tagName;
19320
19321   if (fn) {
19322     itemHash.template = fn;
19323     delete options.fn;
19324   }
19325
19326   var emptyViewClass;
19327   if (inverse && inverse !== Handlebars.VM.noop) {
19328     emptyViewClass = get(collectionPrototype, 'emptyViewClass');
19329     emptyViewClass = emptyViewClass.extend({
19330           template: inverse,
19331           tagName: itemHash.tagName
19332     });
19333   } else if (hash.emptyViewClass) {
19334     emptyViewClass = handlebarsGet(this, hash.emptyViewClass, options);
19335   }
19336   hash.emptyView = emptyViewClass;
19337
19338   if (hash.eachHelper === 'each') {
19339     itemHash._context = Ember.computed(function() {
19340       return get(this, 'content');
19341     }).property('content');
19342     delete hash.eachHelper;
19343   }
19344
19345   var viewString = view.toString();
19346
19347   var viewOptions = Ember.Handlebars.ViewHelper.propertiesFromHTMLOptions({ data: data, hash: itemHash }, this);
19348   hash.itemViewClass = itemViewClass.extend(viewOptions);
19349
19350   return Ember.Handlebars.helpers.view.call(this, collectionClass, options);
19351 });
19352
19353
19354 })();
19355
19356
19357
19358 (function() {
19359 /*globals Handlebars */
19360 /**
19361 @module ember
19362 @submodule ember-handlebars
19363 */
19364
19365 var handlebarsGet = Ember.Handlebars.get;
19366
19367 /**
19368   `unbound` allows you to output a property without binding. *Important:* The
19369   output will not be updated if the property changes. Use with caution.
19370
19371   ```handlebars
19372   <div>{{unbound somePropertyThatDoesntChange}}</div>
19373   ```
19374
19375   @method unbound
19376   @for Ember.Handlebars.helpers
19377   @param {String} property
19378   @return {String} HTML string
19379 */
19380 Ember.Handlebars.registerHelper('unbound', function(property, fn) {
19381   var context = (fn.contexts && fn.contexts[0]) || this;
19382   return handlebarsGet(context, property, fn);
19383 });
19384
19385 })();
19386
19387
19388
19389 (function() {
19390 /*jshint debug:true*/
19391 /**
19392 @module ember
19393 @submodule ember-handlebars
19394 */
19395
19396 var handlebarsGet = Ember.Handlebars.get, normalizePath = Ember.Handlebars.normalizePath;
19397
19398 /**
19399   `log` allows you to output the value of a value in the current rendering
19400   context.
19401
19402   ```handlebars
19403   {{log myVariable}}
19404   ```
19405
19406   @method log
19407   @for Ember.Handlebars.helpers
19408   @param {String} property
19409 */
19410 Ember.Handlebars.registerHelper('log', function(property, options) {
19411   var context = (options.contexts && options.contexts[0]) || this,
19412       normalized = normalizePath(context, property, options.data),
19413       pathRoot = normalized.root,
19414       path = normalized.path,
19415       value = (path === 'this') ? pathRoot : handlebarsGet(pathRoot, path, options);
19416   Ember.Logger.log(value);
19417 });
19418
19419 /**
19420   Execute the `debugger` statement in the current context.
19421
19422   ```handlebars
19423   {{debugger}}
19424   ```
19425
19426   @method debugger
19427   @for Ember.Handlebars.helpers
19428   @param {String} property
19429 */
19430 Ember.Handlebars.registerHelper('debugger', function() {
19431   debugger;
19432 });
19433
19434 })();
19435
19436
19437
19438 (function() {
19439 /**
19440 @module ember
19441 @submodule ember-handlebars
19442 */
19443
19444 var get = Ember.get, set = Ember.set;
19445
19446 Ember.Handlebars.EachView = Ember.CollectionView.extend(Ember._Metamorph, {
19447   itemViewClass: Ember._MetamorphView,
19448   emptyViewClass: Ember._MetamorphView,
19449
19450   createChildView: function(view, attrs) {
19451     view = this._super(view, attrs);
19452
19453     // At the moment, if a container view subclass wants
19454     // to insert keywords, it is responsible for cloning
19455     // the keywords hash. This will be fixed momentarily.
19456     var keyword = get(this, 'keyword');
19457
19458     if (keyword) {
19459       var data = get(view, 'templateData');
19460
19461       data = Ember.copy(data);
19462       data.keywords = view.cloneKeywords();
19463       set(view, 'templateData', data);
19464
19465       var content = get(view, 'content');
19466
19467       // In this case, we do not bind, because the `content` of
19468       // a #each item cannot change.
19469       data.keywords[keyword] = content;
19470     }
19471
19472     return view;
19473   }
19474 });
19475
19476 var GroupedEach = Ember.Handlebars.GroupedEach = function(context, path, options) {
19477   var self = this,
19478       normalized = Ember.Handlebars.normalizePath(context, path, options.data);
19479
19480   this.context = context;
19481   this.path = path;
19482   this.options = options;
19483   this.template = options.fn;
19484   this.containingView = options.data.view;
19485   this.normalizedRoot = normalized.root;
19486   this.normalizedPath = normalized.path;
19487   this.content = this.lookupContent();
19488
19489   this.addContentObservers();
19490   this.addArrayObservers();
19491
19492   this.containingView.on('willClearRender', function() {
19493     self.destroy();
19494   });
19495 };
19496
19497 GroupedEach.prototype = {
19498   contentWillChange: function() {
19499     this.removeArrayObservers();
19500   },
19501
19502   contentDidChange: function() {
19503     this.content = this.lookupContent();
19504     this.addArrayObservers();
19505     this.rerenderContainingView();
19506   },
19507
19508   contentArrayWillChange: Ember.K,
19509
19510   contentArrayDidChange: function() {
19511     this.rerenderContainingView();
19512   },
19513
19514   lookupContent: function() {
19515     return Ember.Handlebars.get(this.normalizedRoot, this.normalizedPath, this.options);
19516   },
19517
19518   addArrayObservers: function() {
19519     this.content.addArrayObserver(this, {
19520       willChange: 'contentArrayWillChange',
19521       didChange: 'contentArrayDidChange'
19522     });
19523   },
19524
19525   removeArrayObservers: function() {
19526     this.content.removeArrayObserver(this, {
19527       willChange: 'contentArrayWillChange',
19528       didChange: 'contentArrayDidChange'
19529     });
19530   },
19531
19532   addContentObservers: function() {
19533     Ember.addBeforeObserver(this.normalizedRoot, this.normalizedPath, this, this.contentWillChange);
19534     Ember.addObserver(this.normalizedRoot, this.normalizedPath, this, this.contentDidChange);
19535   },
19536
19537   removeContentObservers: function() {
19538     Ember.removeBeforeObserver(this.normalizedRoot, this.normalizedPath, this.contentWillChange);
19539     Ember.removeObserver(this.normalizedRoot, this.normalizedPath, this.contentDidChange);
19540   },
19541
19542   render: function() {
19543     var content = this.content,
19544         contentLength = get(content, 'length'),
19545         data = this.options.data,
19546         template = this.template;
19547
19548     data.insideEach = true;
19549     for (var i = 0; i < contentLength; i++) {
19550       template(content.objectAt(i), { data: data });
19551     }
19552   },
19553
19554   rerenderContainingView: function() {
19555     Ember.run.scheduleOnce('render', this.containingView, 'rerender');
19556   },
19557
19558   destroy: function() {
19559     this.removeContentObservers();
19560     this.removeArrayObservers();
19561   }
19562 };
19563
19564 /**
19565   The `{{#each}}` helper loops over elements in a collection, rendering its
19566   block once for each item:
19567
19568   ```javascript
19569   Developers = [{name: 'Yehuda'},{name: 'Tom'}, {name: 'Paul'}];
19570   ```
19571
19572   ```handlebars
19573   {{#each Developers}}
19574     {{name}}
19575   {{/each}}
19576   ```
19577
19578   `{{each}}` supports an alternative syntax with element naming:
19579
19580   ```handlebars
19581   {{#each person in Developers}}
19582     {{person.name}}
19583   {{/each}}
19584   ```
19585
19586   When looping over objects that do not have properties, `{{this}}` can be used
19587   to render the object:
19588
19589   ```javascript
19590   DeveloperNames = ['Yehuda', 'Tom', 'Paul']
19591   ```
19592
19593   ```handlebars
19594   {{#each DeveloperNames}}
19595     {{this}}
19596   {{/each}}
19597   ```
19598
19599   ### Blockless Use
19600
19601   If you provide an `itemViewClass` option that has its own `template` you can
19602   omit the block in a similar way to how it can be done with the collection
19603   helper.
19604
19605   The following template:
19606
19607   ```handlebars
19608   {{#view App.MyView }}
19609     {{each view.items itemViewClass="App.AnItemView"}} 
19610   {{/view}}
19611   ```
19612
19613   And application code
19614
19615   ```javascript
19616   App = Ember.Application.create({
19617     MyView: Ember.View.extend({
19618       items: [
19619         Ember.Object.create({name: 'Dave'}),
19620         Ember.Object.create({name: 'Mary'}),
19621         Ember.Object.create({name: 'Sara'})
19622       ]
19623     })
19624   });
19625
19626   App.AnItemView = Ember.View.extend({
19627     template: Ember.Handlebars.compile("Greetings {{name}}")
19628   });
19629
19630   App.initialize();
19631   ```
19632
19633   Will result in the HTML structure below
19634
19635   ```html
19636   <div class="ember-view">
19637     <div class="ember-view">Greetings Dave</div>
19638     <div class="ember-view">Greetings Mary</div>
19639     <div class="ember-view">Greetings Sara</div>
19640   </div>
19641   ```
19642
19643   @method each
19644   @for Ember.Handlebars.helpers
19645   @param [name] {String} name for item (used with `in`)
19646   @param path {String} path
19647 */
19648 Ember.Handlebars.registerHelper('each', function(path, options) {
19649   if (arguments.length === 4) {
19650     Ember.assert("If you pass more than one argument to the each helper, it must be in the form #each foo in bar", arguments[1] === "in");
19651
19652     var keywordName = arguments[0];
19653
19654     options = arguments[3];
19655     path = arguments[2];
19656     if (path === '') { path = "this"; }
19657
19658     options.hash.keyword = keywordName;
19659   } else {
19660     options.hash.eachHelper = 'each';
19661   }
19662
19663   options.hash.contentBinding = path;
19664   // Set up emptyView as a metamorph with no tag
19665   //options.hash.emptyViewClass = Ember._MetamorphView;
19666
19667   if (options.data.insideGroup && !options.hash.groupedRows && !options.hash.itemViewClass) {
19668     new Ember.Handlebars.GroupedEach(this, path, options).render();
19669   } else {
19670     return Ember.Handlebars.helpers.collection.call(this, 'Ember.Handlebars.EachView', options);
19671   }
19672 });
19673
19674 })();
19675
19676
19677
19678 (function() {
19679 /**
19680 @module ember
19681 @submodule ember-handlebars
19682 */
19683
19684 /**
19685   `template` allows you to render a template from inside another template.
19686   This allows you to re-use the same template in multiple places. For example:
19687
19688   ```html
19689   <script type="text/x-handlebars" data-template-name="logged_in_user">
19690     {{#with loggedInUser}}
19691       Last Login: {{lastLogin}}
19692       User Info: {{template "user_info"}}
19693     {{/with}}
19694   </script>
19695   ```
19696
19697   ```html
19698   <script type="text/x-handlebars" data-template-name="user_info">
19699     Name: <em>{{name}}</em>
19700     Karma: <em>{{karma}}</em>
19701   </script>
19702   ```
19703
19704   This helper looks for templates in the global `Ember.TEMPLATES` hash. If you
19705   add `<script>` tags to your page with the `data-template-name` attribute set,
19706   they will be compiled and placed in this hash automatically.
19707
19708   You can also manually register templates by adding them to the hash:
19709
19710   ```javascript
19711   Ember.TEMPLATES["my_cool_template"] = Ember.Handlebars.compile('<b>{{user}}</b>');
19712   ```
19713
19714   @method template
19715   @for Ember.Handlebars.helpers
19716   @param {String} templateName the template to render
19717 */
19718
19719 Ember.Handlebars.registerHelper('template', function(name, options) {
19720   var template = Ember.TEMPLATES[name];
19721
19722   Ember.assert("Unable to find template with name '"+name+"'.", !!template);
19723
19724   Ember.TEMPLATES[name](this, { data: options.data });
19725 });
19726
19727 Ember.Handlebars.registerHelper('partial', function(name, options) {
19728   var nameParts = name.split("/"),
19729       lastPart = nameParts[nameParts.length - 1];
19730
19731   nameParts[nameParts.length - 1] = "_" + lastPart;
19732
19733   var underscoredName = nameParts.join("/");
19734
19735   var template = Ember.TEMPLATES[underscoredName],
19736       deprecatedTemplate = Ember.TEMPLATES[name];
19737
19738   Ember.deprecate("You tried to render the partial " + name + ", which should be at '" + underscoredName + "', but Ember found '" + name + "'. Please use a leading underscore in your partials", template);
19739   Ember.assert("Unable to find partial with name '"+name+"'.", template || deprecatedTemplate);
19740
19741   template = template || deprecatedTemplate;
19742
19743   template(this, { data: options.data });
19744 });
19745
19746 })();
19747
19748
19749
19750 (function() {
19751 /**
19752 @module ember
19753 @submodule ember-handlebars
19754 */
19755
19756 var get = Ember.get, set = Ember.set;
19757
19758 /**
19759   When used in a Handlebars template that is assigned to an `Ember.View`
19760   instance's `layout` property Ember will render the layout template first,
19761   inserting the view's own rendered output at the `{{yield}}` location.
19762
19763   An empty `<body>` and the following application code:
19764
19765   ```javascript
19766   AView = Ember.View.extend({
19767     classNames: ['a-view-with-layout'],
19768     layout: Ember.Handlebars.compile('<div class="wrapper">{{yield}}</div>'),
19769     template: Ember.Handlebars.compile('<span>I am wrapped</span>')
19770   });
19771
19772   aView = AView.create();
19773   aView.appendTo('body');
19774   ```
19775
19776   Will result in the following HTML output:
19777
19778   ```html
19779   <body>
19780     <div class='ember-view a-view-with-layout'>
19781       <div class="wrapper">
19782         <span>I am wrapped</span>
19783       </div>
19784     </div>
19785   </body>
19786   ```
19787
19788   The `yield` helper cannot be used outside of a template assigned to an
19789   `Ember.View`'s `layout` property and will throw an error if attempted.
19790
19791   ```javascript
19792   BView = Ember.View.extend({
19793     classNames: ['a-view-with-layout'],
19794     template: Ember.Handlebars.compile('{{yield}}')
19795   });
19796
19797   bView = BView.create();
19798   bView.appendTo('body');
19799
19800   // throws
19801   // Uncaught Error: assertion failed: You called yield in a template that was not a layout
19802   ```
19803
19804   @method yield
19805   @for Ember.Handlebars.helpers
19806   @param {Hash} options
19807   @return {String} HTML string
19808 */
19809 Ember.Handlebars.registerHelper('yield', function(options) {
19810   var view = options.data.view, template;
19811
19812   while (view && !get(view, 'layout')) {
19813     view = get(view, 'parentView');
19814   }
19815
19816   Ember.assert("You called yield in a template that was not a layout", !!view);
19817
19818   template = get(view, 'template');
19819
19820   if (template) { template(this, options); }
19821 });
19822
19823 })();
19824
19825
19826
19827 (function() {
19828
19829 })();
19830
19831
19832
19833 (function() {
19834
19835 })();
19836
19837
19838
19839 (function() {
19840 /**
19841 @module ember
19842 @submodule ember-handlebars
19843 */
19844
19845 var set = Ember.set, get = Ember.get;
19846
19847 /**
19848   The `Ember.Checkbox` view class renders a checkbox
19849   [input](https://developer.mozilla.org/en/HTML/Element/Input) element. It
19850   allows for binding an Ember property (`checked`) to the status of the
19851   checkbox.
19852
19853   Example:
19854
19855   ```handlebars
19856   {{view Ember.Checkbox checkedBinding="receiveEmail"}}
19857   ```
19858
19859   You can add a `label` tag yourself in the template where the `Ember.Checkbox`
19860   is being used.
19861
19862   ```html
19863   <label>
19864     {{view Ember.Checkbox classNames="applicaton-specific-checkbox"}}
19865     Some Title
19866   </label>
19867   ```
19868
19869   The `checked` attribute of an `Ember.Checkbox` object should always be set
19870   through the Ember object or by interacting with its rendered element
19871   representation via the mouse, keyboard, or touch. Updating the value of the
19872   checkbox via jQuery will result in the checked value of the object and its
19873   element losing synchronization.
19874
19875   ## Layout and LayoutName properties
19876
19877   Because HTML `input` elements are self closing `layout` and `layoutName`
19878   properties will not be applied. See `Ember.View`'s layout section for more
19879   information.
19880
19881   @class Checkbox
19882   @namespace Ember
19883   @extends Ember.View
19884 */
19885 Ember.Checkbox = Ember.View.extend({
19886   classNames: ['ember-checkbox'],
19887
19888   tagName: 'input',
19889
19890   attributeBindings: ['type', 'checked', 'disabled', 'tabindex'],
19891
19892   type: "checkbox",
19893   checked: false,
19894   disabled: false,
19895
19896   init: function() {
19897     this._super();
19898     this.on("change", this, this._updateElementValue);
19899   },
19900
19901   _updateElementValue: function() {
19902     set(this, 'checked', this.$().prop('checked'));
19903   }
19904 });
19905
19906 })();
19907
19908
19909
19910 (function() {
19911 /**
19912 @module ember
19913 @submodule ember-handlebars
19914 */
19915
19916 var get = Ember.get, set = Ember.set;
19917
19918 /**
19919   Shared mixin used by `Ember.TextField` and `Ember.TextArea`.
19920
19921   @class TextSupport
19922   @namespace Ember
19923   @extends Ember.Mixin
19924   @private
19925 */
19926 Ember.TextSupport = Ember.Mixin.create({
19927   value: "",
19928
19929   attributeBindings: ['placeholder', 'disabled', 'maxlength', 'tabindex'],
19930   placeholder: null,
19931   disabled: false,
19932   maxlength: null,
19933
19934   insertNewline: Ember.K,
19935   cancel: Ember.K,
19936
19937   init: function() {
19938     this._super();
19939     this.on("focusOut", this, this._elementValueDidChange);
19940     this.on("change", this, this._elementValueDidChange);
19941     this.on("paste", this, this._elementValueDidChange);
19942     this.on("cut", this, this._elementValueDidChange);
19943     this.on("input", this, this._elementValueDidChange);
19944     this.on("keyUp", this, this.interpretKeyEvents);
19945   },
19946
19947   interpretKeyEvents: function(event) {
19948     var map = Ember.TextSupport.KEY_EVENTS;
19949     var method = map[event.keyCode];
19950
19951     this._elementValueDidChange();
19952     if (method) { return this[method](event); }
19953   },
19954
19955   _elementValueDidChange: function() {
19956     set(this, 'value', this.$().val());
19957   }
19958
19959 });
19960
19961 Ember.TextSupport.KEY_EVENTS = {
19962   13: 'insertNewline',
19963   27: 'cancel'
19964 };
19965
19966 })();
19967
19968
19969
19970 (function() {
19971 /**
19972 @module ember
19973 @submodule ember-handlebars
19974 */
19975
19976 var get = Ember.get, set = Ember.set;
19977
19978 /**
19979   The `Ember.TextField` view class renders a text
19980   [input](https://developer.mozilla.org/en/HTML/Element/Input) element. It
19981   allows for binding Ember properties to the text field contents (`value`),
19982   live-updating as the user inputs text.
19983
19984   Example:
19985
19986   ```handlebars
19987   {{view Ember.TextField valueBinding="firstName"}}
19988   ```
19989
19990   ## Layout and LayoutName properties
19991
19992   Because HTML `input` elements are self closing `layout` and `layoutName`
19993   properties will not be applied. See `Ember.View`'s layout section for more
19994   information.
19995
19996   ## HTML Attributes
19997
19998   By default `Ember.TextField` provides support for `type`, `value`, `size`,
19999   `placeholder`, `disabled`, `maxlength` and `tabindex` attributes on a
20000   test field. If you need to support more attributes have a look at the
20001   `attributeBindings` property in `Ember.View`'s HTML Attributes section.
20002
20003   To globally add support for additional attributes you can reopen
20004   `Ember.TextField` or `Ember.TextSupport`.
20005
20006   ```javascript
20007   Ember.TextSupport.reopen({
20008     attributeBindings: ["required"]
20009   })
20010   ```
20011
20012   @class TextField
20013   @namespace Ember
20014   @extends Ember.View
20015   @uses Ember.TextSupport
20016 */
20017 Ember.TextField = Ember.View.extend(Ember.TextSupport,
20018   /** @scope Ember.TextField.prototype */ {
20019
20020   classNames: ['ember-text-field'],
20021   tagName: "input",
20022   attributeBindings: ['type', 'value', 'size'],
20023
20024   /**
20025     The `value` attribute of the input element. As the user inputs text, this
20026     property is updated live.
20027
20028     @property value
20029     @type String
20030     @default ""
20031   */
20032   value: "",
20033
20034   /**
20035     The `type` attribute of the input element.
20036
20037     @property type
20038     @type String
20039     @default "text"
20040   */
20041   type: "text",
20042
20043   /**
20044     The `size` of the text field in characters.
20045
20046     @property size
20047     @type String
20048     @default null
20049   */
20050   size: null,
20051
20052   /**
20053     The action to be sent when the user presses the return key.
20054
20055     This is similar to the `{{action}}` helper, but is fired when
20056     the user presses the return key when editing a text field, and sends
20057     the value of the field as the context.
20058
20059    @property action
20060    @type String
20061    @default null
20062   */
20063   action: null,
20064
20065   insertNewline: function() {
20066     var controller = get(this, 'controller'),
20067         action = get(this, 'action');
20068
20069     if (action) {
20070       controller.send(action, get(this, 'value'));
20071     }
20072
20073     return false;
20074   }
20075 });
20076
20077 })();
20078
20079
20080
20081 (function() {
20082 /**
20083 @module ember
20084 @submodule ember-handlebars
20085 */
20086
20087 var get = Ember.get, set = Ember.set;
20088
20089 /**
20090   @class Button
20091   @namespace Ember
20092   @extends Ember.View
20093   @uses Ember.TargetActionSupport
20094   @deprecated
20095 */
20096 Ember.Button = Ember.View.extend(Ember.TargetActionSupport, {
20097   classNames: ['ember-button'],
20098   classNameBindings: ['isActive'],
20099
20100   tagName: 'button',
20101
20102   propagateEvents: false,
20103
20104   attributeBindings: ['type', 'disabled', 'href', 'tabindex'],
20105
20106   /**
20107     @private
20108
20109     Overrides `TargetActionSupport`'s `targetObject` computed
20110     property to use Handlebars-specific path resolution.
20111
20112     @property targetObject
20113   */
20114   targetObject: Ember.computed(function() {
20115     var target = get(this, 'target'),
20116         root = get(this, 'context'),
20117         data = get(this, 'templateData');
20118
20119     if (typeof target !== 'string') { return target; }
20120
20121     return Ember.Handlebars.get(root, target, { data: data });
20122   }).property('target'),
20123
20124   // Defaults to 'button' if tagName is 'input' or 'button'
20125   type: Ember.computed(function(key) {
20126     var tagName = this.tagName;
20127     if (tagName === 'input' || tagName === 'button') { return 'button'; }
20128   }),
20129
20130   disabled: false,
20131
20132   // Allow 'a' tags to act like buttons
20133   href: Ember.computed(function() {
20134     return this.tagName === 'a' ? '#' : null;
20135   }),
20136
20137   mouseDown: function() {
20138     if (!get(this, 'disabled')) {
20139       set(this, 'isActive', true);
20140       this._mouseDown = true;
20141       this._mouseEntered = true;
20142     }
20143     return get(this, 'propagateEvents');
20144   },
20145
20146   mouseLeave: function() {
20147     if (this._mouseDown) {
20148       set(this, 'isActive', false);
20149       this._mouseEntered = false;
20150     }
20151   },
20152
20153   mouseEnter: function() {
20154     if (this._mouseDown) {
20155       set(this, 'isActive', true);
20156       this._mouseEntered = true;
20157     }
20158   },
20159
20160   mouseUp: function(event) {
20161     if (get(this, 'isActive')) {
20162       // Actually invoke the button's target and action.
20163       // This method comes from the Ember.TargetActionSupport mixin.
20164       this.triggerAction();
20165       set(this, 'isActive', false);
20166     }
20167
20168     this._mouseDown = false;
20169     this._mouseEntered = false;
20170     return get(this, 'propagateEvents');
20171   },
20172
20173   keyDown: function(event) {
20174     // Handle space or enter
20175     if (event.keyCode === 13 || event.keyCode === 32) {
20176       this.mouseDown();
20177     }
20178   },
20179
20180   keyUp: function(event) {
20181     // Handle space or enter
20182     if (event.keyCode === 13 || event.keyCode === 32) {
20183       this.mouseUp();
20184     }
20185   },
20186
20187   // TODO: Handle proper touch behavior. Including should make inactive when
20188   // finger moves more than 20x outside of the edge of the button (vs mouse
20189   // which goes inactive as soon as mouse goes out of edges.)
20190
20191   touchStart: function(touch) {
20192     return this.mouseDown(touch);
20193   },
20194
20195   touchEnd: function(touch) {
20196     return this.mouseUp(touch);
20197   },
20198
20199   init: function() {
20200     Ember.deprecate("Ember.Button is deprecated and will be removed from future releases. Consider using the `{{action}}` helper.");
20201     this._super();
20202   }
20203 });
20204
20205 })();
20206
20207
20208
20209 (function() {
20210 /**
20211 @module ember
20212 @submodule ember-handlebars
20213 */
20214
20215 var get = Ember.get, set = Ember.set;
20216
20217 /**
20218   The `Ember.TextArea` view class renders a
20219   [textarea](https://developer.mozilla.org/en/HTML/Element/textarea) element.
20220   It allows for binding Ember properties to the text area contents (`value`),
20221   live-updating as the user inputs text.
20222
20223   ## Layout and LayoutName properties
20224
20225   Because HTML `textarea` elements do not contain inner HTML the `layout` and
20226   `layoutName` properties will not be applied. See `Ember.View`'s layout
20227   section for more information.
20228
20229   ## HTML Attributes
20230
20231   By default `Ember.TextArea` provides support for `rows`, `cols`,
20232   `placeholder`, `disabled`, `maxlength` and `tabindex` attributes on a
20233   textarea. If you need to support  more attributes have a look at the
20234   `attributeBindings` property in `Ember.View`'s HTML Attributes section.
20235
20236   To globally add support for additional attributes you can reopen
20237   `Ember.TextArea` or `Ember.TextSupport`.
20238
20239   ```javascript
20240   Ember.TextSupport.reopen({
20241     attributeBindings: ["required"]
20242   })
20243   ```
20244
20245   @class TextArea
20246   @namespace Ember
20247   @extends Ember.View
20248   @uses Ember.TextSupport
20249 */
20250 Ember.TextArea = Ember.View.extend(Ember.TextSupport, {
20251   classNames: ['ember-text-area'],
20252
20253   tagName: "textarea",
20254   attributeBindings: ['rows', 'cols'],
20255   rows: null,
20256   cols: null,
20257
20258   _updateElementValue: Ember.observer(function() {
20259     // We do this check so cursor position doesn't get affected in IE
20260     var value = get(this, 'value'),
20261         $el = this.$();
20262     if ($el && value !== $el.val()) {
20263       $el.val(value);
20264     }
20265   }, 'value'),
20266
20267   init: function() {
20268     this._super();
20269     this.on("didInsertElement", this, this._updateElementValue);
20270   }
20271
20272 });
20273
20274 })();
20275
20276
20277
20278 (function() {
20279 /*jshint eqeqeq:false */
20280
20281 /**
20282 @module ember
20283 @submodule ember-handlebars
20284 */
20285
20286 var set = Ember.set,
20287     get = Ember.get,
20288     indexOf = Ember.EnumerableUtils.indexOf,
20289     indexesOf = Ember.EnumerableUtils.indexesOf,
20290     replace = Ember.EnumerableUtils.replace,
20291     isArray = Ember.isArray,
20292     precompileTemplate = Ember.Handlebars.compile;
20293
20294 /**
20295   The `Ember.Select` view class renders a
20296   [select](https://developer.mozilla.org/en/HTML/Element/select) HTML element,
20297   allowing the user to choose from a list of options.
20298
20299   The text and `value` property of each `<option>` element within the
20300   `<select>` element are populated from the objects in the `Element.Select`'s
20301   `content` property. The underlying data object of the selected `<option>` is
20302   stored in the `Element.Select`'s `value` property.
20303
20304   ### `content` as an array of Strings
20305
20306   The simplest version of an `Ember.Select` takes an array of strings as its
20307   `content` property. The string will be used as both the `value` property and
20308   the inner text of each `<option>` element inside the rendered `<select>`.
20309
20310   Example:
20311
20312   ```javascript
20313   App.names = ["Yehuda", "Tom"];
20314   ```
20315
20316   ```handlebars
20317   {{view Ember.Select contentBinding="App.names"}}
20318   ```
20319
20320   Would result in the following HTML:
20321
20322   ```html
20323   <select class="ember-select">
20324     <option value="Yehuda">Yehuda</option>
20325     <option value="Tom">Tom</option>
20326   </select>
20327   ```
20328
20329   You can control which `<option>` is selected through the `Ember.Select`'s
20330   `value` property directly or as a binding:
20331
20332   ```javascript
20333   App.names = Ember.Object.create({
20334     selected: 'Tom',
20335     content: ["Yehuda", "Tom"]
20336   });
20337   ```
20338
20339   ```handlebars
20340   {{view Ember.Select
20341          contentBinding="App.names.content"
20342          valueBinding="App.names.selected"
20343   }}
20344   ```
20345
20346   Would result in the following HTML with the `<option>` for 'Tom' selected:
20347
20348   ```html
20349   <select class="ember-select">
20350     <option value="Yehuda">Yehuda</option>
20351     <option value="Tom" selected="selected">Tom</option>
20352   </select>
20353   ```
20354
20355   A user interacting with the rendered `<select>` to choose "Yehuda" would
20356   update the value of `App.names.selected` to "Yehuda".
20357
20358   ### `content` as an Array of Objects
20359
20360   An `Ember.Select` can also take an array of JavaScript or Ember objects as
20361   its `content` property.
20362
20363   When using objects you need to tell the `Ember.Select` which property should
20364   be accessed on each object to supply the `value` attribute of the `<option>`
20365   and which property should be used to supply the element text.
20366
20367   The `optionValuePath` option is used to specify the path on each object to
20368   the desired property for the `value` attribute. The `optionLabelPath`
20369   specifies the path on each object to the desired property for the
20370   element's text. Both paths must reference each object itself as `content`:
20371
20372   ```javascript
20373   App.programmers = [
20374     Ember.Object.create({firstName: "Yehuda", id: 1}),
20375     Ember.Object.create({firstName: "Tom",    id: 2})
20376   ];
20377   ```
20378
20379   ```handlebars
20380   {{view Ember.Select
20381          contentBinding="App.programmers"
20382          optionValuePath="content.id"
20383          optionLabelPath="content.firstName"}}
20384   ```
20385
20386   Would result in the following HTML:
20387
20388   ```html
20389   <select class="ember-select">
20390     <option value>Please Select</option>
20391     <option value="1">Yehuda</option>
20392     <option value="2">Tom</option>
20393   </select>
20394   ```
20395
20396   The `value` attribute of the selected `<option>` within an `Ember.Select`
20397   can be bound to a property on another object by providing a
20398   `valueBinding` option:
20399
20400   ```javascript
20401   App.programmers = [
20402     Ember.Object.create({firstName: "Yehuda", id: 1}),
20403     Ember.Object.create({firstName: "Tom",    id: 2})
20404   ];
20405
20406   App.currentProgrammer = Ember.Object.create({
20407     id: 2
20408   });
20409   ```
20410
20411   ```handlebars
20412   {{view Ember.Select
20413          contentBinding="App.programmers"
20414          optionValuePath="content.id"
20415          optionLabelPath="content.firstName"
20416          valueBinding="App.currentProgrammer.id"}}
20417   ```
20418
20419   Would result in the following HTML with a selected option:
20420
20421   ```html
20422   <select class="ember-select">
20423     <option value>Please Select</option>
20424     <option value="1">Yehuda</option>
20425     <option value="2" selected="selected">Tom</option>
20426   </select>
20427   ```
20428
20429   Interacting with the rendered element by selecting the first option
20430   ('Yehuda') will update the `id` value of `App.currentProgrammer`
20431   to match the `value` property of the newly selected `<option>`.
20432
20433   Alternatively, you can control selection through the underlying objects
20434   used to render each object providing a `selectionBinding`. When the selected
20435   `<option>` is changed, the property path provided to `selectionBinding`
20436   will be updated to match the content object of the rendered `<option>`
20437   element:
20438
20439   ```javascript
20440   App.controller = Ember.Object.create({
20441     selectedPerson: null,
20442     content: [
20443       Ember.Object.create({firstName: "Yehuda", id: 1}),
20444       Ember.Object.create({firstName: "Tom",    id: 2})
20445     ]
20446   });
20447   ```
20448
20449   ```handlebars
20450   {{view Ember.Select
20451          contentBinding="App.controller.content"
20452          optionValuePath="content.id"
20453          optionLabelPath="content.firstName"
20454          selectionBinding="App.controller.selectedPerson"}}
20455   ```
20456
20457   Would result in the following HTML with a selected option:
20458
20459   ```html
20460   <select class="ember-select">
20461     <option value>Please Select</option>
20462     <option value="1">Yehuda</option>
20463     <option value="2" selected="selected">Tom</option>
20464   </select>
20465   ```
20466
20467   Interacting with the rendered element by selecting the first option
20468   ('Yehuda') will update the `selectedPerson` value of `App.controller`
20469   to match the content object of the newly selected `<option>`. In this
20470   case it is the first object in the `App.content.content`
20471
20472   ### Supplying a Prompt
20473
20474   A `null` value for the `Ember.Select`'s `value` or `selection` property
20475   results in there being no `<option>` with a `selected` attribute:
20476
20477   ```javascript
20478   App.controller = Ember.Object.create({
20479     selected: null,
20480     content: [
20481       "Yehuda",
20482       "Tom"
20483     ]
20484   });
20485   ```
20486
20487   ``` handlebars
20488   {{view Ember.Select
20489          contentBinding="App.controller.content"
20490          valueBinding="App.controller.selected"
20491   }}
20492   ```
20493
20494   Would result in the following HTML:
20495
20496   ```html
20497   <select class="ember-select">
20498     <option value="Yehuda">Yehuda</option>
20499     <option value="Tom">Tom</option>
20500   </select>
20501   ```
20502
20503   Although `App.controller.selected` is `null` and no `<option>`
20504   has a `selected` attribute the rendered HTML will display the
20505   first item as though it were selected. You can supply a string
20506   value for the `Ember.Select` to display when there is no selection
20507   with the `prompt` option:
20508
20509   ```javascript
20510   App.controller = Ember.Object.create({
20511     selected: null,
20512     content: [
20513       "Yehuda",
20514       "Tom"
20515     ]
20516   });
20517   ```
20518
20519   ```handlebars
20520   {{view Ember.Select
20521          contentBinding="App.controller.content"
20522          valueBinding="App.controller.selected"
20523          prompt="Please select a name"
20524   }}
20525   ```
20526
20527   Would result in the following HTML:
20528
20529   ```html
20530   <select class="ember-select">
20531     <option>Please select a name</option>
20532     <option value="Yehuda">Yehuda</option>
20533     <option value="Tom">Tom</option>
20534   </select>
20535   ```
20536
20537   @class Select
20538   @namespace Ember
20539   @extends Ember.View
20540 */
20541 Ember.Select = Ember.View.extend(
20542   /** @scope Ember.Select.prototype */ {
20543
20544   tagName: 'select',
20545   classNames: ['ember-select'],
20546   defaultTemplate: Ember.Handlebars.template(function anonymous(Handlebars,depth0,helpers,partials,data) {
20547 helpers = helpers || Ember.Handlebars.helpers; data = data || {};
20548   var buffer = '', stack1, escapeExpression=this.escapeExpression, self=this;
20549
20550 function program1(depth0,data) {
20551   
20552   var buffer = '', stack1;
20553   data.buffer.push("<option value=\"\">");
20554   stack1 = helpers._triageMustache.call(depth0, "view.prompt", {hash:{},contexts:[depth0],data:data});
20555   data.buffer.push(escapeExpression(stack1) + "</option>");
20556   return buffer;}
20557
20558 function program3(depth0,data) {
20559   
20560   var stack1;
20561   stack1 = {};
20562   stack1['contentBinding'] = "this";
20563   stack1 = helpers.view.call(depth0, "Ember.SelectOption", {hash:stack1,contexts:[depth0],data:data});
20564   data.buffer.push(escapeExpression(stack1));}
20565
20566   stack1 = helpers['if'].call(depth0, "view.prompt", {hash:{},inverse:self.noop,fn:self.program(1, program1, data),contexts:[depth0],data:data});
20567   if(stack1 || stack1 === 0) { data.buffer.push(stack1); }
20568   stack1 = helpers.each.call(depth0, "view.content", {hash:{},inverse:self.noop,fn:self.program(3, program3, data),contexts:[depth0],data:data});
20569   if(stack1 || stack1 === 0) { data.buffer.push(stack1); }
20570   return buffer;
20571 }),
20572   attributeBindings: ['multiple', 'disabled', 'tabindex'],
20573
20574   /**
20575     The `multiple` attribute of the select element. Indicates whether multiple
20576     options can be selected.
20577
20578     @property multiple
20579     @type Boolean
20580     @default false
20581   */
20582   multiple: false,
20583
20584   disabled: false,
20585
20586   /**
20587     The list of options.
20588
20589     If `optionLabelPath` and `optionValuePath` are not overridden, this should
20590     be a list of strings, which will serve simultaneously as labels and values.
20591
20592     Otherwise, this should be a list of objects. For instance:
20593
20594     ```javascript
20595     Ember.Select.create({
20596       content: Ember.A([
20597           { id: 1, firstName: 'Yehuda' },
20598           { id: 2, firstName: 'Tom' }
20599         ]),
20600       optionLabelPath: 'content.firstName',
20601       optionValuePath: 'content.id'
20602     });
20603     ```
20604
20605     @property content
20606     @type Array
20607     @default null
20608   */
20609   content: null,
20610
20611   /**
20612     When `multiple` is `false`, the element of `content` that is currently
20613     selected, if any.
20614
20615     When `multiple` is `true`, an array of such elements.
20616
20617     @property selection
20618     @type Object or Array
20619     @default null
20620   */
20621   selection: null,
20622
20623   /**
20624     In single selection mode (when `multiple` is `false`), value can be used to
20625     get the current selection's value or set the selection by it's value.
20626
20627     It is not currently supported in multiple selection mode.
20628
20629     @property value
20630     @type String
20631     @default null
20632   */
20633   value: Ember.computed(function(key, value) {
20634     if (arguments.length === 2) { return value; }
20635     var valuePath = get(this, 'optionValuePath').replace(/^content\.?/, '');
20636     return valuePath ? get(this, 'selection.' + valuePath) : get(this, 'selection');
20637   }).property('selection'),
20638
20639   /**
20640     If given, a top-most dummy option will be rendered to serve as a user
20641     prompt.
20642
20643     @property prompt
20644     @type String
20645     @default null
20646   */
20647   prompt: null,
20648
20649   /**
20650     The path of the option labels. See `content`.
20651
20652     @property optionLabelPath
20653     @type String
20654     @default 'content'
20655   */
20656   optionLabelPath: 'content',
20657
20658   /**
20659     The path of the option values. See `content`.
20660
20661     @property optionValuePath
20662     @type String
20663     @default 'content'
20664   */
20665   optionValuePath: 'content',
20666
20667   _change: function() {
20668     if (get(this, 'multiple')) {
20669       this._changeMultiple();
20670     } else {
20671       this._changeSingle();
20672     }
20673   },
20674
20675   selectionDidChange: Ember.observer(function() {
20676     var selection = get(this, 'selection');
20677     if (get(this, 'multiple')) {
20678       if (!isArray(selection)) {
20679         set(this, 'selection', Ember.A([selection]));
20680         return;
20681       }
20682       this._selectionDidChangeMultiple();
20683     } else {
20684       this._selectionDidChangeSingle();
20685     }
20686   }, 'selection.@each'),
20687
20688   valueDidChange: Ember.observer(function() {
20689     var content = get(this, 'content'),
20690         value = get(this, 'value'),
20691         valuePath = get(this, 'optionValuePath').replace(/^content\.?/, ''),
20692         selectedValue = (valuePath ? get(this, 'selection.' + valuePath) : get(this, 'selection')),
20693         selection;
20694
20695     if (value !== selectedValue) {
20696       selection = content.find(function(obj) {
20697         return value === (valuePath ? get(obj, valuePath) : obj);
20698       });
20699
20700       this.set('selection', selection);
20701     }
20702   }, 'value'),
20703
20704
20705   _triggerChange: function() {
20706     var selection = get(this, 'selection');
20707     var value = get(this, 'value');
20708
20709     if (selection) { this.selectionDidChange(); }
20710     if (value) { this.valueDidChange(); }
20711
20712     this._change();
20713   },
20714
20715   _changeSingle: function() {
20716     var selectedIndex = this.$()[0].selectedIndex,
20717         content = get(this, 'content'),
20718         prompt = get(this, 'prompt');
20719
20720     if (!get(content, 'length')) { return; }
20721     if (prompt && selectedIndex === 0) { set(this, 'selection', null); return; }
20722
20723     if (prompt) { selectedIndex -= 1; }
20724     set(this, 'selection', content.objectAt(selectedIndex));
20725   },
20726
20727
20728   _changeMultiple: function() {
20729     var options = this.$('option:selected'),
20730         prompt = get(this, 'prompt'),
20731         offset = prompt ? 1 : 0,
20732         content = get(this, 'content'),
20733         selection = get(this, 'selection');
20734
20735     if (!content){ return; }
20736     if (options) {
20737       var selectedIndexes = options.map(function(){
20738         return this.index - offset;
20739       }).toArray();
20740       var newSelection = content.objectsAt(selectedIndexes);
20741
20742       if (isArray(selection)) {
20743         replace(selection, 0, get(selection, 'length'), newSelection);
20744       } else {
20745         set(this, 'selection', newSelection);
20746       }
20747     }
20748   },
20749
20750   _selectionDidChangeSingle: function() {
20751     var el = this.get('element');
20752     if (!el) { return; }
20753
20754     var content = get(this, 'content'),
20755         selection = get(this, 'selection'),
20756         selectionIndex = content ? indexOf(content, selection) : -1,
20757         prompt = get(this, 'prompt');
20758
20759     if (prompt) { selectionIndex += 1; }
20760     if (el) { el.selectedIndex = selectionIndex; }
20761   },
20762
20763   _selectionDidChangeMultiple: function() {
20764     var content = get(this, 'content'),
20765         selection = get(this, 'selection'),
20766         selectedIndexes = content ? indexesOf(content, selection) : [-1],
20767         prompt = get(this, 'prompt'),
20768         offset = prompt ? 1 : 0,
20769         options = this.$('option'),
20770         adjusted;
20771
20772     if (options) {
20773       options.each(function() {
20774         adjusted = this.index > -1 ? this.index - offset : -1;
20775         this.selected = indexOf(selectedIndexes, adjusted) > -1;
20776       });
20777     }
20778   },
20779
20780   init: function() {
20781     this._super();
20782     this.on("didInsertElement", this, this._triggerChange);
20783     this.on("change", this, this._change);
20784   }
20785 });
20786
20787 Ember.SelectOption = Ember.View.extend({
20788   tagName: 'option',
20789   attributeBindings: ['value', 'selected'],
20790
20791   defaultTemplate: function(context, options) {
20792     options = { data: options.data, hash: {} };
20793     Ember.Handlebars.helpers.bind.call(context, "view.label", options);
20794   },
20795
20796   init: function() {
20797     this.labelPathDidChange();
20798     this.valuePathDidChange();
20799
20800     this._super();
20801   },
20802
20803   selected: Ember.computed(function() {
20804     var content = get(this, 'content'),
20805         selection = get(this, 'parentView.selection');
20806     if (get(this, 'parentView.multiple')) {
20807       return selection && indexOf(selection, content.valueOf()) > -1;
20808     } else {
20809       // Primitives get passed through bindings as objects... since
20810       // `new Number(4) !== 4`, we use `==` below
20811       return content == selection;
20812     }
20813   }).property('content', 'parentView.selection').volatile(),
20814
20815   labelPathDidChange: Ember.observer(function() {
20816     var labelPath = get(this, 'parentView.optionLabelPath');
20817
20818     if (!labelPath) { return; }
20819
20820     Ember.defineProperty(this, 'label', Ember.computed(function() {
20821       return get(this, labelPath);
20822     }).property(labelPath));
20823   }, 'parentView.optionLabelPath'),
20824
20825   valuePathDidChange: Ember.observer(function() {
20826     var valuePath = get(this, 'parentView.optionValuePath');
20827
20828     if (!valuePath) { return; }
20829
20830     Ember.defineProperty(this, 'value', Ember.computed(function() {
20831       return get(this, valuePath);
20832     }).property(valuePath));
20833   }, 'parentView.optionValuePath')
20834 });
20835
20836 })();
20837
20838
20839
20840 (function() {
20841
20842 })();
20843
20844
20845
20846 (function() {
20847 /*globals Handlebars */
20848 /**
20849 @module ember
20850 @submodule ember-handlebars
20851 */
20852
20853 /**
20854   @private
20855
20856   Find templates stored in the head tag as script tags and make them available
20857   to `Ember.CoreView` in the global `Ember.TEMPLATES` object. This will be run
20858   as as jQuery DOM-ready callback.
20859
20860   Script tags with `text/x-handlebars` will be compiled
20861   with Ember's Handlebars and are suitable for use as a view's template.
20862   Those with type `text/x-raw-handlebars` will be compiled with regular
20863   Handlebars and are suitable for use in views' computed properties.
20864
20865   @method bootstrap
20866   @for Ember.Handlebars
20867   @static
20868   @param ctx
20869 */
20870 Ember.Handlebars.bootstrap = function(ctx) {
20871   var selectors = 'script[type="text/x-handlebars"], script[type="text/x-raw-handlebars"]';
20872
20873   Ember.$(selectors, ctx)
20874     .each(function() {
20875     // Get a reference to the script tag
20876     var script = Ember.$(this),
20877         type   = script.attr('type');
20878
20879     var compile = (script.attr('type') === 'text/x-raw-handlebars') ?
20880                   Ember.$.proxy(Handlebars.compile, Handlebars) :
20881                   Ember.$.proxy(Ember.Handlebars.compile, Ember.Handlebars),
20882       // Get the name of the script, used by Ember.View's templateName property.
20883       // First look for data-template-name attribute, then fall back to its
20884       // id if no name is found.
20885       templateName = script.attr('data-template-name') || script.attr('id') || 'application',
20886       template = compile(script.html());
20887
20888     // For templates which have a name, we save them and then remove them from the DOM
20889     Ember.TEMPLATES[templateName] = template;
20890
20891     // Remove script tag from DOM
20892     script.remove();
20893   });
20894 };
20895
20896 function bootstrap() {
20897   Ember.Handlebars.bootstrap( Ember.$(document) );
20898 }
20899
20900 /*
20901   We tie this to application.load to ensure that we've at least
20902   attempted to bootstrap at the point that the application is loaded.
20903
20904   We also tie this to document ready since we're guaranteed that all
20905   the inline templates are present at this point.
20906
20907   There's no harm to running this twice, since we remove the templates
20908   from the DOM after processing.
20909 */
20910
20911 Ember.onLoad('application', bootstrap);
20912
20913 })();
20914
20915
20916
20917 (function() {
20918 /**
20919 Ember Handlebars
20920
20921 @module ember
20922 @submodule ember-handlebars
20923 @requires ember-views
20924 */
20925
20926 Ember.runLoadHooks('Ember.Handlebars', Ember.Handlebars);
20927
20928 })();
20929
20930 (function() {
20931 define("route-recognizer",
20932   [],
20933   function() {
20934     "use strict";
20935     var specials = [
20936       '/', '.', '*', '+', '?', '|',
20937       '(', ')', '[', ']', '{', '}', '\\'
20938     ];
20939
20940     var escapeRegex = new RegExp('(\\' + specials.join('|\\') + ')', 'g');
20941
20942     // A Segment represents a segment in the original route description.
20943     // Each Segment type provides an `eachChar` and `regex` method.
20944     //
20945     // The `eachChar` method invokes the callback with one or more character
20946     // specifications. A character specification consumes one or more input
20947     // characters.
20948     //
20949     // The `regex` method returns a regex fragment for the segment. If the
20950     // segment is a dynamic of star segment, the regex fragment also includes
20951     // a capture.
20952     //
20953     // A character specification contains:
20954     //
20955     // * `validChars`: a String with a list of all valid characters, or
20956     // * `invalidChars`: a String with a list of all invalid characters
20957     // * `repeat`: true if the character specification can repeat
20958
20959     function StaticSegment(string) { this.string = string; }
20960     StaticSegment.prototype = {
20961       eachChar: function(callback) {
20962         var string = this.string, char;
20963
20964         for (var i=0, l=string.length; i<l; i++) {
20965           char = string.charAt(i);
20966           callback({ validChars: char });
20967         }
20968       },
20969
20970       regex: function() {
20971         return this.string.replace(escapeRegex, '\\$1');
20972       },
20973
20974       generate: function() {
20975         return this.string;
20976       }
20977     };
20978
20979     function DynamicSegment(name) { this.name = name; }
20980     DynamicSegment.prototype = {
20981       eachChar: function(callback) {
20982         callback({ invalidChars: "/", repeat: true });
20983       },
20984
20985       regex: function() {
20986         return "([^/]+)";
20987       },
20988
20989       generate: function(params) {
20990         return params[this.name];
20991       }
20992     };
20993
20994     function StarSegment(name) { this.name = name; }
20995     StarSegment.prototype = {
20996       eachChar: function(callback) {
20997         callback({ invalidChars: "", repeat: true });
20998       },
20999
21000       regex: function() {
21001         return "(.+)";
21002       },
21003
21004       generate: function(params) {
21005         return params[this.name];
21006       }
21007     };
21008
21009     function EpsilonSegment() {}
21010     EpsilonSegment.prototype = {
21011       eachChar: function() {},
21012       regex: function() { return ""; },
21013       generate: function() { return ""; }
21014     };
21015
21016     function parse(route, names, types) {
21017       // normalize route as not starting with a "/". Recognition will
21018       // also normalize.
21019       if (route.charAt(0) === "/") { route = route.substr(1); }
21020
21021       var segments = route.split("/"), results = [];
21022
21023       for (var i=0, l=segments.length; i<l; i++) {
21024         var segment = segments[i], match;
21025
21026         if (match = segment.match(/^:([^\/]+)$/)) {
21027           results.push(new DynamicSegment(match[1]));
21028           names.push(match[1]);
21029           types.dynamics++;
21030         } else if (match = segment.match(/^\*([^\/]+)$/)) {
21031           results.push(new StarSegment(match[1]));
21032           names.push(match[1]);
21033           types.stars++;
21034         } else if(segment === "") {
21035           results.push(new EpsilonSegment());
21036         } else {
21037           results.push(new StaticSegment(segment));
21038           types.statics++;
21039         }
21040       }
21041
21042       return results;
21043     }
21044
21045     // A State has a character specification and (`charSpec`) and a list of possible
21046     // subsequent states (`nextStates`).
21047     //
21048     // If a State is an accepting state, it will also have several additional
21049     // properties:
21050     //
21051     // * `regex`: A regular expression that is used to extract parameters from paths
21052     //   that reached this accepting state.
21053     // * `handlers`: Information on how to convert the list of captures into calls
21054     //   to registered handlers with the specified parameters
21055     // * `types`: How many static, dynamic or star segments in this route. Used to
21056     //   decide which route to use if multiple registered routes match a path.
21057     //
21058     // Currently, State is implemented naively by looping over `nextStates` and
21059     // comparing a character specification against a character. A more efficient
21060     // implementation would use a hash of keys pointing at one or more next states.
21061
21062     function State(charSpec) {
21063       this.charSpec = charSpec;
21064       this.nextStates = [];
21065     }
21066
21067     State.prototype = {
21068       get: function(charSpec) {
21069         var nextStates = this.nextStates;
21070
21071         for (var i=0, l=nextStates.length; i<l; i++) {
21072           var child = nextStates[i];
21073
21074           var isEqual = child.charSpec.validChars === charSpec.validChars;
21075           isEqual = isEqual && child.charSpec.invalidChars === charSpec.invalidChars;
21076
21077           if (isEqual) { return child; }
21078         }
21079       },
21080
21081       put: function(charSpec) {
21082         var state;
21083
21084         // If the character specification already exists in a child of the current
21085         // state, just return that state.
21086         if (state = this.get(charSpec)) { return state; }
21087
21088         // Make a new state for the character spec
21089         state = new State(charSpec);
21090
21091         // Insert the new state as a child of the current state
21092         this.nextStates.push(state);
21093
21094         // If this character specification repeats, insert the new state as a child
21095         // of itself. Note that this will not trigger an infinite loop because each
21096         // transition during recognition consumes a character.
21097         if (charSpec.repeat) {
21098           state.nextStates.push(state);
21099         }
21100
21101         // Return the new state
21102         return state;
21103       },
21104
21105       // Find a list of child states matching the next character
21106       match: function(char) {
21107         // DEBUG "Processing `" + char + "`:"
21108         var nextStates = this.nextStates,
21109             child, charSpec, chars;
21110
21111         // DEBUG "  " + debugState(this)
21112         var returned = [];
21113
21114         for (var i=0, l=nextStates.length; i<l; i++) {
21115           child = nextStates[i];
21116
21117           charSpec = child.charSpec;
21118
21119           if (typeof (chars = charSpec.validChars) !== 'undefined') {
21120             if (chars.indexOf(char) !== -1) { returned.push(child); }
21121           } else if (typeof (chars = charSpec.invalidChars) !== 'undefined') {
21122             if (chars.indexOf(char) === -1) { returned.push(child); }
21123           }
21124         }
21125
21126         return returned;
21127       }
21128
21129       /** IF DEBUG
21130       , debug: function() {
21131         var charSpec = this.charSpec,
21132             debug = "[",
21133             chars = charSpec.validChars || charSpec.invalidChars;
21134
21135         if (charSpec.invalidChars) { debug += "^"; }
21136         debug += chars;
21137         debug += "]";
21138
21139         if (charSpec.repeat) { debug += "+"; }
21140
21141         return debug;
21142       }
21143       END IF **/
21144     };
21145
21146     /** IF DEBUG
21147     function debug(log) {
21148       console.log(log);
21149     }
21150
21151     function debugState(state) {
21152       return state.nextStates.map(function(n) {
21153         if (n.nextStates.length === 0) { return "( " + n.debug() + " [accepting] )"; }
21154         return "( " + n.debug() + " <then> " + n.nextStates.map(function(s) { return s.debug() }).join(" or ") + " )";
21155       }).join(", ")
21156     }
21157     END IF **/
21158
21159     // This is a somewhat naive strategy, but should work in a lot of cases
21160     // A better strategy would properly resolve /posts/:id/new and /posts/edit/:id
21161     function sortSolutions(states) {
21162       return states.sort(function(a, b) {
21163         if (a.types.stars !== b.types.stars) { return a.types.stars - b.types.stars; }
21164         if (a.types.dynamics !== b.types.dynamics) { return a.types.dynamics - b.types.dynamics; }
21165         if (a.types.statics !== b.types.statics) { return a.types.statics - b.types.statics; }
21166
21167         return 0;
21168       });
21169     }
21170
21171     function recognizeChar(states, char) {
21172       var nextStates = [];
21173
21174       for (var i=0, l=states.length; i<l; i++) {
21175         var state = states[i];
21176
21177         nextStates = nextStates.concat(state.match(char));
21178       }
21179
21180       return nextStates;
21181     }
21182
21183     function findHandler(state, path) {
21184       var handlers = state.handlers, regex = state.regex;
21185       var captures = path.match(regex), currentCapture = 1;
21186       var result = [];
21187
21188       for (var i=0, l=handlers.length; i<l; i++) {
21189         var handler = handlers[i], names = handler.names, params = {};
21190
21191         for (var j=0, m=names.length; j<m; j++) {
21192           params[names[j]] = captures[currentCapture++];
21193         }
21194
21195         result.push({ handler: handler.handler, params: params, isDynamic: !!names.length });
21196       }
21197
21198       return result;
21199     }
21200
21201     function addSegment(currentState, segment) {
21202       segment.eachChar(function(char) {
21203         var state;
21204
21205         currentState = currentState.put(char);
21206       });
21207
21208       return currentState;
21209     }
21210
21211     // The main interface
21212
21213     var RouteRecognizer = function() {
21214       this.rootState = new State();
21215       this.names = {};
21216     };
21217
21218
21219     RouteRecognizer.prototype = {
21220       add: function(routes, options) {
21221         var currentState = this.rootState, regex = "^",
21222             types = { statics: 0, dynamics: 0, stars: 0 },
21223             handlers = [], allSegments = [], name;
21224
21225         var isEmpty = true;
21226
21227         for (var i=0, l=routes.length; i<l; i++) {
21228           var route = routes[i], names = [];
21229
21230           var segments = parse(route.path, names, types);
21231
21232           allSegments = allSegments.concat(segments);
21233
21234           for (var j=0, m=segments.length; j<m; j++) {
21235             var segment = segments[j];
21236
21237             if (segment instanceof EpsilonSegment) { continue; }
21238
21239             isEmpty = false;
21240
21241             // Add a "/" for the new segment
21242             currentState = currentState.put({ validChars: "/" });
21243             regex += "/";
21244
21245             // Add a representation of the segment to the NFA and regex
21246             currentState = addSegment(currentState, segment);
21247             regex += segment.regex();
21248           }
21249
21250           handlers.push({ handler: route.handler, names: names });
21251         }
21252
21253         if (isEmpty) {
21254           currentState = currentState.put({ validChars: "/" });
21255           regex += "/";
21256         }
21257
21258         currentState.handlers = handlers;
21259         currentState.regex = new RegExp(regex + "$");
21260         currentState.types = types;
21261
21262         if (name = options && options.as) {
21263           this.names[name] = {
21264             segments: allSegments,
21265             handlers: handlers
21266           };
21267         }
21268       },
21269
21270       handlersFor: function(name) {
21271         var route = this.names[name], result = [];
21272         if (!route) { throw new Error("There is no route named " + name); }
21273
21274         for (var i=0, l=route.handlers.length; i<l; i++) {
21275           result.push(route.handlers[i]);
21276         }
21277
21278         return result;
21279       },
21280
21281       hasRoute: function(name) {
21282         return !!this.names[name];
21283       },
21284
21285       generate: function(name, params) {
21286         var route = this.names[name], output = "";
21287         if (!route) { throw new Error("There is no route named " + name); }
21288
21289         var segments = route.segments;
21290
21291         for (var i=0, l=segments.length; i<l; i++) {
21292           var segment = segments[i];
21293
21294           if (segment instanceof EpsilonSegment) { continue; }
21295
21296           output += "/";
21297           output += segment.generate(params);
21298         }
21299
21300         if (output.charAt(0) !== '/') { output = '/' + output; }
21301
21302         return output;
21303       },
21304
21305       recognize: function(path) {
21306         var states = [ this.rootState ], i, l;
21307
21308         // DEBUG GROUP path
21309
21310         var pathLen = path.length;
21311
21312         if (path.charAt(0) !== "/") { path = "/" + path; }
21313
21314         if (pathLen > 1 && path.charAt(pathLen - 1) === "/") {
21315           path = path.substr(0, pathLen - 1);
21316         }
21317
21318         for (i=0, l=path.length; i<l; i++) {
21319           states = recognizeChar(states, path.charAt(i));
21320           if (!states.length) { break; }
21321         }
21322
21323         // END DEBUG GROUP
21324
21325         var solutions = [];
21326         for (i=0, l=states.length; i<l; i++) {
21327           if (states[i].handlers) { solutions.push(states[i]); }
21328         }
21329
21330         states = sortSolutions(solutions);
21331
21332         var state = solutions[0];
21333
21334         if (state && state.handlers) {
21335           return findHandler(state, path);
21336         }
21337       }
21338     };
21339
21340     function Target(path, matcher, delegate) {
21341       this.path = path;
21342       this.matcher = matcher;
21343       this.delegate = delegate;
21344     }
21345
21346     Target.prototype = {
21347       to: function(target, callback) {
21348         var delegate = this.delegate;
21349
21350         if (delegate && delegate.willAddRoute) {
21351           target = delegate.willAddRoute(this.matcher.target, target);
21352         }
21353
21354         this.matcher.add(this.path, target);
21355
21356         if (callback) {
21357           if (callback.length === 0) { throw new Error("You must have an argument in the function passed to `to`"); }
21358           this.matcher.addChild(this.path, target, callback, this.delegate);
21359         }
21360       }
21361     };
21362
21363     function Matcher(target) {
21364       this.routes = {};
21365       this.children = {};
21366       this.target = target;
21367     }
21368
21369     Matcher.prototype = {
21370       add: function(path, handler) {
21371         this.routes[path] = handler;
21372       },
21373
21374       addChild: function(path, target, callback, delegate) {
21375         var matcher = new Matcher(target);
21376         this.children[path] = matcher;
21377
21378         var match = generateMatch(path, matcher, delegate);
21379
21380         if (delegate && delegate.contextEntered) {
21381           delegate.contextEntered(target, match);
21382         }
21383
21384         callback(match);
21385       }
21386     };
21387
21388     function generateMatch(startingPath, matcher, delegate) {
21389       return function(path, nestedCallback) {
21390         var fullPath = startingPath + path;
21391
21392         if (nestedCallback) {
21393           nestedCallback(generateMatch(fullPath, matcher, delegate));
21394         } else {
21395           return new Target(startingPath + path, matcher, delegate);
21396         }
21397       };
21398     }
21399
21400     function addRoute(routeArray, path, handler) {
21401       var len = 0;
21402       for (var i=0, l=routeArray.length; i<l; i++) {
21403         len += routeArray[i].path.length;
21404       }
21405
21406       path = path.substr(len);
21407       routeArray.push({ path: path, handler: handler });
21408     }
21409
21410     function eachRoute(baseRoute, matcher, callback, binding) {
21411       var routes = matcher.routes;
21412
21413       for (var path in routes) {
21414         if (routes.hasOwnProperty(path)) {
21415           var routeArray = baseRoute.slice();
21416           addRoute(routeArray, path, routes[path]);
21417
21418           if (matcher.children[path]) {
21419             eachRoute(routeArray, matcher.children[path], callback, binding);
21420           } else {
21421             callback.call(binding, routeArray);
21422           }
21423         }
21424       }
21425     }
21426
21427     RouteRecognizer.prototype.map = function(callback, addRouteCallback) {
21428       var matcher = new Matcher();
21429
21430       callback(generateMatch("", matcher, this.delegate));
21431
21432       eachRoute([], matcher, function(route) {
21433         if (addRouteCallback) { addRouteCallback(this, route); }
21434         else { this.add(route); }
21435       }, this);
21436     };
21437     return RouteRecognizer;
21438   });
21439
21440 })();
21441
21442
21443
21444 (function() {
21445 define("router",
21446   ["route-recognizer"],
21447   function(RouteRecognizer) {
21448     "use strict";
21449     /**
21450       @private
21451
21452       This file references several internal structures:
21453
21454       ## `RecognizedHandler`
21455
21456       * `{String} handler`: A handler name
21457       * `{Object} params`: A hash of recognized parameters
21458
21459       ## `UnresolvedHandlerInfo`
21460
21461       * `{Boolean} isDynamic`: whether a handler has any dynamic segments
21462       * `{String} name`: the name of a handler
21463       * `{Object} context`: the active context for the handler
21464
21465       ## `HandlerInfo`
21466
21467       * `{Boolean} isDynamic`: whether a handler has any dynamic segments
21468       * `{String} name`: the original unresolved handler name
21469       * `{Object} handler`: a handler object
21470       * `{Object} context`: the active context for the handler
21471     */
21472
21473
21474     function Router() {
21475       this.recognizer = new RouteRecognizer();
21476     }
21477
21478
21479     Router.prototype = {
21480       /**
21481         The main entry point into the router. The API is essentially
21482         the same as the `map` method in `route-recognizer`.
21483
21484         This method extracts the String handler at the last `.to()`
21485         call and uses it as the name of the whole route.
21486
21487         @param {Function} callback
21488       */
21489       map: function(callback) {
21490         this.recognizer.delegate = this.delegate;
21491
21492         this.recognizer.map(callback, function(recognizer, route) {
21493           var lastHandler = route[route.length - 1].handler;
21494           var args = [route, { as: lastHandler }];
21495           recognizer.add.apply(recognizer, args);
21496         });
21497       },
21498
21499       hasRoute: function(route) {
21500         return this.recognizer.hasRoute(route);
21501       },
21502
21503       /**
21504         The entry point for handling a change to the URL (usually
21505         via the back and forward button).
21506
21507         Returns an Array of handlers and the parameters associated
21508         with those parameters.
21509
21510         @param {String} url a URL to process
21511
21512         @return {Array} an Array of `[handler, parameter]` tuples
21513       */
21514       handleURL: function(url) {
21515         var results = this.recognizer.recognize(url),
21516             objects = [];
21517
21518         if (!results) {
21519           throw new Error("No route matched the URL '" + url + "'");
21520         }
21521
21522         collectObjects(this, results, 0, []);
21523       },
21524
21525       /**
21526         Hook point for updating the URL.
21527
21528         @param {String} url a URL to update to
21529       */
21530       updateURL: function() {
21531         throw "updateURL is not implemented";
21532       },
21533
21534       /**
21535         Hook point for replacing the current URL, i.e. with replaceState
21536
21537         By default this behaves the same as `updateURL`
21538
21539         @param {String} url a URL to update to
21540       */
21541       replaceURL: function(url) {
21542         this.updateURL(url);
21543       },
21544
21545       /**
21546         Transition into the specified named route.
21547
21548         If necessary, trigger the exit callback on any handlers
21549         that are no longer represented by the target route.
21550
21551         @param {String} name the name of the route
21552       */
21553       transitionTo: function(name) {
21554         var args = Array.prototype.slice.call(arguments, 1);
21555         doTransition(this, name, this.updateURL, args);
21556       },
21557
21558       /**
21559         Identical to `transitionTo` except that the current URL will be replaced
21560         if possible.
21561
21562         This method is intended primarily for use with `replaceState`.
21563
21564         @param {String} name the name of the route
21565       */
21566       replaceWith: function(name) {
21567         var args = Array.prototype.slice.call(arguments, 1);
21568         doTransition(this, name, this.replaceURL, args);
21569       },
21570
21571       /**
21572         @private
21573
21574         This method takes a handler name and a list of contexts and returns
21575         a serialized parameter hash suitable to pass to `recognizer.generate()`.
21576
21577         @param {String} handlerName
21578         @param {Array[Object]} contexts
21579         @return {Object} a serialized parameter hash
21580       */
21581       paramsForHandler: function(handlerName, callback) {
21582         var output = this._paramsForHandler(handlerName, [].slice.call(arguments, 1));
21583         return output.params;
21584       },
21585
21586       /**
21587         Take a named route and context objects and generate a
21588         URL.
21589
21590         @param {String} name the name of the route to generate
21591           a URL for
21592         @param {...Object} objects a list of objects to serialize
21593
21594         @return {String} a URL
21595       */
21596       generate: function(handlerName) {
21597         var params = this.paramsForHandler.apply(this, arguments);
21598         return this.recognizer.generate(handlerName, params);
21599       },
21600
21601       /**
21602         @private
21603
21604         Used internally by `generate` and `transitionTo`.
21605       */
21606       _paramsForHandler: function(handlerName, objects, doUpdate) {
21607         var handlers = this.recognizer.handlersFor(handlerName),
21608             params = {},
21609             toSetup = [],
21610             startIdx = handlers.length,
21611             objectsToMatch = objects.length,
21612             object, objectChanged, handlerObj, handler, names, i, len;
21613
21614         // Find out which handler to start matching at
21615         for (i=handlers.length-1; i>=0 && objectsToMatch>0; i--) {
21616           if (handlers[i].names.length) {
21617             objectsToMatch--;
21618             startIdx = i;
21619           }
21620         }
21621
21622         if (objectsToMatch > 0) {
21623           throw "More objects were passed than dynamic segments";
21624         }
21625
21626         // Connect the objects to the routes
21627         for (i=0, len=handlers.length; i<len; i++) {
21628           handlerObj = handlers[i];
21629           handler = this.getHandler(handlerObj.handler);
21630           names = handlerObj.names;
21631           objectChanged = false;
21632
21633           // If it's a dynamic segment
21634           if (names.length) {
21635             // If we have objects, use them
21636             if (i >= startIdx) {
21637               object = objects.shift();
21638               objectChanged = true;
21639             // Otherwise use existing context
21640             } else {
21641               object = handler.context;
21642             }
21643
21644             // Serialize to generate params
21645             if (handler.serialize) {
21646               merge(params, handler.serialize(object, names));
21647             }
21648           // If it's not a dynamic segment and we're updating
21649           } else if (doUpdate) {
21650             // If we've passed the match point we need to deserialize again
21651             // or if we never had a context
21652             if (i > startIdx || !handler.hasOwnProperty('context')) {
21653               if (handler.deserialize) {
21654                 object = handler.deserialize({});
21655                 objectChanged = true;
21656               }
21657             // Otherwise use existing context
21658             } else {
21659               object = handler.context;
21660             }
21661           }
21662
21663           // Make sure that we update the context here so it's available to
21664           // subsequent deserialize calls
21665           if (doUpdate && objectChanged) {
21666             // TODO: It's a bit awkward to set the context twice, see if we can DRY things up
21667             setContext(handler, object);
21668           }
21669
21670           toSetup.push({
21671             isDynamic: !!handlerObj.names.length,
21672             handler: handlerObj.handler,
21673             name: handlerObj.name,
21674             context: object
21675           });
21676         }
21677
21678         return { params: params, toSetup: toSetup };
21679       },
21680
21681       isActive: function(handlerName) {
21682         var contexts = [].slice.call(arguments, 1);
21683
21684         var currentHandlerInfos = this.currentHandlerInfos,
21685             found = false, names, object, handlerInfo, handlerObj;
21686
21687         for (var i=currentHandlerInfos.length-1; i>=0; i--) {
21688           handlerInfo = currentHandlerInfos[i];
21689           if (handlerInfo.name === handlerName) { found = true; }
21690
21691           if (found) {
21692             if (contexts.length === 0) { break; }
21693
21694             if (handlerInfo.isDynamic) {
21695               object = contexts.pop();
21696               if (handlerInfo.context !== object) { return false; }
21697             }
21698           }
21699         }
21700
21701         return contexts.length === 0 && found;
21702       },
21703
21704       trigger: function(name) {
21705         var args = [].slice.call(arguments);
21706         trigger(this, args);
21707       }
21708     };
21709
21710     function merge(hash, other) {
21711       for (var prop in other) {
21712         if (other.hasOwnProperty(prop)) { hash[prop] = other[prop]; }
21713       }
21714     }
21715
21716     function isCurrent(currentHandlerInfos, handlerName) {
21717       return currentHandlerInfos[currentHandlerInfos.length - 1].name === handlerName;
21718     }
21719
21720     /**
21721       @private
21722
21723       This function is called the first time the `collectObjects`
21724       function encounters a promise while converting URL parameters
21725       into objects.
21726
21727       It triggers the `enter` and `setup` methods on the `loading`
21728       handler.
21729
21730       @param {Router} router
21731     */
21732     function loading(router) {
21733       if (!router.isLoading) {
21734         router.isLoading = true;
21735         var handler = router.getHandler('loading');
21736
21737         if (handler) {
21738           if (handler.enter) { handler.enter(); }
21739           if (handler.setup) { handler.setup(); }
21740         }
21741       }
21742     }
21743
21744     /**
21745       @private
21746
21747       This function is called if a promise was previously
21748       encountered once all promises are resolved.
21749
21750       It triggers the `exit` method on the `loading` handler.
21751
21752       @param {Router} router
21753     */
21754     function loaded(router) {
21755       router.isLoading = false;
21756       var handler = router.getHandler('loading');
21757       if (handler && handler.exit) { handler.exit(); }
21758     }
21759
21760     /**
21761       @private
21762
21763       This function is called if any encountered promise
21764       is rejected.
21765
21766       It triggers the `exit` method on the `loading` handler,
21767       the `enter` method on the `failure` handler, and the
21768       `setup` method on the `failure` handler with the
21769       `error`.
21770
21771       @param {Router} router
21772       @param {Object} error the reason for the promise
21773         rejection, to pass into the failure handler's
21774         `setup` method.
21775     */
21776     function failure(router, error) {
21777       loaded(router);
21778       var handler = router.getHandler('failure');
21779       if (handler && handler.setup) { handler.setup(error); }
21780     }
21781
21782     /**
21783       @private
21784     */
21785     function doTransition(router, name, method, args) {
21786       var output = router._paramsForHandler(name, args, true);
21787       var params = output.params, toSetup = output.toSetup;
21788
21789       var url = router.recognizer.generate(name, params);
21790       method.call(router, url);
21791
21792       setupContexts(router, toSetup);
21793     }
21794
21795     /**
21796       @private
21797
21798       This function is called after a URL change has been handled
21799       by `router.handleURL`.
21800
21801       Takes an Array of `RecognizedHandler`s, and converts the raw
21802       params hashes into deserialized objects by calling deserialize
21803       on the handlers. This process builds up an Array of
21804       `HandlerInfo`s. It then calls `setupContexts` with the Array.
21805
21806       If the `deserialize` method on a handler returns a promise
21807       (i.e. has a method called `then`), this function will pause
21808       building up the `HandlerInfo` Array until the promise is
21809       resolved. It will use the resolved value as the context of
21810       `HandlerInfo`.
21811     */
21812     function collectObjects(router, results, index, objects) {
21813       if (results.length === index) {
21814         loaded(router);
21815         setupContexts(router, objects);
21816         return;
21817       }
21818
21819       var result = results[index];
21820       var handler = router.getHandler(result.handler);
21821       var object = handler.deserialize && handler.deserialize(result.params);
21822
21823       if (object && typeof object.then === 'function') {
21824         loading(router);
21825
21826         // The chained `then` means that we can also catch errors that happen in `proceed`
21827         object.then(proceed).then(null, function(error) {
21828           failure(router, error);
21829         });
21830       } else {
21831         proceed(object);
21832       }
21833
21834       function proceed(value) {
21835         if (handler.context !== object) {
21836           setContext(handler, object);
21837         }
21838
21839         var updatedObjects = objects.concat([{
21840           context: value,
21841           handler: result.handler,
21842           isDynamic: result.isDynamic
21843         }]);
21844         collectObjects(router, results, index + 1, updatedObjects);
21845       }
21846     }
21847
21848     /**
21849       @private
21850
21851       Takes an Array of `UnresolvedHandlerInfo`s, resolves the handler names
21852       into handlers, and then figures out what to do with each of the handlers.
21853
21854       For example, consider the following tree of handlers. Each handler is
21855       followed by the URL segment it handles.
21856
21857       ```
21858       |~index ("/")
21859       | |~posts ("/posts")
21860       | | |-showPost ("/:id")
21861       | | |-newPost ("/new")
21862       | | |-editPost ("/edit")
21863       | |~about ("/about/:id")
21864       ```
21865
21866       Consider the following transitions:
21867
21868       1. A URL transition to `/posts/1`.
21869          1. Triggers the `deserialize` callback on the
21870             `index`, `posts`, and `showPost` handlers
21871          2. Triggers the `enter` callback on the same
21872          3. Triggers the `setup` callback on the same
21873       2. A direct transition to `newPost`
21874          1. Triggers the `exit` callback on `showPost`
21875          2. Triggers the `enter` callback on `newPost`
21876          3. Triggers the `setup` callback on `newPost`
21877       3. A direct transition to `about` with a specified
21878          context object
21879          1. Triggers the `exit` callback on `newPost`
21880             and `posts`
21881          2. Triggers the `serialize` callback on `about`
21882          3. Triggers the `enter` callback on `about`
21883          4. Triggers the `setup` callback on `about`
21884
21885       @param {Router} router
21886       @param {Array[UnresolvedHandlerInfo]} handlerInfos
21887     */
21888     function setupContexts(router, handlerInfos) {
21889       resolveHandlers(router, handlerInfos);
21890
21891       var partition =
21892         partitionHandlers(router.currentHandlerInfos || [], handlerInfos);
21893
21894       router.currentHandlerInfos = handlerInfos;
21895
21896       eachHandler(partition.exited, function(handler, context) {
21897         delete handler.context;
21898         if (handler.exit) { handler.exit(); }
21899       });
21900
21901       eachHandler(partition.updatedContext, function(handler, context) {
21902         setContext(handler, context);
21903         if (handler.setup) { handler.setup(context); }
21904       });
21905
21906       eachHandler(partition.entered, function(handler, context) {
21907         if (handler.enter) { handler.enter(); }
21908         setContext(handler, context);
21909         if (handler.setup) { handler.setup(context); }
21910       });
21911
21912       if (router.didTransition) {
21913         router.didTransition(handlerInfos);
21914       }
21915     }
21916
21917     /**
21918       @private
21919
21920       Iterates over an array of `HandlerInfo`s, passing the handler
21921       and context into the callback.
21922
21923       @param {Array[HandlerInfo]} handlerInfos
21924       @param {Function(Object, Object)} callback
21925     */
21926     function eachHandler(handlerInfos, callback) {
21927       for (var i=0, l=handlerInfos.length; i<l; i++) {
21928         var handlerInfo = handlerInfos[i],
21929             handler = handlerInfo.handler,
21930             context = handlerInfo.context;
21931
21932         callback(handler, context);
21933       }
21934     }
21935
21936     /**
21937       @private
21938
21939       Updates the `handler` field in each element in an Array of
21940       `UnresolvedHandlerInfo`s from a handler name to a resolved handler.
21941
21942       When done, the Array will contain `HandlerInfo` structures.
21943
21944       @param {Router} router
21945       @param {Array[UnresolvedHandlerInfo]} handlerInfos
21946     */
21947     function resolveHandlers(router, handlerInfos) {
21948       var handlerInfo;
21949
21950       for (var i=0, l=handlerInfos.length; i<l; i++) {
21951         handlerInfo = handlerInfos[i];
21952
21953         handlerInfo.name = handlerInfo.handler;
21954         handlerInfo.handler = router.getHandler(handlerInfo.handler);
21955       }
21956     }
21957
21958     /**
21959       @private
21960
21961       This function is called when transitioning from one URL to
21962       another to determine which handlers are not longer active,
21963       which handlers are newly active, and which handlers remain
21964       active but have their context changed.
21965
21966       Take a list of old handlers and new handlers and partition
21967       them into four buckets:
21968
21969       * unchanged: the handler was active in both the old and
21970         new URL, and its context remains the same
21971       * updated context: the handler was active in both the
21972         old and new URL, but its context changed. The handler's
21973         `setup` method, if any, will be called with the new
21974         context.
21975       * exited: the handler was active in the old URL, but is
21976         no longer active.
21977       * entered: the handler was not active in the old URL, but
21978         is now active.
21979
21980       The PartitionedHandlers structure has three fields:
21981
21982       * `updatedContext`: a list of `HandlerInfo` objects that
21983         represent handlers that remain active but have a changed
21984         context
21985       * `entered`: a list of `HandlerInfo` objects that represent
21986         handlers that are newly active
21987       * `exited`: a list of `HandlerInfo` objects that are no
21988         longer active.
21989
21990       @param {Array[HandlerInfo]} oldHandlers a list of the handler
21991         information for the previous URL (or `[]` if this is the
21992         first handled transition)
21993       @param {Array[HandlerInfo]} newHandlers a list of the handler
21994         information for the new URL
21995
21996       @return {Partition}
21997     */
21998     function partitionHandlers(oldHandlers, newHandlers) {
21999       var handlers = {
22000             updatedContext: [],
22001             exited: [],
22002             entered: []
22003           };
22004
22005       var handlerChanged, contextChanged, i, l;
22006
22007       for (i=0, l=newHandlers.length; i<l; i++) {
22008         var oldHandler = oldHandlers[i], newHandler = newHandlers[i];
22009
22010         if (!oldHandler || oldHandler.handler !== newHandler.handler) {
22011           handlerChanged = true;
22012         }
22013
22014         if (handlerChanged) {
22015           handlers.entered.push(newHandler);
22016           if (oldHandler) { handlers.exited.unshift(oldHandler); }
22017         } else if (contextChanged || oldHandler.context !== newHandler.context) {
22018           contextChanged = true;
22019           handlers.updatedContext.push(newHandler);
22020         }
22021       }
22022
22023       for (i=newHandlers.length, l=oldHandlers.length; i<l; i++) {
22024         handlers.exited.unshift(oldHandlers[i]);
22025       }
22026
22027       return handlers;
22028     }
22029
22030     function trigger(router, args) {
22031       var currentHandlerInfos = router.currentHandlerInfos;
22032
22033       if (!currentHandlerInfos) {
22034         throw new Error("Could not trigger event. There are no active handlers");
22035       }
22036
22037       var name = args.shift();
22038
22039       for (var i=currentHandlerInfos.length-1; i>=0; i--) {
22040         var handlerInfo = currentHandlerInfos[i],
22041             handler = handlerInfo.handler;
22042
22043         if (handler.events && handler.events[name]) {
22044           handler.events[name].apply(handler, args);
22045           break;
22046         }
22047       }
22048     }
22049
22050     function setContext(handler, context) {
22051       handler.context = context;
22052       if (handler.contextDidChange) { handler.contextDidChange(); }
22053     }
22054     return Router;
22055   });
22056
22057 })();
22058
22059
22060
22061 (function() {
22062 /**
22063 @module ember
22064 @submodule ember-routing
22065 */
22066
22067 function DSL(name) {
22068   this.parent = name;
22069   this.matches = [];
22070 }
22071
22072 DSL.prototype = {
22073   resource: function(name, options, callback) {
22074     if (arguments.length === 2 && typeof options === 'function') {
22075       callback = options;
22076       options = {};
22077     }
22078
22079     if (arguments.length === 1) {
22080       options = {};
22081     }
22082
22083     if (typeof options.path !== 'string') {
22084       options.path = "/" + name;
22085     }
22086
22087     if (callback) {
22088       var dsl = new DSL(name);
22089       callback.call(dsl);
22090       this.push(options.path, name, dsl.generate());
22091     } else {
22092       this.push(options.path, name);
22093     }
22094   },
22095
22096   push: function(url, name, callback) {
22097     if (url === "" || url === "/") { this.explicitIndex = true; }
22098
22099     this.matches.push([url, name, callback]);
22100   },
22101
22102   route: function(name, options) {
22103     Ember.assert("You must use `this.resource` to nest", typeof options !== 'function');
22104
22105     options = options || {};
22106
22107     if (typeof options.path !== 'string') {
22108       options.path = "/" + name;
22109     }
22110
22111     if (this.parent && this.parent !== 'application') {
22112       name = this.parent + "." + name;
22113     }
22114
22115     this.push(options.path, name);
22116   },
22117
22118   generate: function() {
22119     var dslMatches = this.matches;
22120
22121     if (!this.explicitIndex) {
22122       this.route("index", { path: "/" });
22123     }
22124
22125     return function(match) {
22126       for (var i=0, l=dslMatches.length; i<l; i++) {
22127         var dslMatch = dslMatches[i];
22128         match(dslMatch[0]).to(dslMatch[1], dslMatch[2]);
22129       }
22130     };
22131   }
22132 };
22133
22134 DSL.map = function(callback) {
22135   var dsl = new DSL();
22136   callback.call(dsl);
22137   return dsl;
22138 };
22139
22140 Ember.RouterDSL = DSL;
22141
22142 })();
22143
22144
22145
22146 (function() {
22147 /**
22148 @module ember
22149 @submodule ember-routing
22150 */
22151
22152 Ember.controllerFor = function(container, controllerName, context) {
22153   return container.lookup('controller:' + controllerName) ||
22154          Ember.generateController(container, controllerName, context);
22155 };
22156
22157 Ember.generateController = function(container, controllerName, context) {
22158   var controller;
22159
22160   if (context && Ember.isArray(context)) {
22161     controller = Ember.ArrayController.extend({
22162       content: context
22163     });
22164   } else if (context) {
22165     controller = Ember.ObjectController.extend({
22166       content: context
22167     });
22168   } else {
22169     controller = Ember.Controller.extend();
22170   }
22171
22172   controller.toString = function() {
22173     return "(generated " + controllerName + " controller)";
22174   };
22175
22176   container.register('controller', controllerName, controller);
22177   return container.lookup('controller:' + controllerName);
22178 };
22179
22180 })();
22181
22182
22183
22184 (function() {
22185 /**
22186 @module ember
22187 @submodule ember-routing
22188 */
22189
22190 var Router = requireModule("router");
22191 var get = Ember.get, set = Ember.set, classify = Ember.String.classify;
22192
22193 var DefaultView = Ember.View.extend(Ember._Metamorph);
22194 function setupLocation(router) {
22195   var location = get(router, 'location'),
22196       rootURL = get(router, 'rootURL');
22197
22198   if ('string' === typeof location) {
22199     location = set(router, 'location', Ember.Location.create({
22200       implementation: location
22201     }));
22202
22203     if (typeof rootURL === 'string') {
22204       set(location, 'rootURL', rootURL);
22205     }
22206   }
22207 }
22208
22209 Ember.Router = Ember.Object.extend({
22210   location: 'hash',
22211
22212   init: function() {
22213     this.router = this.constructor.router;
22214     this._activeViews = {};
22215     setupLocation(this);
22216   },
22217
22218   startRouting: function() {
22219     this.router = this.router || this.constructor.map(Ember.K);
22220
22221     var router = this.router,
22222         location = get(this, 'location'),
22223         container = this.container,
22224         self = this;
22225
22226     setupRouter(this, router, location);
22227
22228     container.register('view', 'default', DefaultView);
22229     container.register('view', 'toplevel', Ember.View.extend());
22230
22231     router.handleURL(location.getURL());
22232     location.onUpdateURL(function(url) {
22233       router.handleURL(url);
22234     });
22235   },
22236
22237   didTransition: function(infos) {
22238     // Don't do any further action here if we redirected
22239     if (infos[infos.length-1].handler.transitioned) { return; }
22240
22241     var appController = this.container.lookup('controller:application'),
22242         path = routePath(infos);
22243
22244     set(appController, 'currentPath', path);
22245     this.notifyPropertyChange('url');
22246
22247     if (get(this, 'namespace').LOG_TRANSITIONS) {
22248       Ember.Logger.log("Transitioned into '" + path + "'");
22249     }
22250   },
22251
22252   handleURL: function(url) {
22253     this.router.handleURL(url);
22254     this.notifyPropertyChange('url');
22255   },
22256
22257   transitionTo: function(passedName) {
22258     var args = [].slice.call(arguments), name;
22259
22260     if (!this.router.hasRoute(passedName)) {
22261       name = args[0] = passedName + '.index';
22262     } else {
22263       name = passedName;
22264     }
22265
22266     Ember.assert("The route " + passedName + " was not found", this.router.hasRoute(name));
22267
22268     this.router.transitionTo.apply(this.router, args);
22269     this.notifyPropertyChange('url');
22270   },
22271
22272   replaceWith: function() {
22273     this.router.replaceWith.apply(this.router, arguments);
22274     this.notifyPropertyChange('url');
22275   },
22276
22277   generate: function() {
22278     var url = this.router.generate.apply(this.router, arguments);
22279     return this.location.formatURL(url);
22280   },
22281
22282   isActive: function(routeName) {
22283     var router = this.router;
22284     return router.isActive.apply(router, arguments);
22285   },
22286
22287   send: function(name, context) {
22288     if (Ember.$ && context instanceof Ember.$.Event) {
22289       context = context.context;
22290     }
22291
22292     this.router.trigger(name, context);
22293   },
22294
22295   hasRoute: function(route) {
22296     return this.router.hasRoute(route);
22297   },
22298
22299   _lookupActiveView: function(templateName) {
22300     var active = this._activeViews[templateName];
22301     return active && active[0];
22302   },
22303
22304   _connectActiveView: function(templateName, view) {
22305     var existing = this._activeViews[templateName];
22306
22307     if (existing) {
22308       existing[0].off('willDestroyElement', this, existing[1]);
22309     }
22310
22311     var disconnect = function() {
22312       delete this._activeViews[templateName];
22313     };
22314
22315     this._activeViews[templateName] = [view, disconnect];
22316     view.one('willDestroyElement', this, disconnect);
22317   }
22318 });
22319
22320 Ember.Router.reopenClass({
22321   defaultFailureHandler: {
22322     setup: function(error) {
22323       Ember.Logger.error('Error while loading route:', error);
22324
22325       // Using setTimeout allows us to escape from the Promise's try/catch block
22326       setTimeout(function() { throw error; });
22327     }
22328   }
22329 });
22330
22331 function getHandlerFunction(router) {
22332   var seen = {}, container = router.container;
22333
22334   return function(name) {
22335     var handler = container.lookup('route:' + name);
22336     if (seen[name]) { return handler; }
22337
22338     seen[name] = true;
22339
22340     if (!handler) {
22341       if (name === 'loading') { return {}; }
22342       if (name === 'failure') { return router.constructor.defaultFailureHandler; }
22343
22344       container.register('route', name, Ember.Route.extend());
22345       handler = container.lookup('route:' + name);
22346     }
22347
22348     handler.routeName = name;
22349     return handler;
22350   };
22351 }
22352
22353 function handlerIsActive(router, handlerName) {
22354   var handler = router.container.lookup('route:' + handlerName),
22355       currentHandlerInfos = router.router.currentHandlerInfos,
22356       handlerInfo;
22357
22358   for (var i=0, l=currentHandlerInfos.length; i<l; i++) {
22359     handlerInfo = currentHandlerInfos[i];
22360     if (handlerInfo.handler === handler) { return true; }
22361   }
22362
22363   return false;
22364 }
22365
22366 function routePath(handlerInfos) {
22367   var path = [];
22368
22369   for (var i=1, l=handlerInfos.length; i<l; i++) {
22370     var name = handlerInfos[i].name,
22371         nameParts = name.split(".");
22372
22373     path.push(nameParts[nameParts.length - 1]);
22374   }
22375
22376   return path.join(".");
22377 }
22378
22379 function setupRouter(emberRouter, router, location) {
22380   var lastURL;
22381
22382   router.getHandler = getHandlerFunction(emberRouter);
22383
22384   var doUpdateURL = function() {
22385     location.setURL(lastURL);
22386   };
22387
22388   router.updateURL = function(path) {
22389     lastURL = path;
22390     Ember.run.once(doUpdateURL);
22391   };
22392
22393   if (location.replaceURL) {
22394     var doReplaceURL = function() {
22395       location.replaceURL(lastURL);
22396     };
22397
22398     router.replaceURL = function(path) {
22399       lastURL = path;
22400       Ember.run.once(doReplaceURL);
22401     };
22402   }
22403
22404   router.didTransition = function(infos) {
22405     emberRouter.didTransition(infos);
22406   };
22407 }
22408
22409 Ember.Router.reopenClass({
22410   map: function(callback) {
22411     var router = this.router = new Router();
22412
22413     var dsl = Ember.RouterDSL.map(function() {
22414       this.resource('application', { path: "/" }, function() {
22415         callback.call(this);
22416       });
22417     });
22418
22419     router.map(dsl.generate());
22420     return router;
22421   }
22422 });
22423
22424 })();
22425
22426
22427
22428 (function() {
22429 /**
22430 @module ember
22431 @submodule ember-routing
22432 */
22433
22434 var get = Ember.get, set = Ember.set,
22435     classify = Ember.String.classify,
22436     decamelize = Ember.String.decamelize;
22437
22438
22439 Ember.Route = Ember.Object.extend({
22440   exit: function() {
22441     teardownView(this);
22442   },
22443
22444   /**
22445     Transition into another route. Optionally supply a model for the
22446     route in question. The model will be serialized into the URL
22447     using the `serialize` hook.
22448
22449     @method transitionTo
22450     @param {String} name the name of the route
22451     @param {...Object} models the
22452   */
22453   transitionTo: function() {
22454     this.transitioned = true;
22455     return this.router.transitionTo.apply(this.router, arguments);
22456   },
22457
22458   /**
22459     Transition into another route while replacing the current URL if
22460     possible. Identical to `transitionTo` in all other respects.
22461
22462     @method replaceWith
22463     @param {String} name the name of the route
22464     @param {...Object} models the
22465   */
22466   replaceWith: function() {
22467     this.transitioned = true;
22468     return this.router.replaceWith.apply(this.router, arguments);
22469   },
22470
22471   send: function() {
22472     return this.router.send.apply(this.router, arguments);
22473   },
22474
22475   /**
22476     @private
22477
22478     This hook is the entry point for router.js
22479
22480     @method setup
22481   */
22482   setup: function(context) {
22483     this.transitioned = false;
22484     this.redirect(context);
22485
22486     if (this.transitioned) { return; }
22487
22488     var controller = this.controllerFor(this.routeName, context);
22489
22490     if (controller) {
22491       set(controller, 'model', context);
22492     }
22493
22494     if (this.setupControllers) {
22495       Ember.deprecate("Ember.Route.setupControllers is deprecated. Please use Ember.Route.setupController(controller, model) instead.");
22496       this.setupControllers(controller, context);
22497     } else {
22498       this.setupController(controller, context);
22499     }
22500
22501     if (this.renderTemplates) {
22502       Ember.deprecate("Ember.Route.renderTemplates is deprecated. Please use Ember.Route.renderTemplate(controller, model) instead.");
22503       this.renderTemplates(context);
22504     } else {
22505       this.renderTemplate(controller, context);
22506     }
22507   },
22508
22509   /**
22510     A hook you can implement to optionally redirect to another route.
22511
22512     If you call `this.transitionTo` from inside of this hook, this route
22513     will not be entered in favor of the other hook.
22514
22515     @method redirect
22516     @param {Object} model the model for this route
22517   */
22518   redirect: Ember.K,
22519
22520   /**
22521     @private
22522
22523     The hook called by `router.js` to convert parameters into the context
22524     for this handler. The public Ember hook is `model`.
22525
22526     @method deserialize
22527   */
22528   deserialize: function(params) {
22529     var model = this.model(params);
22530     return this.currentModel = model;
22531   },
22532
22533   /**
22534     @private
22535
22536     Called when the context is changed by router.js.
22537   */
22538   contextDidChange: function() {
22539     this.currentModel = this.context;
22540   },
22541
22542   /**
22543     A hook you can implement to convert the URL into the model for
22544     this route.
22545
22546     ```js
22547     App.Route.map(function(match) {
22548       match("/posts/:post_id").to("post");
22549     });
22550     ```
22551
22552     The model for the `post` route is `App.Post.find(params.post_id)`.
22553
22554     By default, if your route has a dynamic segment ending in `_id`:
22555
22556     * The model class is determined from the segment (`post_id`'s
22557       class is `App.Post`)
22558     * The find method is called on the model class with the value of
22559       the dynamic segment.
22560
22561     @method model
22562     @param {Object} params the parameters extracted from the URL
22563   */
22564   model: function(params) {
22565     var match, name, value;
22566
22567     for (var prop in params) {
22568       if (match = prop.match(/^(.*)_id$/)) {
22569         name = match[1];
22570         value = params[prop];
22571       }
22572     }
22573
22574     if (!name) { return; }
22575
22576     var className = classify(name),
22577         namespace = this.router.namespace,
22578         modelClass = namespace[className];
22579
22580     Ember.assert("You used the dynamic segment " + name + "_id in your router, but " + namespace + "." + className + " did not exist and you did not override your state's `model` hook.", modelClass);
22581     return modelClass.find(value);
22582   },
22583
22584   /**
22585     A hook you can implement to convert the route's model into parameters
22586     for the URL.
22587
22588     ```js
22589     App.Route.map(function(match) {
22590       match("/posts/:post_id").to("post");
22591     });
22592
22593     App.PostRoute = Ember.Route.extend({
22594       model: function(params) {
22595         // the server returns `{ id: 12 }`
22596         return jQuery.getJSON("/posts/" + params.post_id);
22597       },
22598
22599       serialize: function(model) {
22600         // this will make the URL `/posts/12`
22601         return { post_id: model.id };
22602       }
22603     });
22604     ```
22605
22606     The default `serialize` method inserts the model's `id` into the
22607     route's dynamic segment (in this case, `:post_id`).
22608
22609     This method is called when `transitionTo` is called with a context
22610     in order to populate the URL.
22611
22612     @method serialize
22613     @param {Object} model the route's model
22614     @param {Array} params an Array of parameter names for the current
22615       route (in the example, `['post_id']`.
22616     @return {Object} the serialized parameters
22617   */
22618   serialize: function(model, params) {
22619     if (params.length !== 1) { return; }
22620
22621     var name = params[0], object = {};
22622     object[name] = get(model, 'id');
22623
22624     return object;
22625   },
22626
22627   /**
22628     A hook you can use to setup the controller for the current route.
22629
22630     This method is called with the controller for the current route and the
22631     model supplied by the `model` hook.
22632
22633     ```js
22634     App.Route.map(function(match) {
22635       match("/posts/:post_id").to("post");
22636     });
22637     ```
22638
22639     For the `post` route, the controller is `App.PostController`.
22640
22641     By default, the `setupController` hook sets the `content` property of
22642     the controller to the `model`.
22643
22644     If no explicit controller is defined, the route will automatically create
22645     an appropriate controller for the model:
22646
22647     * if the model is an `Ember.Array` (including record arrays from Ember
22648       Data), the controller is an `Ember.ArrayController`.
22649     * otherwise, the controller is an `Ember.ObjectController`.
22650
22651     This means that your template will get a proxy for the model as its
22652     context, and you can act as though the model itself was the context.
22653
22654     @method setupController
22655   */
22656   setupController: Ember.K,
22657
22658   /**
22659     Returns the controller for a particular route.
22660
22661     ```js
22662     App.PostRoute = Ember.Route.extend({
22663       setupController: function(controller, post) {
22664         this._super(controller, post);
22665         this.controllerFor('posts').set('currentPost', post);
22666       }
22667     });
22668     ```
22669
22670     By default, the controller for `post` is the shared instance of
22671     `App.PostController`.
22672
22673     @method controllerFor
22674     @param {String} name the name of the route
22675     @param {Object} model the model associated with the route (optional)
22676     @return {Ember.Controller}
22677   */
22678   controllerFor: function(name, model) {
22679     var container = this.router.container,
22680         controller = container.lookup('controller:' + name);
22681
22682     if (!controller) {
22683       model = model || this.modelFor(name);
22684
22685       Ember.assert("You are trying to look up a controller that you did not define, and for which Ember does not know the model.\n\nThis is not a controller for a route, so you must explicitly define the controller ("+this.router.namespace.toString() + "." + Ember.String.capitalize(Ember.String.camelize(name))+"Controller) or pass a model as the second parameter to `controllerFor`, so that Ember knows which type of controller to create for you.", model || this.container.lookup('route:' + name));
22686
22687       controller = Ember.generateController(container, name, model);
22688     }
22689
22690     return controller;
22691   },
22692
22693   /**
22694     Returns the current model for a given route.
22695
22696     This is the object returned by the `model` hook of the route
22697     in question.
22698
22699     @method modelFor
22700     @param {String} name the name of the route
22701     @return {Object} the model object
22702   */
22703   modelFor: function(name) {
22704     var route = this.container.lookup('route:' + name);
22705     return route && route.currentModel;
22706   },
22707
22708   /**
22709     A hook you can use to render the template for the current route.
22710
22711     This method is called with the controller for the current route and the
22712     model supplied by the `model` hook. By default, it renders the route's
22713     template, configured with the controller for the route.
22714
22715     This method can be overridden to set up and render additional or
22716     alternative templates.
22717
22718     @method renderTemplate
22719     @param {Object} controller the route's controller
22720     @param {Object} model the route's model
22721   */
22722   renderTemplate: function(controller, model) {
22723     this.render();
22724   },
22725
22726   /**
22727     Renders a template into an outlet.
22728
22729     This method has a number of defaults, based on the name of the
22730     route specified in the router.
22731
22732     For example:
22733
22734     ```js
22735     App.Router.map(function(match) {
22736       match("/").to("index");
22737       match("/posts/:post_id").to("post");
22738     });
22739
22740     App.PostRoute = App.Route.extend({
22741       renderTemplate: function() {
22742         this.render();
22743       }
22744     });
22745     ```
22746
22747     The name of the `PostRoute`, as defined by the router, is `post`.
22748
22749     By default, render will:
22750
22751     * render the `post` template
22752     * with the `post` view (`PostView`) for event handling, if one exists
22753     * and the `post` controller (`PostController`), if one exists
22754     * into the `main` outlet of the `application` template
22755
22756     You can override this behavior:
22757
22758     ```js
22759     App.PostRoute = App.Route.extend({
22760       renderTemplate: function() {
22761         this.render('myPost', {   // the template to render
22762           into: 'index',          // the template to render into
22763           outlet: 'detail',       // the name of the outlet in that template
22764           controller: 'blogPost'  // the controller to use for the template
22765         });
22766       }
22767     });
22768     ```
22769
22770     Remember that the controller's `content` will be the route's model. In
22771     this case, the default model will be `App.Post.find(params.post_id)`.
22772
22773     @method render
22774     @param {String} name the name of the template to render
22775     @param {Object} options the options
22776   */
22777   render: function(name, options) {
22778     if (typeof name === 'object' && !options) {
22779       options = name;
22780       name = this.routeName;
22781     }
22782
22783     name = name ? name.replace(/\//g, '.') : this.routeName;
22784
22785     var container = this.container,
22786         view = container.lookup('view:' + name),
22787         template = container.lookup('template:' + name);
22788
22789     if (!view && !template) { return; }
22790
22791     this.lastRenderedTemplate = name;
22792
22793     options = normalizeOptions(this, name, template, options);
22794     view = setupView(view, container, options);
22795
22796     appendView(this, view, options);
22797   }
22798 });
22799
22800 function parentRoute(route) {
22801   var handlerInfos = route.router.router.currentHandlerInfos;
22802
22803   var parent, current;
22804
22805   for (var i=0, l=handlerInfos.length; i<l; i++) {
22806     current = handlerInfos[i].handler;
22807     if (current === route) { return parent; }
22808     parent = current;
22809   }
22810 }
22811
22812 function parentTemplate(route) {
22813   var parent = parentRoute(route), template;
22814
22815   if (!parent) { return; }
22816
22817   if (template = parent.lastRenderedTemplate) {
22818     return template;
22819   } else {
22820     return parentTemplate(parent);
22821   }
22822 }
22823
22824 function normalizeOptions(route, name, template, options) {
22825   options = options || {};
22826   options.into = options.into ? options.into.replace(/\//g, '.') : parentTemplate(route);
22827   options.outlet = options.outlet || 'main';
22828   options.name = name;
22829   options.template = template;
22830
22831   var controller = options.controller, namedController;
22832
22833   if (options.controller) {
22834     controller = options.controller;
22835   } else if (namedController = route.container.lookup('controller:' + name)) {
22836     controller = namedController;
22837   } else {
22838     controller = route.routeName;
22839   }
22840
22841   if (typeof controller === 'string') {
22842     controller = route.container.lookup('controller:' + controller);
22843   }
22844
22845   options.controller = controller;
22846
22847   return options;
22848 }
22849
22850 function setupView(view, container, options) {
22851   var defaultView = options.into ? 'view:default' : 'view:toplevel';
22852
22853   view = view || container.lookup(defaultView);
22854
22855   if (!get(view, 'templateName')) {
22856     set(view, 'template', options.template);
22857   }
22858
22859   set(view, 'renderedName', options.name);
22860   set(view, 'controller', options.controller);
22861
22862   return view;
22863 }
22864
22865 function appendView(route, view, options) {
22866   if (options.into) {
22867     var parentView = route.router._lookupActiveView(options.into);
22868     route.teardownView = teardownOutlet(parentView, options.outlet);
22869     parentView.connectOutlet(options.outlet, view);
22870   } else {
22871     var rootElement = get(route, 'router.namespace.rootElement');
22872     route.router._connectActiveView(options.name, view);
22873     route.teardownView = teardownTopLevel(view);
22874     view.appendTo(rootElement);
22875   }
22876 }
22877
22878 function teardownTopLevel(view) {
22879   return function() { view.remove(); };
22880 }
22881
22882 function teardownOutlet(parentView, outlet) {
22883   return function() { parentView.disconnectOutlet(outlet); };
22884 }
22885
22886 function teardownView(route) {
22887   if (route.teardownView) { route.teardownView(); }
22888
22889   delete route.teardownView;
22890   delete route.lastRenderedTemplate;
22891 }
22892
22893 })();
22894
22895
22896
22897 (function() {
22898
22899 })();
22900
22901
22902
22903 (function() {
22904 var get = Ember.get, set = Ember.set;
22905 Ember.onLoad('Ember.Handlebars', function(Handlebars) {
22906
22907   var resolvePaths = Ember.Handlebars.resolvePaths,
22908       isSimpleClick = Ember.ViewUtils.isSimpleClick;
22909
22910   function fullRouteName(router, name) {
22911     if (!router.hasRoute(name)) {
22912       name = name + '.index';
22913     }
22914
22915     return name;
22916   }
22917
22918   function resolvedPaths(linkView) {
22919     return resolvePaths(linkView.parameters);
22920   }
22921
22922   function args(linkView, router, route) {
22923     var passedRouteName = route || linkView.namedRoute, routeName;
22924
22925     routeName = fullRouteName(router, passedRouteName);
22926
22927     Ember.assert("The route " + passedRouteName + " was not found", router.hasRoute(routeName));
22928
22929     var ret = [ routeName ];
22930     return ret.concat(resolvePaths(linkView.parameters));
22931   }
22932
22933   var LinkView = Ember.View.extend({
22934     tagName: 'a',
22935     namedRoute: null,
22936     currentWhen: null,
22937     title: null,
22938     activeClass: 'active',
22939     replace: false,
22940     attributeBindings: ['href', 'title'],
22941     classNameBindings: 'active',
22942
22943     active: Ember.computed(function() {
22944       var router = this.get('router'),
22945           params = resolvedPaths(this),
22946           currentWithIndex = this.currentWhen + '.index',
22947           isActive = router.isActive.apply(router, [this.currentWhen].concat(params)) ||
22948                      router.isActive.apply(router, [currentWithIndex].concat(params));
22949
22950       if (isActive) { return get(this, 'activeClass'); }
22951     }).property('namedRoute', 'router.url'),
22952
22953     router: Ember.computed(function() {
22954       return this.get('controller').container.lookup('router:main');
22955     }),
22956
22957     click: function(event) {
22958       if (!isSimpleClick(event)) { return true; }
22959
22960       event.preventDefault();
22961       if (this.bubbles === false) { event.stopPropagation(); }
22962
22963       var router = this.get('router');
22964
22965       if (this.get('replace')) {
22966         router.replaceWith.apply(router, args(this, router));
22967       } else {
22968         router.transitionTo.apply(router, args(this, router));
22969       }
22970     },
22971
22972     href: Ember.computed(function() {
22973       var router = this.get('router');
22974       return router.generate.apply(router, args(this, router));
22975     })
22976   });
22977
22978   LinkView.toString = function() { return "LinkView"; };
22979
22980   Ember.Handlebars.registerHelper('linkTo', function(name) {
22981     var options = [].slice.call(arguments, -1)[0];
22982     var contexts = [].slice.call(arguments, 1, -1);
22983
22984     var hash = options.hash;
22985
22986     hash.namedRoute = name;
22987     hash.currentWhen = hash.currentWhen || name;
22988
22989     hash.parameters = {
22990       data: options.data,
22991       contexts: contexts,
22992       roots: options.contexts
22993     };
22994
22995     return Ember.Handlebars.helpers.view.call(this, LinkView, options);
22996   });
22997
22998 });
22999
23000
23001 })();
23002
23003
23004
23005 (function() {
23006 /**
23007 @module ember
23008 @submodule ember-routing
23009 */
23010
23011 var get = Ember.get, set = Ember.set;
23012 Ember.onLoad('Ember.Handlebars', function(Handlebars) {
23013   /**
23014   @module ember
23015   @submodule ember-handlebars
23016   */
23017
23018   Handlebars.OutletView = Ember.ContainerView.extend(Ember._Metamorph);
23019
23020   /**
23021     The `outlet` helper allows you to specify that the current
23022     view's controller will fill in the view for a given area.
23023
23024     ``` handlebars
23025     {{outlet}}
23026     ```
23027
23028     By default, when the the current controller's `view` property changes, the
23029     outlet will replace its current view with the new view. You can set the
23030     `view` property directly, but it's normally best to use `connectOutlet`.
23031
23032     ``` javascript
23033     # Instantiate App.PostsView and assign to `view`, so as to render into outlet.
23034     controller.connectOutlet('posts');
23035     ```
23036
23037     You can also specify a particular name other than `view`:
23038
23039     ``` handlebars
23040     {{outlet masterView}}
23041     {{outlet detailView}}
23042     ```
23043
23044     Then, you can control several outlets from a single controller.
23045
23046     ``` javascript
23047     # Instantiate App.PostsView and assign to controller.masterView.
23048     controller.connectOutlet('masterView', 'posts');
23049     # Also, instantiate App.PostInfoView and assign to controller.detailView.
23050     controller.connectOutlet('detailView', 'postInfo');
23051     ```
23052
23053     @method outlet
23054     @for Ember.Handlebars.helpers
23055     @param {String} property the property on the controller
23056       that holds the view for this outlet
23057   */
23058   Handlebars.registerHelper('outlet', function(property, options) {
23059     var outletSource;
23060
23061     if (property && property.data && property.data.isRenderData) {
23062       options = property;
23063       property = 'main';
23064     }
23065
23066     outletSource = options.data.view;
23067     while (!(outletSource.get('template.isTop'))){
23068       outletSource = outletSource.get('_parentView');
23069     }
23070
23071     options.data.view.set('outletSource', outletSource);
23072     options.hash.currentViewBinding = '_view.outletSource._outlets.' + property;
23073
23074     return Handlebars.helpers.view.call(this, Handlebars.OutletView, options);
23075   });
23076
23077   Ember.View.reopen({
23078     init: function() {
23079       set(this, '_outlets', {});
23080       this._super();
23081     },
23082
23083     connectOutlet: function(outletName, view) {
23084       var outlets = get(this, '_outlets'),
23085           container = get(this, 'container'),
23086           router = container && container.lookup('router:main'),
23087           oldView = get(outlets, outletName),
23088           renderedName = get(view, 'renderedName');
23089
23090       set(outlets, outletName, view);
23091
23092       if (router) {
23093         if (oldView) {
23094           router._disconnectActiveView(oldView);
23095         }
23096         if (renderedName) {
23097           router._connectActiveView(renderedName, view);
23098         }
23099       }
23100     },
23101
23102     disconnectOutlet: function(outletName) {
23103       var outlets = get(this, '_outlets'),
23104           container = get(this, 'container'),
23105           router = container && container.lookup('router:main'),
23106           view = get(outlets, outletName);
23107
23108       set(outlets, outletName, null);
23109
23110       if (router && view) {
23111         router._disconnectActiveView(view);
23112       }
23113     }
23114   });
23115 });
23116
23117 })();
23118
23119
23120
23121 (function() {
23122 /**
23123 @module ember
23124 @submodule ember-routing
23125 */
23126
23127 var get = Ember.get, set = Ember.set;
23128 Ember.onLoad('Ember.Handlebars', function(Handlebars) {
23129
23130   Ember.Handlebars.registerHelper('render', function(name, context, options) {
23131     Ember.assert("You must pass a template to render", arguments.length >= 2);
23132     var container, router, controller, view;
23133
23134     if (arguments.length === 2) {
23135       options = context;
23136       context = undefined;
23137     }
23138
23139     if (typeof context === 'string') {
23140       context = Ember.Handlebars.get(options.contexts[1], context, options);
23141     }
23142
23143     name = name.replace(/\//g, '.');
23144     container = options.data.keywords.controller.container;
23145     router = container.lookup('router:main');
23146
23147     Ember.assert("This view is already rendered", !router || !router._lookupActiveView(name));
23148
23149     view = container.lookup('view:' + name) || container.lookup('view:default');
23150
23151     if (controller = options.hash.controller) {
23152       controller = container.lookup('controller:' + controller);
23153     } else {
23154       controller = Ember.controllerFor(container, name, context);
23155     }
23156
23157     if (controller && context) {
23158       controller.set('model', context);
23159     }
23160
23161     controller.set('target', options.data.keywords.controller);
23162
23163     options.hash.viewName = Ember.String.camelize(name);
23164     options.hash.template = container.lookup('template:' + name);
23165     options.hash.controller = controller;
23166
23167     if (router) {
23168       router._connectActiveView(name, view);
23169     }
23170
23171     Ember.Handlebars.helpers.view.call(this, view, options);
23172   });
23173
23174 });
23175
23176 })();
23177
23178
23179
23180 (function() {
23181 /**
23182 @module ember
23183 @submodule ember-routing
23184 */
23185 Ember.onLoad('Ember.Handlebars', function(Handlebars) {
23186
23187   var resolvePaths = Ember.Handlebars.resolvePaths,
23188       isSimpleClick = Ember.ViewUtils.isSimpleClick;
23189
23190   var EmberHandlebars = Ember.Handlebars,
23191       handlebarsGet = EmberHandlebars.get,
23192       SafeString = EmberHandlebars.SafeString,
23193       get = Ember.get,
23194       a_slice = Array.prototype.slice;
23195
23196   function args(options, actionName) {
23197     var ret = [];
23198     if (actionName) { ret.push(actionName); }
23199     return ret.concat(resolvePaths(options.parameters));
23200   }
23201
23202   var ActionHelper = EmberHandlebars.ActionHelper = {
23203     registeredActions: {}
23204   };
23205
23206   ActionHelper.registerAction = function(actionName, options) {
23207     var actionId = (++Ember.uuid).toString();
23208
23209     ActionHelper.registeredActions[actionId] = {
23210       eventName: options.eventName,
23211       handler: function(event) {
23212         if (!isSimpleClick(event)) { return true; }
23213         event.preventDefault();
23214
23215         if (options.bubbles === false) {
23216           event.stopPropagation();
23217         }
23218
23219         var view = options.view,
23220             contexts = options.contexts,
23221             target = options.target;
23222
23223         if (target.send) {
23224           return target.send.apply(target, args(options, actionName));
23225         } else {
23226           Ember.assert("The action '" + actionName + "' did not exist on " + target, typeof target[actionName] === 'function');
23227           return target[actionName].apply(target, args(options));
23228         }
23229       }
23230     };
23231
23232     options.view.on('willClearRender', function() {
23233       delete ActionHelper.registeredActions[actionId];
23234     });
23235
23236     return actionId;
23237   };
23238
23239   /**
23240     The `{{action}}` helper registers an HTML element within a template for DOM
23241     event handling and forwards that interaction to the view's controller
23242     or supplied `target` option (see 'Specifying a Target').
23243
23244     If the view's controller does not implement the event, the event is sent
23245     to the current route, and it bubbles up the route hierarchy from there.
23246
23247     User interaction with that element will invoke the supplied action name on
23248     the appropriate target.
23249
23250     Given the following Handlebars template on the page
23251
23252     ```handlebars
23253     <script type="text/x-handlebars" data-template-name='a-template'>
23254       <div {{action anActionName}}>
23255         click me
23256       </div>
23257     </script>
23258     ```
23259
23260     And application code
23261
23262     ```javascript
23263     AController = Ember.Controller.extend({
23264       anActionName: function() {}
23265     });
23266
23267     AView = Ember.View.extend({
23268       controller: AController.create(),
23269       templateName: 'a-template'
23270     });
23271
23272     aView = AView.create();
23273     aView.appendTo('body');
23274     ```
23275
23276     Will results in the following rendered HTML
23277
23278     ```html
23279     <div class="ember-view">
23280       <div data-ember-action="1">
23281         click me
23282       </div>
23283     </div>
23284     ```
23285
23286     Clicking "click me" will trigger the `anActionName` method of the
23287     `AController`. In this case, no additional parameters will be passed.
23288
23289     If you provide additional parameters to the helper:
23290
23291     ```handlebars
23292     <button {{action 'edit' post}}>Edit</button>
23293     ```
23294
23295     Those parameters will be passed along as arguments to the JavaScript
23296     function implementing the action.
23297
23298     ### Event Propagation
23299
23300     Events triggered through the action helper will automatically have
23301     `.preventDefault()` called on them. You do not need to do so in your event
23302     handlers.
23303
23304     To also disable bubbling, pass `bubbles=false` to the helper:
23305
23306     ```handlebars
23307     <button {{action 'edit' post bubbles=false}}>Edit</button>
23308     ```
23309
23310     If you need the default handler to trigger you should either register your
23311     own event handler, or use event methods on your view class. See `Ember.View`
23312     'Responding to Browser Events' for more information.
23313
23314     ### Specifying DOM event type
23315
23316     By default the `{{action}}` helper registers for DOM `click` events. You can
23317     supply an `on` option to the helper to specify a different DOM event name:
23318
23319     ```handlebars
23320     <script type="text/x-handlebars" data-template-name='a-template'>
23321       <div {{action anActionName on="doubleClick"}}>
23322         click me
23323       </div>
23324     </script>
23325     ```
23326
23327     See `Ember.View` 'Responding to Browser Events' for a list of
23328     acceptable DOM event names.
23329
23330     NOTE: Because `{{action}}` depends on Ember's event dispatch system it will
23331     only function if an `Ember.EventDispatcher` instance is available. An
23332     `Ember.EventDispatcher` instance will be created when a new `Ember.Application`
23333     is created. Having an instance of `Ember.Application` will satisfy this
23334     requirement.
23335
23336     ### Specifying a Target
23337
23338     There are several possible target objects for `{{action}}` helpers:
23339
23340     In a typical Ember application, where views are managed through use of the
23341     `{{outlet}}` helper, actions will bubble to the current controller, then
23342     to the current route, and then up the route hierarchy.
23343
23344     Alternatively, a `target` option can be provided to the helper to change
23345     which object will receive the method call. This option must be a path
23346     path to an object, accessible in the current context:
23347
23348     ```handlebars
23349     <script type="text/x-handlebars" data-template-name='a-template'>
23350       <div {{action anActionName target="MyApplication.someObject"}}>
23351         click me
23352       </div>
23353     </script>
23354     ```
23355
23356     Clicking "click me" in the rendered HTML of the above template will trigger
23357     the  `anActionName` method of the object at `MyApplication.someObject`.
23358
23359     If an action's target does not implement a method that matches the supplied
23360     action name an error will be thrown.
23361
23362     ```handlebars
23363     <script type="text/x-handlebars" data-template-name='a-template'>
23364       <div {{action aMethodNameThatIsMissing}}>
23365         click me
23366       </div>
23367     </script>
23368     ```
23369
23370     With the following application code
23371
23372     ```javascript
23373     AView = Ember.View.extend({
23374       templateName; 'a-template',
23375       // note: no method 'aMethodNameThatIsMissing'
23376       anActionName: function(event) {}
23377     });
23378
23379     aView = AView.create();
23380     aView.appendTo('body');
23381     ```
23382
23383     Will throw `Uncaught TypeError: Cannot call method 'call' of undefined` when
23384     "click me" is clicked.
23385
23386     ### Additional Parameters
23387
23388     You may specify additional parameters to the `{{action}}` helper. These
23389     parameters are passed along as the arguments to the JavaScript function
23390     implementing the action.
23391
23392     ```handlebars
23393     <script type="text/x-handlebars" data-template-name='a-template'>
23394       {{#each person in people}}
23395         <div {{action edit person}}>
23396           click me
23397         </div>
23398       {{/each}}
23399     </script>
23400     ```
23401
23402     Clicking "click me" will trigger the `edit` method on the current view's
23403     controller with the current person as a parameter.
23404
23405     @method action
23406     @for Ember.Handlebars.helpers
23407     @param {String} actionName
23408     @param {Object...} contexts
23409     @param {Hash} options
23410   */
23411   EmberHandlebars.registerHelper('action', function(actionName) {
23412     var options = arguments[arguments.length - 1],
23413         contexts = a_slice.call(arguments, 1, -1);
23414
23415     var hash = options.hash,
23416         view = options.data.view,
23417         target, controller, link;
23418
23419     // create a hash to pass along to registerAction
23420     var action = {
23421       eventName: hash.on || "click"
23422     };
23423
23424     action.parameters = {
23425       data: options.data,
23426       contexts: contexts,
23427       roots: options.contexts
23428     };
23429
23430     action.view = view = get(view, 'concreteView');
23431
23432     if (hash.target) {
23433       target = handlebarsGet(this, hash.target, options);
23434     } else if (controller = options.data.keywords.controller) {
23435       target = controller;
23436     }
23437
23438     action.target = target;
23439     action.bubbles = hash.bubbles;
23440
23441     var actionId = ActionHelper.registerAction(actionName, action);
23442     return new SafeString('data-ember-action="' + actionId + '"');
23443   });
23444
23445 });
23446
23447 })();
23448
23449
23450
23451 (function() {
23452
23453 })();
23454
23455
23456
23457 (function() {
23458 /**
23459 @module ember
23460 @submodule ember-routing
23461 */
23462
23463 var get = Ember.get, set = Ember.set;
23464 var ControllersProxy = Ember.Object.extend({
23465   controller: null,
23466
23467   unknownProperty: function(controllerName) {
23468     var controller = get(this, 'controller'),
23469       needs = get(controller, 'needs'),
23470       dependency;
23471
23472     for (var i=0, l=needs.length; i<l; i++) {
23473       dependency = needs[i];
23474       if (dependency === controllerName) {
23475         return controller.controllerFor(controllerName);
23476       }
23477     }
23478   }
23479 });
23480
23481 Ember.ControllerMixin.reopen({
23482   concatenatedProperties: ['needs'],
23483   needs: [],
23484
23485   init: function() {
23486     this._super.apply(this, arguments);
23487
23488     // Structure asserts to still do verification but not string concat in production
23489     if(!verifyDependencies(this)) {
23490       Ember.assert("Missing dependencies", false);
23491     }
23492   },
23493
23494   transitionToRoute: function() {
23495     var target = get(this, 'target');
23496
23497     return target.transitionTo.apply(target, arguments);
23498   },
23499
23500   // TODO: Deprecate this, see https://github.com/emberjs/ember.js/issues/1785
23501   transitionTo: function() {
23502     return this.transitionToRoute.apply(this, arguments);
23503   },
23504
23505   replaceRoute: function() {
23506     var target = get(this, 'target');
23507
23508     return target.replaceWith.apply(target, arguments);
23509   },
23510
23511   // TODO: Deprecate this, see https://github.com/emberjs/ember.js/issues/1785
23512   replaceWith: function() {
23513     return this.replaceRoute.apply(this, arguments);
23514   },
23515
23516   controllerFor: function(controllerName) {
23517     var container = get(this, 'container');
23518     return container.lookup('controller:' + controllerName);
23519   },
23520
23521   model: Ember.computed(function(key, value) {
23522     if (arguments.length > 1) {
23523       return set(this, 'content', value);
23524     } else {
23525       return get(this, 'content');
23526     }
23527   }).property('content'),
23528
23529   controllers: Ember.computed(function() {
23530     return ControllersProxy.create({ controller: this });
23531   })
23532 });
23533
23534 function verifyDependencies(controller) {
23535   var needs = get(controller, 'needs'),
23536       container = get(controller, 'container'),
23537       dependency, satisfied = true;
23538
23539   for (var i=0, l=needs.length; i<l; i++) {
23540     dependency = needs[i];
23541     if (dependency.indexOf(':') === -1) {
23542       dependency = "controller:" + dependency;
23543     }
23544
23545     if (!container.has(dependency)) {
23546       satisfied = false;
23547       Ember.assert(controller + " needs " + dependency + " but it does not exist", false);
23548     }
23549   }
23550
23551   return satisfied;
23552 }
23553
23554 })();
23555
23556
23557
23558 (function() {
23559 /**
23560 @module ember
23561 @submodule ember-routing
23562 */
23563
23564 var get = Ember.get, set = Ember.set;
23565
23566 Ember.View.reopen({
23567   init: function() {
23568     set(this, '_outlets', {});
23569     this._super();
23570   },
23571
23572   connectOutlet: function(outletName, view) {
23573     var outlets = get(this, '_outlets'),
23574         container = get(this, 'container'),
23575         router = container && container.lookup('router:main'),
23576         renderedName = get(view, 'renderedName');
23577
23578     set(outlets, outletName, view);
23579
23580     if (router && renderedName) {
23581       router._connectActiveView(renderedName, view);
23582     }
23583   },
23584
23585   disconnectOutlet: function(outletName) {
23586     var outlets = get(this, '_outlets');
23587
23588     set(outlets, outletName, null);
23589   }
23590 });
23591
23592 })();
23593
23594
23595
23596 (function() {
23597
23598 })();
23599
23600
23601
23602 (function() {
23603 /**
23604 @module ember
23605 @submodule ember-routing
23606 */
23607
23608 var get = Ember.get, set = Ember.set;
23609
23610 /*
23611   This file implements the `location` API used by Ember's router.
23612
23613   That API is:
23614
23615   getURL: returns the current URL
23616   setURL(path): sets the current URL
23617   replaceURL(path): replace the current URL (optional)
23618   onUpdateURL(callback): triggers the callback when the URL changes
23619   formatURL(url): formats `url` to be placed into `href` attribute
23620
23621   Calling setURL or replaceURL will not trigger onUpdateURL callbacks.
23622
23623   TODO: This should perhaps be moved so that it's visible in the doc output.
23624 */
23625
23626 /**
23627   Ember.Location returns an instance of the correct implementation of
23628   the `location` API.
23629
23630   You can pass it a `implementation` ('hash', 'history', 'none') to force a
23631   particular implementation.
23632
23633   @class Location
23634   @namespace Ember
23635   @static
23636 */
23637 Ember.Location = {
23638   create: function(options) {
23639     var implementation = options && options.implementation;
23640     Ember.assert("Ember.Location.create: you must specify a 'implementation' option", !!implementation);
23641
23642     var implementationClass = this.implementations[implementation];
23643     Ember.assert("Ember.Location.create: " + implementation + " is not a valid implementation", !!implementationClass);
23644
23645     return implementationClass.create.apply(implementationClass, arguments);
23646   },
23647
23648   registerImplementation: function(name, implementation) {
23649     this.implementations[name] = implementation;
23650   },
23651
23652   implementations: {}
23653 };
23654
23655 })();
23656
23657
23658
23659 (function() {
23660 /**
23661 @module ember
23662 @submodule ember-routing
23663 */
23664
23665 var get = Ember.get, set = Ember.set;
23666
23667 /**
23668   Ember.NoneLocation does not interact with the browser. It is useful for
23669   testing, or when you need to manage state with your Router, but temporarily
23670   don't want it to muck with the URL (for example when you embed your
23671   application in a larger page).
23672
23673   @class NoneLocation
23674   @namespace Ember
23675   @extends Ember.Object
23676 */
23677 Ember.NoneLocation = Ember.Object.extend({
23678   path: '',
23679
23680   getURL: function() {
23681     return get(this, 'path');
23682   },
23683
23684   setURL: function(path) {
23685     set(this, 'path', path);
23686   },
23687
23688   onUpdateURL: function(callback) {
23689     // We are not wired up to the browser, so we'll never trigger the callback.
23690   },
23691
23692   formatURL: function(url) {
23693     // The return value is not overly meaningful, but we do not want to throw
23694     // errors when test code renders templates containing {{action href=true}}
23695     // helpers.
23696     return url;
23697   }
23698 });
23699
23700 Ember.Location.registerImplementation('none', Ember.NoneLocation);
23701
23702 })();
23703
23704
23705
23706 (function() {
23707 /**
23708 @module ember
23709 @submodule ember-routing
23710 */
23711
23712 var get = Ember.get, set = Ember.set;
23713
23714 /**
23715   Ember.HashLocation implements the location API using the browser's
23716   hash. At present, it relies on a hashchange event existing in the
23717   browser.
23718
23719   @class HashLocation
23720   @namespace Ember
23721   @extends Ember.Object
23722 */
23723 Ember.HashLocation = Ember.Object.extend({
23724
23725   init: function() {
23726     set(this, 'location', get(this, 'location') || window.location);
23727   },
23728
23729   /**
23730     @private
23731
23732     Returns the current `location.hash`, minus the '#' at the front.
23733
23734     @method getURL
23735   */
23736   getURL: function() {
23737     return get(this, 'location').hash.substr(1);
23738   },
23739
23740   /**
23741     @private
23742
23743     Set the `location.hash` and remembers what was set. This prevents
23744     `onUpdateURL` callbacks from triggering when the hash was set by
23745     `HashLocation`.
23746
23747     @method setURL
23748     @param path {String}
23749   */
23750   setURL: function(path) {
23751     get(this, 'location').hash = path;
23752     set(this, 'lastSetURL', path);
23753   },
23754
23755   /**
23756     @private
23757
23758     Register a callback to be invoked when the hash changes. These
23759     callbacks will execute when the user presses the back or forward
23760     button, but not after `setURL` is invoked.
23761
23762     @method onUpdateURL
23763     @param callback {Function}
23764   */
23765   onUpdateURL: function(callback) {
23766     var self = this;
23767     var guid = Ember.guidFor(this);
23768
23769     Ember.$(window).bind('hashchange.ember-location-'+guid, function() {
23770       var path = location.hash.substr(1);
23771       if (get(self, 'lastSetURL') === path) { return; }
23772
23773       set(self, 'lastSetURL', null);
23774
23775       callback(location.hash.substr(1));
23776     });
23777   },
23778
23779   /**
23780     @private
23781
23782     Given a URL, formats it to be placed into the page as part
23783     of an element's `href` attribute.
23784
23785     This is used, for example, when using the {{action}} helper
23786     to generate a URL based on an event.
23787
23788     @method formatURL
23789     @param url {String}
23790   */
23791   formatURL: function(url) {
23792     return '#'+url;
23793   },
23794
23795   willDestroy: function() {
23796     var guid = Ember.guidFor(this);
23797
23798     Ember.$(window).unbind('hashchange.ember-location-'+guid);
23799   }
23800 });
23801
23802 Ember.Location.registerImplementation('hash', Ember.HashLocation);
23803
23804 })();
23805
23806
23807
23808 (function() {
23809 /**
23810 @module ember
23811 @submodule ember-routing
23812 */
23813
23814 var get = Ember.get, set = Ember.set;
23815 var popstateReady = false;
23816
23817 /**
23818   Ember.HistoryLocation implements the location API using the browser's
23819   history.pushState API.
23820
23821   @class HistoryLocation
23822   @namespace Ember
23823   @extends Ember.Object
23824 */
23825 Ember.HistoryLocation = Ember.Object.extend({
23826
23827   init: function() {
23828     set(this, 'location', get(this, 'location') || window.location);
23829     this.initState();
23830   },
23831
23832   /**
23833     @private
23834
23835     Used to set state on first call to setURL
23836
23837     @method initState
23838   */
23839   initState: function() {
23840     this.replaceState(get(this, 'location').pathname);
23841     set(this, 'history', window.history);
23842   },
23843
23844   /**
23845     Will be pre-pended to path upon state change
23846
23847     @property rootURL
23848     @default '/'
23849   */
23850   rootURL: '/',
23851
23852   /**
23853     @private
23854
23855     Returns the current `location.pathname`.
23856
23857     @method getURL
23858   */
23859   getURL: function() {
23860     return get(this, 'location').pathname;
23861   },
23862
23863   /**
23864     @private
23865
23866     Uses `history.pushState` to update the url without a page reload.
23867
23868     @method setURL
23869     @param path {String}
23870   */
23871   setURL: function(path) {
23872     path = this.formatURL(path);
23873
23874     if (this.getState() && this.getState().path !== path) {
23875       popstateReady = true;
23876       this.pushState(path);
23877     }
23878   },
23879
23880   /**
23881     @private
23882
23883     Uses `history.replaceState` to update the url without a page reload
23884     or history modification.
23885
23886     @method replaceURL
23887     @param path {String}
23888   */
23889   replaceURL: function(path) {
23890     path = this.formatURL(path);
23891
23892     if (this.getState() && this.getState().path !== path) {
23893       popstateReady = true;
23894       this.replaceState(path);
23895     }
23896   },
23897
23898   /**
23899    @private
23900
23901    Get the current `history.state`
23902
23903    @method getState
23904   */
23905   getState: function() {
23906     return get(this, 'history').state;
23907   },
23908
23909   /**
23910    @private
23911
23912    Pushes a new state
23913
23914    @method pushState
23915    @param path {String}
23916   */
23917   pushState: function(path) {
23918     window.history.pushState({ path: path }, null, path);
23919   },
23920
23921   /**
23922    @private
23923
23924    Replaces the current state
23925
23926    @method replaceState
23927    @param path {String}
23928   */
23929   replaceState: function(path) {
23930     window.history.replaceState({ path: path }, null, path);
23931   },
23932
23933   /**
23934     @private
23935
23936     Register a callback to be invoked whenever the browser
23937     history changes, including using forward and back buttons.
23938
23939     @method onUpdateURL
23940     @param callback {Function}
23941   */
23942   onUpdateURL: function(callback) {
23943     var guid = Ember.guidFor(this);
23944
23945     Ember.$(window).bind('popstate.ember-location-'+guid, function(e) {
23946       if(!popstateReady) {
23947         return;
23948       }
23949       callback(location.pathname);
23950     });
23951   },
23952
23953   /**
23954     @private
23955
23956     Used when using `{{action}}` helper.  The url is always appended to the rootURL.
23957
23958     @method formatURL
23959     @param url {String}
23960   */
23961   formatURL: function(url) {
23962     var rootURL = get(this, 'rootURL');
23963
23964     if (url !== '') {
23965       rootURL = rootURL.replace(/\/$/, '');
23966     }
23967
23968     return rootURL + url;
23969   },
23970
23971   willDestroy: function() {
23972     var guid = Ember.guidFor(this);
23973
23974     Ember.$(window).unbind('popstate.ember-location-'+guid);
23975   }
23976 });
23977
23978 Ember.Location.registerImplementation('history', Ember.HistoryLocation);
23979
23980 })();
23981
23982
23983
23984 (function() {
23985
23986 })();
23987
23988
23989
23990 (function() {
23991 /**
23992 Ember Routing
23993
23994 @module ember
23995 @submodule ember-routing
23996 @requires ember-states
23997 @requires ember-views
23998 */
23999
24000 })();
24001
24002 (function() {
24003 function visit(vertex, fn, visited, path) {
24004   var name = vertex.name,
24005     vertices = vertex.incoming,
24006     names = vertex.incomingNames,
24007     len = names.length,
24008     i;
24009   if (!visited) {
24010     visited = {};
24011   }
24012   if (!path) {
24013     path = [];
24014   }
24015   if (visited.hasOwnProperty(name)) {
24016     return;
24017   }
24018   path.push(name);
24019   visited[name] = true;
24020   for (i = 0; i < len; i++) {
24021     visit(vertices[names[i]], fn, visited, path);
24022   }
24023   fn(vertex, path);
24024   path.pop();
24025 }
24026
24027 function DAG() {
24028   this.names = [];
24029   this.vertices = {};
24030 }
24031
24032 DAG.prototype.add = function(name) {
24033   if (!name) { return; }
24034   if (this.vertices.hasOwnProperty(name)) {
24035     return this.vertices[name];
24036   }
24037   var vertex = {
24038     name: name, incoming: {}, incomingNames: [], hasOutgoing: false, value: null
24039   };
24040   this.vertices[name] = vertex;
24041   this.names.push(name);
24042   return vertex;
24043 };
24044
24045 DAG.prototype.map = function(name, value) {
24046   this.add(name).value = value;
24047 };
24048
24049 DAG.prototype.addEdge = function(fromName, toName) {
24050   if (!fromName || !toName || fromName === toName) {
24051     return;
24052   }
24053   var from = this.add(fromName), to = this.add(toName);
24054   if (to.incoming.hasOwnProperty(fromName)) {
24055     return;
24056   }
24057   function checkCycle(vertex, path) {
24058     if (vertex.name === toName) {
24059       throw new Error("cycle detected: " + toName + " <- " + path.join(" <- "));
24060     }
24061   }
24062   visit(from, checkCycle);
24063   from.hasOutgoing = true;
24064   to.incoming[fromName] = from;
24065   to.incomingNames.push(fromName);
24066 };
24067
24068 DAG.prototype.topsort = function(fn) {
24069   var visited = {},
24070     vertices = this.vertices,
24071     names = this.names,
24072     len = names.length,
24073     i, vertex;
24074   for (i = 0; i < len; i++) {
24075     vertex = vertices[names[i]];
24076     if (!vertex.hasOutgoing) {
24077       visit(vertex, fn, visited);
24078     }
24079   }
24080 };
24081
24082 DAG.prototype.addEdges = function(name, value, before, after) {
24083   var i;
24084   this.map(name, value);
24085   if (before) {
24086     if (typeof before === 'string') {
24087       this.addEdge(name, before);
24088     } else {
24089       for (i = 0; i < before.length; i++) {
24090         this.addEdge(name, before[i]);
24091       }
24092     }
24093   }
24094   if (after) {
24095     if (typeof after === 'string') {
24096       this.addEdge(after, name);
24097     } else {
24098       for (i = 0; i < after.length; i++) {
24099         this.addEdge(after[i], name);
24100       }
24101     }
24102   }
24103 };
24104
24105 Ember.DAG = DAG;
24106
24107 })();
24108
24109
24110
24111 (function() {
24112 /**
24113 @module ember
24114 @submodule ember-application
24115 */
24116
24117 var get = Ember.get, set = Ember.set,
24118     classify = Ember.String.classify,
24119     decamelize = Ember.String.decamelize;
24120
24121 /**
24122   An instance of `Ember.Application` is the starting point for every Ember
24123   application. It helps to instantiate, initialize and coordinate the many
24124   objects that make up your app.
24125
24126   Each Ember app has one and only one `Ember.Application` object. In fact, the
24127   very first thing you should do in your application is create the instance:
24128
24129   ```javascript
24130   window.App = Ember.Application.create();
24131   ```
24132
24133   Typically, the application object is the only global variable. All other
24134   classes in your app should be properties on the `Ember.Application` instance,
24135   which highlights its first role: a global namespace.
24136
24137   For example, if you define a view class, it might look like this:
24138
24139   ```javascript
24140   App.MyView = Ember.View.extend();
24141   ```
24142
24143   By default, calling `Ember.Application.create()` will automatically initialize
24144   your  application by calling the `Ember.Application.initialize()` method. If
24145   you need to delay initialization, you can call your app's `deferReadiness()`
24146   method. When you are ready for your app to be initialized, call its
24147   `advanceReadiness()` method.
24148
24149   Because `Ember.Application` inherits from `Ember.Namespace`, any classes
24150   you create will have useful string representations when calling `toString()`.
24151   See the `Ember.Namespace` documentation for more information.
24152
24153   While you can think of your `Ember.Application` as a container that holds the
24154   other classes in your application, there are several other responsibilities
24155   going on under-the-hood that you may want to understand.
24156
24157   ### Event Delegation
24158
24159   Ember uses a technique called _event delegation_. This allows the framework
24160   to set up a global, shared event listener instead of requiring each view to
24161   do it manually. For example, instead of each view registering its own
24162   `mousedown` listener on its associated element, Ember sets up a `mousedown`
24163   listener on the `body`.
24164
24165   If a `mousedown` event occurs, Ember will look at the target of the event and
24166   start walking up the DOM node tree, finding corresponding views and invoking
24167   their `mouseDown` method as it goes.
24168
24169   `Ember.Application` has a number of default events that it listens for, as
24170   well as a mapping from lowercase events to camel-cased view method names. For
24171   example, the `keypress` event causes the `keyPress` method on the view to be
24172   called, the `dblclick` event causes `doubleClick` to be called, and so on.
24173
24174   If there is a browser event that Ember does not listen for by default, you
24175   can specify custom events and their corresponding view method names by
24176   setting the application's `customEvents` property:
24177
24178   ```javascript
24179   App = Ember.Application.create({
24180     customEvents: {
24181       // add support for the loadedmetadata media
24182       // player event
24183       'loadedmetadata': "loadedMetadata"
24184     }
24185   });
24186   ```
24187
24188   By default, the application sets up these event listeners on the document
24189   body. However, in cases where you are embedding an Ember application inside
24190   an existing page, you may want it to set up the listeners on an element
24191   inside the body.
24192
24193   For example, if only events inside a DOM element with the ID of `ember-app`
24194   should be delegated, set your application's `rootElement` property:
24195
24196   ```javascript
24197   window.App = Ember.Application.create({
24198     rootElement: '#ember-app'
24199   });
24200   ```
24201
24202   The `rootElement` can be either a DOM element or a jQuery-compatible selector
24203   string. Note that *views appended to the DOM outside the root element will
24204   not receive events.* If you specify a custom root element, make sure you only
24205   append views inside it!
24206
24207   To learn more about the advantages of event delegation and the Ember view
24208   layer, and a list of the event listeners that are setup by default, visit the
24209   [Ember View Layer guide](http://emberjs.com/guides/view_layer#toc_event-delegation).
24210
24211   ### Dependency Injection
24212
24213   One thing you may have noticed while using Ember is that you define
24214   *classes*, not *instances*. When your application loads, all of the instances
24215   are created for you. Creating these instances is the responsibility of
24216   `Ember.Application`.
24217
24218   When the `Ember.Application` initializes, it will look for an `Ember.Router`
24219   class defined on the applications's `Router` property, like this:
24220
24221   ```javascript
24222   App.Router = Ember.Router.extend({
24223   // ...
24224   });
24225   ```
24226
24227   If found, the router is instantiated and saved on the application's `router`
24228   property (note the lowercase 'r'). While you should *not* reference this
24229   router instance directly from your application code, having access to
24230   `App.router` from the console can be useful during debugging.
24231
24232   After the router is created, the application loops through all of the
24233   registered _injections_ and invokes them once for each property on the
24234   `Ember.Application` object.
24235
24236   An injection is a function that is responsible for instantiating objects from
24237   classes defined on the application. By default, the only injection registered
24238   instantiates controllers and makes them available on the router.
24239
24240   For example, if you define a controller class:
24241
24242   ```javascript
24243   App.MyController = Ember.Controller.extend({
24244     // ...
24245   });
24246   ```
24247
24248   Your router will receive an instance of `App.MyController` saved on its
24249   `myController` property.
24250
24251   Libraries on top of Ember can register additional injections. For example,
24252   if your application is using Ember Data, it registers an injection that
24253   instantiates `DS.Store`:
24254
24255   ```javascript
24256   Ember.Application.registerInjection({
24257     name: 'store',
24258     before: 'controllers',
24259
24260     injection: function(app, router, property) {
24261       if (property === 'Store') {
24262         set(router, 'store', app[property].create());
24263       }
24264     }
24265   });
24266   ```
24267
24268   ### Routing
24269
24270   In addition to creating your application's router, `Ember.Application` is
24271   also responsible for telling the router when to start routing.
24272
24273   By default, the router will begin trying to translate the current URL into
24274   application state once the browser emits the `DOMContentReady` event. If you
24275   need to defer routing, you can call the application's `deferReadiness()`
24276   method. Once routing can begin, call the `advanceReadiness()` method.
24277
24278   If there is any setup required before routing begins, you can implement a
24279   `ready()` method on your app that will be invoked immediately before routing
24280   begins:
24281
24282   ```javascript
24283   window.App = Ember.Application.create({
24284     ready: function() {
24285       this.set('router.enableLogging', true);
24286     }
24287   });
24288
24289   To begin routing, you must have at a minimum a top-level controller and view.
24290   You define these as `App.ApplicationController` and `App.ApplicationView`,
24291   respectively. Your application will not work if you do not define these two
24292   mandatory classes. For example:
24293
24294   ```javascript
24295   App.ApplicationView = Ember.View.extend({
24296     templateName: 'application'
24297   });
24298   App.ApplicationController = Ember.Controller.extend();
24299   ```
24300
24301   @class Application
24302   @namespace Ember
24303   @extends Ember.Namespace
24304 */
24305 var Application = Ember.Application = Ember.Namespace.extend(
24306 /** @scope Ember.Application.prototype */{
24307
24308   /**
24309     The root DOM element of the Application. This can be specified as an
24310     element or a
24311     [jQuery-compatible selector string](http://api.jquery.com/category/selectors/).
24312
24313     This is the element that will be passed to the Application's,
24314     `eventDispatcher`, which sets up the listeners for event delegation. Every
24315     view in your application should be a child of the element you specify here.
24316
24317     @property rootElement
24318     @type DOMElement
24319     @default 'body'
24320   */
24321   rootElement: 'body',
24322
24323   /**
24324     The `Ember.EventDispatcher` responsible for delegating events to this
24325     application's views.
24326
24327     The event dispatcher is created by the application at initialization time
24328     and sets up event listeners on the DOM element described by the
24329     application's `rootElement` property.
24330
24331     See the documentation for `Ember.EventDispatcher` for more information.
24332
24333     @property eventDispatcher
24334     @type Ember.EventDispatcher
24335     @default null
24336   */
24337   eventDispatcher: null,
24338
24339   /**
24340     The DOM events for which the event dispatcher should listen.
24341
24342     By default, the application's `Ember.EventDispatcher` listens
24343     for a set of standard DOM events, such as `mousedown` and
24344     `keyup`, and delegates them to your application's `Ember.View`
24345     instances.
24346
24347     If you would like additional events to be delegated to your
24348     views, set your `Ember.Application`'s `customEvents` property
24349     to a hash containing the DOM event name as the key and the
24350     corresponding view method name as the value. For example:
24351
24352     ```javascript
24353     App = Ember.Application.create({
24354       customEvents: {
24355         // add support for the loadedmetadata media
24356         // player event
24357         'loadedmetadata': "loadedMetadata"
24358       }
24359     });
24360     ```
24361
24362     @property customEvents
24363     @type Object
24364     @default null
24365   */
24366   customEvents: null,
24367
24368   isInitialized: false,
24369
24370   // Start off the number of deferrals at 1. This will be
24371   // decremented by the Application's own `initialize` method.
24372   _readinessDeferrals: 1,
24373
24374   init: function() {
24375     if (!this.$) { this.$ = Ember.$; }
24376     this.__container__ = this.buildContainer();
24377
24378     this.Router = this.Router || this.defaultRouter();
24379     if (this.Router) { this.Router.namespace = this; }
24380
24381     this._super();
24382
24383     this.deferUntilDOMReady();
24384     this.scheduleInitialize();
24385   },
24386
24387   /**
24388     @private
24389
24390     Build the container for the current application.
24391
24392     Also register a default application view in case the application
24393     itself does not.
24394
24395     @method buildContainer
24396     @return {Ember.Container} the configured container
24397   */
24398   buildContainer: function() {
24399     var container = this.__container__ = Application.buildContainer(this);
24400
24401     return container;
24402   },
24403
24404   /**
24405     @private
24406
24407     If the application has not opted out of routing and has not explicitly
24408     defined a router, supply a default router for the application author
24409     to configure.
24410
24411     This allows application developers to do:
24412
24413     ```javascript
24414     App = Ember.Application.create();
24415
24416     App.Router.map(function(match) {
24417       match("/").to("index");
24418     });
24419     ```
24420
24421     @method defaultRouter
24422     @return {Ember.Router} the default router
24423   */
24424   defaultRouter: function() {
24425     // Create a default App.Router if one was not supplied to make
24426     // it possible to do App.Router.map(...) without explicitly
24427     // creating a router first.
24428     if (this.router === undefined) {
24429       return Ember.Router.extend();
24430     }
24431   },
24432
24433   /**
24434     @private
24435
24436     Defer Ember readiness until DOM readiness. By default, Ember
24437     will wait for both DOM readiness and application initialization,
24438     as well as any deferrals registered by initializers.
24439
24440     @method deferUntilDOMReady
24441   */
24442   deferUntilDOMReady: function() {
24443     this.deferReadiness();
24444
24445     var self = this;
24446     this.$().ready(function() {
24447       self.advanceReadiness();
24448     });
24449   },
24450
24451   /**
24452     @private
24453
24454     Automatically initialize the application once the DOM has
24455     become ready.
24456
24457     The initialization itself is deferred using Ember.run.once,
24458     which ensures that application loading finishes before
24459     booting.
24460
24461     If you are asynchronously loading code, you should call
24462     `deferReadiness()` to defer booting, and then call
24463     `advanceReadiness()` once all of your code has finished
24464     loading.
24465
24466     @method scheduleInitialize
24467   */
24468   scheduleInitialize: function() {
24469     var self = this;
24470     this.$().ready(function() {
24471       if (self.isDestroyed || self.isInitialized) return;
24472       Ember.run.once(self, 'initialize');
24473     });
24474   },
24475
24476   /**
24477     Use this to defer readiness until some condition is true.
24478
24479     Example:
24480
24481     ```javascript
24482     App = Ember.Application.create();
24483     App.deferReadiness();
24484
24485     jQuery.getJSON("/auth-token", function(token) {
24486       App.token = token;
24487       App.advanceReadiness();
24488     });
24489     ```
24490
24491     This allows you to perform asynchronous setup logic and defer
24492     booting your application until the setup has finished.
24493
24494     However, if the setup requires a loading UI, it might be better
24495     to use the router for this purpose.
24496
24497     @method deferReadiness
24498   */
24499   deferReadiness: function() {
24500     Ember.assert("You cannot defer readiness since the `ready()` hook has already been called.", this._readinessDeferrals > 0);
24501     this._readinessDeferrals++;
24502   },
24503
24504   /**
24505     @method advanceReadiness
24506     @see {Ember.Application#deferReadiness}
24507   */
24508   advanceReadiness: function() {
24509     this._readinessDeferrals--;
24510
24511     if (this._readinessDeferrals === 0) {
24512       Ember.run.once(this, this.didBecomeReady);
24513     }
24514   },
24515
24516   register: function() {
24517     var container = this.__container__;
24518     return container.register.apply(container, arguments);
24519   },
24520
24521   /**
24522     @private
24523
24524     Initialize the application. This happens automatically.
24525
24526     Run any injections and run the application load hook. These hooks may
24527     choose to defer readiness. For example, an authentication hook might want
24528     to defer readiness until the auth token has been retrieved.
24529
24530     @method initialize
24531   */
24532   initialize: function() {
24533     Ember.assert("Application initialize may only be called once", !this.isInitialized);
24534     Ember.assert("Cannot initialize a destroyed application", !this.isDestroyed);
24535     this.isInitialized = true;
24536
24537     // At this point, the App.Router must already be assigned
24538     this.__container__.register('router', 'main', this.Router);
24539
24540     // Run any injections and run the application load hook. These hooks may
24541     // choose to defer readiness. For example, an authentication hook might want
24542     // to defer readiness until the auth token has been retrieved.
24543     this.runInitializers();
24544     Ember.runLoadHooks('application', this);
24545
24546     // At this point, any injections or load hooks that would have wanted
24547     // to defer readiness have fired. In general, advancing readiness here
24548     // will proceed to didBecomeReady.
24549     this.advanceReadiness();
24550
24551     return this;
24552   },
24553
24554   /**
24555     @private
24556     @method runInitializers
24557   */
24558   runInitializers: function() {
24559     var initializers = get(this.constructor, 'initializers'),
24560         container = this.__container__,
24561         graph = new Ember.DAG(),
24562         namespace = this,
24563         properties, i, initializer;
24564
24565     for (i=0; i<initializers.length; i++) {
24566       initializer = initializers[i];
24567       graph.addEdges(initializer.name, initializer.initialize, initializer.before, initializer.after);
24568     }
24569
24570     graph.topsort(function (vertex) {
24571       var initializer = vertex.value;
24572       initializer(container, namespace);
24573     });
24574   },
24575
24576   /**
24577     @private
24578     @method didBecomeReady
24579   */
24580   didBecomeReady: function() {
24581     this.setupEventDispatcher();
24582     this.ready(); // user hook
24583     this.startRouting();
24584
24585     if (!Ember.testing) {
24586       // Eagerly name all classes that are already loaded
24587       Ember.Namespace.processAll();
24588       Ember.BOOTED = true;
24589     }
24590   },
24591
24592   /**
24593     @private
24594
24595     Setup up the event dispatcher to receive events on the
24596     application's `rootElement` with any registered
24597     `customEvents`.
24598
24599     @method setupEventDispatcher
24600   */
24601   setupEventDispatcher: function() {
24602     var eventDispatcher = this.createEventDispatcher(),
24603         customEvents    = get(this, 'customEvents');
24604
24605     eventDispatcher.setup(customEvents);
24606   },
24607
24608   /**
24609     @private
24610
24611     Create an event dispatcher for the application's `rootElement`.
24612
24613     @method createEventDispatcher
24614   */
24615   createEventDispatcher: function() {
24616     var rootElement = get(this, 'rootElement'),
24617         eventDispatcher = Ember.EventDispatcher.create({
24618           rootElement: rootElement
24619         });
24620
24621     set(this, 'eventDispatcher', eventDispatcher);
24622     return eventDispatcher;
24623   },
24624
24625   /**
24626     @private
24627
24628     If the application has a router, use it to route to the current URL, and
24629     trigger a new call to `route` whenever the URL changes.
24630
24631     @method startRouting
24632     @property router {Ember.Router}
24633   */
24634   startRouting: function() {
24635     var router = this.__container__.lookup('router:main');
24636     if (!router) { return; }
24637
24638     router.startRouting();
24639   },
24640
24641   /**
24642     Called when the Application has become ready.
24643     The call will be delayed until the DOM has become ready.
24644
24645     @event ready
24646   */
24647   ready: Ember.K,
24648
24649   willDestroy: function() {
24650     Ember.BOOTED = false;
24651
24652     var eventDispatcher = get(this, 'eventDispatcher');
24653     if (eventDispatcher) { eventDispatcher.destroy(); }
24654
24655     this.__container__.destroy();
24656   },
24657
24658   initializer: function(options) {
24659     this.constructor.initializer(options);
24660   }
24661 });
24662
24663 Ember.Application.reopenClass({
24664   concatenatedProperties: ['initializers'],
24665   initializers: Ember.A(),
24666   initializer: function(initializer) {
24667     var initializers = get(this, 'initializers');
24668
24669     Ember.assert("The initializer '" + initializer.name + "' has already been registered", !initializers.findProperty('name', initializers.name));
24670     Ember.assert("An injection cannot be registered with both a before and an after", !(initializer.before && initializer.after));
24671     Ember.assert("An injection cannot be registered without an injection function", Ember.canInvoke(initializer, 'initialize'));
24672
24673     initializers.push(initializer);
24674   },
24675
24676   /**
24677     @private
24678
24679     This creates a container with the default Ember naming conventions.
24680
24681     It also configures the container:
24682
24683     * registered views are created every time they are looked up (they are
24684       not singletons)
24685     * registered templates are not factories; the registered value is
24686       returned directly.
24687     * the router receives the application as its `namespace` property
24688     * all controllers receive the router as their `target` and `controllers`
24689       properties
24690     * all controllers receive the application as their `namespace` property
24691     * the application view receives the application controller as its
24692       `controller` property
24693     * the application view receives the application template as its
24694       `defaultTemplate` property
24695
24696     @method buildContainer
24697     @static
24698     @param {Ember.Application} namespace the application to build the
24699       container for.
24700     @return {Ember.Container} the built container
24701   */
24702   buildContainer: function(namespace) {
24703     var container = new Ember.Container();
24704     Ember.Container.defaultContainer = container;
24705
24706     container.set = Ember.set;
24707     container.resolver = resolverFor(namespace);
24708     container.optionsForType('view', { singleton: false });
24709     container.optionsForType('template', { instantiate: false });
24710     container.register('application', 'main', namespace, { instantiate: false });
24711     container.injection('router:main', 'namespace', 'application:main');
24712
24713     container.typeInjection('controller', 'target', 'router:main');
24714     container.typeInjection('controller', 'namespace', 'application:main');
24715
24716     container.typeInjection('route', 'router', 'router:main');
24717
24718     return container;
24719   }
24720 });
24721
24722 /**
24723   @private
24724
24725   This function defines the default lookup rules for container lookups:
24726
24727   * templates are looked up on `Ember.TEMPLATES`
24728   * other names are looked up on the application after classifying the name.
24729     For example, `controller:post` looks up `App.PostController` by default.
24730   * if the default lookup fails, look for registered classes on the container
24731
24732   This allows the application to register default injections in the container
24733   that could be overridden by the normal naming convention.
24734
24735   @param {Ember.Namespace} namespace the namespace to look for classes
24736   @return {any} the resolved value for a given lookup
24737 */
24738 function resolverFor(namespace) {
24739   return function(fullName) {
24740     var nameParts = fullName.split(":"),
24741         type = nameParts[0], name = nameParts[1];
24742
24743     if (type === 'template') {
24744       var templateName = name.replace(/\./g, '/');
24745       if (Ember.TEMPLATES[templateName]) {
24746         return Ember.TEMPLATES[templateName];
24747       }
24748
24749       templateName = decamelize(templateName);
24750       if (Ember.TEMPLATES[templateName]) {
24751         return Ember.TEMPLATES[templateName];
24752       }
24753     }
24754
24755     if (type === 'controller' || type === 'route' || type === 'view') {
24756       name = name.replace(/\./g, '_');
24757     }
24758
24759     var className = classify(name) + classify(type);
24760     var factory = get(namespace, className);
24761
24762     if (factory) { return factory; }
24763   };
24764 }
24765
24766 Ember.runLoadHooks('Ember.Application', Ember.Application);
24767
24768
24769 })();
24770
24771
24772
24773 (function() {
24774
24775 })();
24776
24777
24778
24779 (function() {
24780 /**
24781 Ember Application
24782
24783 @module ember
24784 @submodule ember-application
24785 @requires ember-views, ember-states, ember-routing
24786 */
24787
24788 })();
24789
24790 (function() {
24791 var get = Ember.get, set = Ember.set;
24792
24793 /**
24794 @module ember
24795 @submodule ember-states
24796 */
24797
24798 /**
24799   @class State
24800   @namespace Ember
24801   @extends Ember.Object
24802   @uses Ember.Evented
24803 */
24804 Ember.State = Ember.Object.extend(Ember.Evented,
24805 /** @scope Ember.State.prototype */{
24806   isState: true,
24807
24808   /**
24809     A reference to the parent state.
24810
24811     @property parentState
24812     @type Ember.State
24813   */
24814   parentState: null,
24815   start: null,
24816
24817   /**
24818     The name of this state.
24819
24820     @property name
24821     @type String
24822   */
24823   name: null,
24824
24825   /**
24826     The full path to this state.
24827
24828     @property path
24829     @type String
24830   */
24831   path: Ember.computed(function() {
24832     var parentPath = get(this, 'parentState.path'),
24833         path = get(this, 'name');
24834
24835     if (parentPath) {
24836       path = parentPath + '.' + path;
24837     }
24838
24839     return path;
24840   }),
24841
24842   /**
24843     @private
24844
24845     Override the default event firing from `Ember.Evented` to
24846     also call methods with the given name.
24847
24848     @method trigger
24849     @param name
24850   */
24851   trigger: function(name) {
24852     if (this[name]) {
24853       this[name].apply(this, [].slice.call(arguments, 1));
24854     }
24855     this._super.apply(this, arguments);
24856   },
24857
24858   init: function() {
24859     var states = get(this, 'states'), foundStates;
24860     set(this, 'childStates', Ember.A());
24861     set(this, 'eventTransitions', get(this, 'eventTransitions') || {});
24862
24863     var name, value, transitionTarget;
24864
24865     // As a convenience, loop over the properties
24866     // of this state and look for any that are other
24867     // Ember.State instances or classes, and move them
24868     // to the `states` hash. This avoids having to
24869     // create an explicit separate hash.
24870
24871     if (!states) {
24872       states = {};
24873
24874       for (name in this) {
24875         if (name === "constructor") { continue; }
24876
24877         if (value = this[name]) {
24878           if (transitionTarget = value.transitionTarget) {
24879             this.eventTransitions[name] = transitionTarget;
24880           }
24881
24882           this.setupChild(states, name, value);
24883         }
24884       }
24885
24886       set(this, 'states', states);
24887     } else {
24888       for (name in states) {
24889         this.setupChild(states, name, states[name]);
24890       }
24891     }
24892
24893     set(this, 'pathsCache', {});
24894     set(this, 'pathsCacheNoContext', {});
24895   },
24896
24897   setupChild: function(states, name, value) {
24898     if (!value) { return false; }
24899
24900     if (value.isState) {
24901       set(value, 'name', name);
24902     } else if (Ember.State.detect(value)) {
24903       value = value.create({
24904         name: name
24905       });
24906     }
24907
24908     if (value.isState) {
24909       set(value, 'parentState', this);
24910       get(this, 'childStates').pushObject(value);
24911       states[name] = value;
24912       return value;
24913     }
24914   },
24915
24916   lookupEventTransition: function(name) {
24917     var path, state = this;
24918
24919     while(state && !path) {
24920       path = state.eventTransitions[name];
24921       state = state.get('parentState');
24922     }
24923
24924     return path;
24925   },
24926
24927   /**
24928     A Boolean value indicating whether the state is a leaf state
24929     in the state hierarchy. This is `false` if the state has child
24930     states; otherwise it is true.
24931
24932     @property isLeaf
24933     @type Boolean
24934   */
24935   isLeaf: Ember.computed(function() {
24936     return !get(this, 'childStates').length;
24937   }),
24938
24939   /**
24940     A boolean value indicating whether the state takes a context.
24941     By default we assume all states take contexts.
24942
24943     @property hasContext
24944     @default true
24945   */
24946   hasContext: true,
24947
24948   /**
24949     This is the default transition event.
24950
24951     @event setup
24952     @param {Ember.StateManager} manager
24953     @param context
24954     @see Ember.StateManager#transitionEvent
24955   */
24956   setup: Ember.K,
24957
24958   /**
24959     This event fires when the state is entered.
24960
24961     @event enter
24962     @param {Ember.StateManager} manager
24963   */
24964   enter: Ember.K,
24965
24966   /**
24967     This event fires when the state is exited.
24968
24969     @event exit
24970     @param {Ember.StateManager} manager
24971   */
24972   exit: Ember.K
24973 });
24974
24975 Ember.State.reopenClass({
24976
24977   /**
24978     Creates an action function for transitioning to the named state while
24979     preserving context.
24980
24981     The following example StateManagers are equivalent:
24982
24983     ```javascript
24984     aManager = Ember.StateManager.create({
24985       stateOne: Ember.State.create({
24986         changeToStateTwo: Ember.State.transitionTo('stateTwo')
24987       }),
24988       stateTwo: Ember.State.create({})
24989     })
24990
24991     bManager = Ember.StateManager.create({
24992       stateOne: Ember.State.create({
24993         changeToStateTwo: function(manager, context){
24994           manager.transitionTo('stateTwo', context)
24995         }
24996       }),
24997       stateTwo: Ember.State.create({})
24998     })
24999     ```
25000
25001     @method transitionTo
25002     @static
25003     @param {String} target
25004   */
25005
25006   transitionTo: function(target) {
25007
25008     var transitionFunction = function(stateManager, contextOrEvent) {
25009       var contexts = [], transitionArgs,
25010           Event = Ember.$ && Ember.$.Event;
25011
25012       if (contextOrEvent && (Event && contextOrEvent instanceof Event)) {
25013         if (contextOrEvent.hasOwnProperty('contexts')) {
25014           contexts = contextOrEvent.contexts.slice();
25015         }
25016       }
25017       else {
25018         contexts = [].slice.call(arguments, 1);
25019       }
25020
25021       contexts.unshift(target);
25022       stateManager.transitionTo.apply(stateManager, contexts);
25023     };
25024
25025     transitionFunction.transitionTarget = target;
25026
25027     return transitionFunction;
25028   }
25029
25030 });
25031
25032 })();
25033
25034
25035
25036 (function() {
25037 /**
25038 @module ember
25039 @submodule ember-states
25040 */
25041
25042 var get = Ember.get, set = Ember.set, fmt = Ember.String.fmt;
25043 var arrayForEach = Ember.ArrayPolyfills.forEach;
25044 /**
25045   A Transition takes the enter, exit and resolve states and normalizes
25046   them:
25047
25048   * takes any passed in contexts into consideration
25049   * adds in `initialState`s
25050
25051   @class Transition
25052   @private
25053 */
25054 var Transition = function(raw) {
25055   this.enterStates = raw.enterStates.slice();
25056   this.exitStates = raw.exitStates.slice();
25057   this.resolveState = raw.resolveState;
25058
25059   this.finalState = raw.enterStates[raw.enterStates.length - 1] || raw.resolveState;
25060 };
25061
25062 Transition.prototype = {
25063   /**
25064     Normalize the passed in enter, exit and resolve states.
25065
25066     This process also adds `finalState` and `contexts` to the Transition object.
25067
25068     @method normalize
25069     @param {Ember.StateManager} manager the state manager running the transition
25070     @param {Array} contexts a list of contexts passed into `transitionTo`
25071   */
25072   normalize: function(manager, contexts) {
25073     this.matchContextsToStates(contexts);
25074     this.addInitialStates();
25075     this.removeUnchangedContexts(manager);
25076     return this;
25077   },
25078
25079   /**
25080     Match each of the contexts passed to `transitionTo` to a state.
25081     This process may also require adding additional enter and exit
25082     states if there are more contexts than enter states.
25083
25084     @method matchContextsToStates
25085     @param {Array} contexts a list of contexts passed into `transitionTo`
25086   */
25087   matchContextsToStates: function(contexts) {
25088     var stateIdx = this.enterStates.length - 1,
25089         matchedContexts = [],
25090         state,
25091         context;
25092
25093     // Next, we will match the passed in contexts to the states they
25094     // represent.
25095     //
25096     // First, assign a context to each enter state in reverse order. If
25097     // any contexts are left, add a parent state to the list of states
25098     // to enter and exit, and assign a context to the parent state.
25099     //
25100     // If there are still contexts left when the state manager is
25101     // reached, raise an exception.
25102     //
25103     // This allows the following:
25104     //
25105     // |- root
25106     // | |- post
25107     // | | |- comments
25108     // | |- about (* current state)
25109     //
25110     // For `transitionTo('post.comments', post, post.get('comments')`,
25111     // the first context (`post`) will be assigned to `root.post`, and
25112     // the second context (`post.get('comments')`) will be assigned
25113     // to `root.post.comments`.
25114     //
25115     // For the following:
25116     //
25117     // |- root
25118     // | |- post
25119     // | | |- index (* current state)
25120     // | | |- comments
25121     //
25122     // For `transitionTo('post.comments', otherPost, otherPost.get('comments')`,
25123     // the `<root.post>` state will be added to the list of enter and exit
25124     // states because its context has changed.
25125
25126     while (contexts.length > 0) {
25127       if (stateIdx >= 0) {
25128         state = this.enterStates[stateIdx--];
25129       } else {
25130         if (this.enterStates.length) {
25131           state = get(this.enterStates[0], 'parentState');
25132           if (!state) { throw "Cannot match all contexts to states"; }
25133         } else {
25134           // If re-entering the current state with a context, the resolve
25135           // state will be the current state.
25136           state = this.resolveState;
25137         }
25138
25139         this.enterStates.unshift(state);
25140         this.exitStates.unshift(state);
25141       }
25142
25143       // in routers, only states with dynamic segments have a context
25144       if (get(state, 'hasContext')) {
25145         context = contexts.pop();
25146       } else {
25147         context = null;
25148       }
25149
25150       matchedContexts.unshift(context);
25151     }
25152
25153     this.contexts = matchedContexts;
25154   },
25155
25156   /**
25157     Add any `initialState`s to the list of enter states.
25158
25159     @method addInitialStates
25160   */
25161   addInitialStates: function() {
25162     var finalState = this.finalState, initialState;
25163
25164     while(true) {
25165       initialState = get(finalState, 'initialState') || 'start';
25166       finalState = get(finalState, 'states.' + initialState);
25167
25168       if (!finalState) { break; }
25169
25170       this.finalState = finalState;
25171       this.enterStates.push(finalState);
25172       this.contexts.push(undefined);
25173     }
25174   },
25175
25176   /**
25177     Remove any states that were added because the number of contexts
25178     exceeded the number of explicit enter states, but the context has
25179     not changed since the last time the state was entered.
25180
25181     @method removeUnchangedContexts
25182     @param {Ember.StateManager} manager passed in to look up the last
25183       context for a states
25184   */
25185   removeUnchangedContexts: function(manager) {
25186     // Start from the beginning of the enter states. If the state was added
25187     // to the list during the context matching phase, make sure the context
25188     // has actually changed since the last time the state was entered.
25189     while (this.enterStates.length > 0) {
25190       if (this.enterStates[0] !== this.exitStates[0]) { break; }
25191
25192       if (this.enterStates.length === this.contexts.length) {
25193         if (manager.getStateMeta(this.enterStates[0], 'context') !== this.contexts[0]) { break; }
25194         this.contexts.shift();
25195       }
25196
25197       this.resolveState = this.enterStates.shift();
25198       this.exitStates.shift();
25199     }
25200   }
25201 };
25202
25203 var sendRecursively = function(event, currentState, isUnhandledPass) {
25204   var log = this.enableLogging,
25205       eventName = isUnhandledPass ? 'unhandledEvent' : event,
25206       action = currentState[eventName],
25207       contexts, sendRecursiveArguments, actionArguments;
25208
25209   contexts = [].slice.call(arguments, 3);
25210
25211   // Test to see if the action is a method that
25212   // can be invoked. Don't blindly check just for
25213   // existence, because it is possible the state
25214   // manager has a child state of the given name,
25215   // and we should still raise an exception in that
25216   // case.
25217   if (typeof action === 'function') {
25218     if (log) {
25219       if (isUnhandledPass) {
25220         Ember.Logger.log(fmt("STATEMANAGER: Unhandled event '%@' being sent to state %@.", [event, get(currentState, 'path')]));
25221       } else {
25222         Ember.Logger.log(fmt("STATEMANAGER: Sending event '%@' to state %@.", [event, get(currentState, 'path')]));
25223       }
25224     }
25225
25226     actionArguments = contexts;
25227     if (isUnhandledPass) {
25228       actionArguments.unshift(event);
25229     }
25230     actionArguments.unshift(this);
25231
25232     return action.apply(currentState, actionArguments);
25233   } else {
25234     var parentState = get(currentState, 'parentState');
25235     if (parentState) {
25236
25237       sendRecursiveArguments = contexts;
25238       sendRecursiveArguments.unshift(event, parentState, isUnhandledPass);
25239
25240       return sendRecursively.apply(this, sendRecursiveArguments);
25241     } else if (!isUnhandledPass) {
25242       return sendEvent.call(this, event, contexts, true);
25243     }
25244   }
25245 };
25246
25247 var sendEvent = function(eventName, sendRecursiveArguments, isUnhandledPass) {
25248   sendRecursiveArguments.unshift(eventName, get(this, 'currentState'), isUnhandledPass);
25249   return sendRecursively.apply(this, sendRecursiveArguments);
25250 };
25251
25252 /**
25253   StateManager is part of Ember's implementation of a finite state machine. A
25254   StateManager instance manages a number of properties that are instances of
25255   `Ember.State`,
25256   tracks the current active state, and triggers callbacks when states have changed.
25257
25258   ## Defining States
25259
25260   The states of StateManager can be declared in one of two ways. First, you can
25261   define a `states` property that contains all the states:
25262
25263   ```javascript
25264   managerA = Ember.StateManager.create({
25265     states: {
25266       stateOne: Ember.State.create(),
25267       stateTwo: Ember.State.create()
25268     }
25269   })
25270
25271   managerA.get('states')
25272   // {
25273   //   stateOne: Ember.State.create(),
25274   //   stateTwo: Ember.State.create()
25275   // }
25276   ```
25277
25278   You can also add instances of `Ember.State` (or an `Ember.State` subclass)
25279   directly as properties of a StateManager. These states will be collected into
25280   the `states` property for you.
25281
25282   ```javascript
25283   managerA = Ember.StateManager.create({
25284     stateOne: Ember.State.create(),
25285     stateTwo: Ember.State.create()
25286   })
25287
25288   managerA.get('states')
25289   // {
25290   //   stateOne: Ember.State.create(),
25291   //   stateTwo: Ember.State.create()
25292   // }
25293   ```
25294
25295   ## The Initial State
25296
25297   When created a StateManager instance will immediately enter into the state
25298   defined as its `start` property or the state referenced by name in its
25299   `initialState` property:
25300
25301   ```javascript
25302   managerA = Ember.StateManager.create({
25303     start: Ember.State.create({})
25304   })
25305
25306   managerA.get('currentState.name') // 'start'
25307
25308   managerB = Ember.StateManager.create({
25309     initialState: 'beginHere',
25310     beginHere: Ember.State.create({})
25311   })
25312
25313   managerB.get('currentState.name') // 'beginHere'
25314   ```
25315
25316   Because it is a property you may also provide a computed function if you wish
25317   to derive an `initialState` programmatically:
25318
25319   ```javascript
25320   managerC = Ember.StateManager.create({
25321     initialState: function(){
25322       if (someLogic) {
25323         return 'active';
25324       } else {
25325         return 'passive';
25326       }
25327     }.property(),
25328     active: Ember.State.create({}),
25329     passive: Ember.State.create({})
25330   })
25331   ```
25332
25333   ## Moving Between States
25334
25335   A StateManager can have any number of `Ember.State` objects as properties
25336   and can have a single one of these states as its current state.
25337
25338   Calling `transitionTo` transitions between states:
25339
25340   ```javascript
25341   robotManager = Ember.StateManager.create({
25342     initialState: 'poweredDown',
25343     poweredDown: Ember.State.create({}),
25344     poweredUp: Ember.State.create({})
25345   })
25346
25347   robotManager.get('currentState.name') // 'poweredDown'
25348   robotManager.transitionTo('poweredUp')
25349   robotManager.get('currentState.name') // 'poweredUp'
25350   ```
25351
25352   Before transitioning into a new state the existing `currentState` will have
25353   its `exit` method called with the StateManager instance as its first argument
25354   and an object representing the transition as its second argument.
25355
25356   After transitioning into a new state the new `currentState` will have its
25357   `enter` method called with the StateManager instance as its first argument
25358   and an object representing the transition as its second argument.
25359
25360   ```javascript
25361   robotManager = Ember.StateManager.create({
25362     initialState: 'poweredDown',
25363     poweredDown: Ember.State.create({
25364       exit: function(stateManager){
25365         console.log("exiting the poweredDown state")
25366       }
25367     }),
25368     poweredUp: Ember.State.create({
25369       enter: function(stateManager){
25370         console.log("entering the poweredUp state. Destroy all humans.")
25371       }
25372     })
25373   })
25374
25375   robotManager.get('currentState.name') // 'poweredDown'
25376   robotManager.transitionTo('poweredUp')
25377
25378   // will log
25379   // 'exiting the poweredDown state'
25380   // 'entering the poweredUp state. Destroy all humans.'
25381   ```
25382
25383   Once a StateManager is already in a state, subsequent attempts to enter that
25384   state will not trigger enter or exit method calls. Attempts to transition
25385   into a state that the manager does not have will result in no changes in the
25386   StateManager's current state:
25387
25388   ```javascript
25389   robotManager = Ember.StateManager.create({
25390     initialState: 'poweredDown',
25391     poweredDown: Ember.State.create({
25392       exit: function(stateManager){
25393         console.log("exiting the poweredDown state")
25394       }
25395     }),
25396     poweredUp: Ember.State.create({
25397       enter: function(stateManager){
25398         console.log("entering the poweredUp state. Destroy all humans.")
25399       }
25400     })
25401   })
25402
25403   robotManager.get('currentState.name') // 'poweredDown'
25404   robotManager.transitionTo('poweredUp')
25405   // will log
25406   // 'exiting the poweredDown state'
25407   // 'entering the poweredUp state. Destroy all humans.'
25408   robotManager.transitionTo('poweredUp') // no logging, no state change
25409
25410   robotManager.transitionTo('someUnknownState') // silently fails
25411   robotManager.get('currentState.name') // 'poweredUp'
25412   ```
25413
25414   Each state property may itself contain properties that are instances of
25415   `Ember.State`. The StateManager can transition to specific sub-states in a
25416   series of transitionTo method calls or via a single transitionTo with the
25417   full path to the specific state. The StateManager will also keep track of the
25418   full path to its currentState
25419
25420   ```javascript
25421   robotManager = Ember.StateManager.create({
25422     initialState: 'poweredDown',
25423     poweredDown: Ember.State.create({
25424       charging: Ember.State.create(),
25425       charged: Ember.State.create()
25426     }),
25427     poweredUp: Ember.State.create({
25428       mobile: Ember.State.create(),
25429       stationary: Ember.State.create()
25430     })
25431   })
25432
25433   robotManager.get('currentState.name') // 'poweredDown'
25434
25435   robotManager.transitionTo('poweredUp')
25436   robotManager.get('currentState.name') // 'poweredUp'
25437
25438   robotManager.transitionTo('mobile')
25439   robotManager.get('currentState.name') // 'mobile'
25440
25441   // transition via a state path
25442   robotManager.transitionTo('poweredDown.charging')
25443   robotManager.get('currentState.name') // 'charging'
25444
25445   robotManager.get('currentState.path') // 'poweredDown.charging'
25446   ```
25447
25448   Enter transition methods will be called for each state and nested child state
25449   in their hierarchical order. Exit methods will be called for each state and
25450   its nested states in reverse hierarchical order.
25451
25452   Exit transitions for a parent state are not called when entering into one of
25453   its child states, only when transitioning to a new section of possible states
25454   in the hierarchy.
25455
25456   ```javascript
25457   robotManager = Ember.StateManager.create({
25458     initialState: 'poweredDown',
25459     poweredDown: Ember.State.create({
25460       enter: function(){},
25461       exit: function(){
25462         console.log("exited poweredDown state")
25463       },
25464       charging: Ember.State.create({
25465         enter: function(){},
25466         exit: function(){}
25467       }),
25468       charged: Ember.State.create({
25469         enter: function(){
25470           console.log("entered charged state")
25471         },
25472         exit: function(){
25473           console.log("exited charged state")
25474         }
25475       })
25476     }),
25477     poweredUp: Ember.State.create({
25478       enter: function(){
25479         console.log("entered poweredUp state")
25480       },
25481       exit: function(){},
25482       mobile: Ember.State.create({
25483         enter: function(){
25484           console.log("entered mobile state")
25485         },
25486         exit: function(){}
25487       }),
25488       stationary: Ember.State.create({
25489         enter: function(){},
25490         exit: function(){}
25491       })
25492     })
25493   })
25494
25495
25496   robotManager.get('currentState.path') // 'poweredDown'
25497   robotManager.transitionTo('charged')
25498   // logs 'entered charged state'
25499   // but does *not* log  'exited poweredDown state'
25500   robotManager.get('currentState.name') // 'charged
25501
25502   robotManager.transitionTo('poweredUp.mobile')
25503   // logs
25504   // 'exited charged state'
25505   // 'exited poweredDown state'
25506   // 'entered poweredUp state'
25507   // 'entered mobile state'
25508   ```
25509
25510   During development you can set a StateManager's `enableLogging` property to
25511   `true` to receive console messages of state transitions.
25512
25513   ```javascript
25514   robotManager = Ember.StateManager.create({
25515     enableLogging: true
25516   })
25517   ```
25518
25519   ## Managing currentState with Actions
25520
25521   To control which transitions are possible for a given state, and
25522   appropriately handle external events, the StateManager can receive and
25523   route action messages to its states via the `send` method. Calling to
25524   `send` with an action name will begin searching for a method with the same
25525   name starting at the current state and moving up through the parent states
25526   in a state hierarchy until an appropriate method is found or the StateManager
25527   instance itself is reached.
25528
25529   If an appropriately named method is found it will be called with the state
25530   manager as the first argument and an optional `context` object as the second
25531   argument.
25532
25533   ```javascript
25534   managerA = Ember.StateManager.create({
25535     initialState: 'stateOne.substateOne.subsubstateOne',
25536     stateOne: Ember.State.create({
25537       substateOne: Ember.State.create({
25538         anAction: function(manager, context){
25539           console.log("an action was called")
25540         },
25541         subsubstateOne: Ember.State.create({})
25542       })
25543     })
25544   })
25545
25546   managerA.get('currentState.name') // 'subsubstateOne'
25547   managerA.send('anAction')
25548   // 'stateOne.substateOne.subsubstateOne' has no anAction method
25549   // so the 'anAction' method of 'stateOne.substateOne' is called
25550   // and logs "an action was called"
25551   // with managerA as the first argument
25552   // and no second argument
25553
25554   someObject = {}
25555   managerA.send('anAction', someObject)
25556   // the 'anAction' method of 'stateOne.substateOne' is called again
25557   // with managerA as the first argument and
25558   // someObject as the second argument.
25559   ```
25560
25561   If the StateManager attempts to send an action but does not find an appropriately named
25562   method in the current state or while moving upwards through the state hierarchy, it will
25563   repeat the process looking for a `unhandledEvent` method. If an `unhandledEvent` method is
25564   found, it will be called with the original event name as the second argument. If an
25565   `unhandledEvent` method is not found, the StateManager will throw a new Ember.Error.
25566
25567   ```javascript
25568   managerB = Ember.StateManager.create({
25569     initialState: 'stateOne.substateOne.subsubstateOne',
25570     stateOne: Ember.State.create({
25571       substateOne: Ember.State.create({
25572         subsubstateOne: Ember.State.create({}),
25573         unhandledEvent: function(manager, eventName, context) {
25574           console.log("got an unhandledEvent with name " + eventName);
25575         }
25576       })
25577     })
25578   })
25579
25580   managerB.get('currentState.name') // 'subsubstateOne'
25581   managerB.send('anAction')
25582   // neither `stateOne.substateOne.subsubstateOne` nor any of it's
25583   // parent states have a handler for `anAction`. `subsubstateOne`
25584   // also does not have a `unhandledEvent` method, but its parent
25585   // state, `substateOne`, does, and it gets fired. It will log
25586   // "got an unhandledEvent with name anAction"
25587   ```
25588
25589   Action detection only moves upwards through the state hierarchy from the current state.
25590   It does not search in other portions of the hierarchy.
25591
25592   ```javascript
25593   managerC = Ember.StateManager.create({
25594     initialState: 'stateOne.substateOne.subsubstateOne',
25595     stateOne: Ember.State.create({
25596       substateOne: Ember.State.create({
25597         subsubstateOne: Ember.State.create({})
25598       })
25599     }),
25600     stateTwo: Ember.State.create({
25601      anAction: function(manager, context){
25602        // will not be called below because it is
25603        // not a parent of the current state
25604      }
25605     })
25606   })
25607
25608   managerC.get('currentState.name') // 'subsubstateOne'
25609   managerC.send('anAction')
25610   // Error: <Ember.StateManager:ember132> could not
25611   // respond to event anAction in state stateOne.substateOne.subsubstateOne.
25612   ```
25613
25614   Inside of an action method the given state should delegate `transitionTo` calls on its
25615   StateManager.
25616
25617   ```javascript
25618   robotManager = Ember.StateManager.create({
25619     initialState: 'poweredDown.charging',
25620     poweredDown: Ember.State.create({
25621       charging: Ember.State.create({
25622         chargeComplete: function(manager, context){
25623           manager.transitionTo('charged')
25624         }
25625       }),
25626       charged: Ember.State.create({
25627         boot: function(manager, context){
25628           manager.transitionTo('poweredUp')
25629         }
25630       })
25631     }),
25632     poweredUp: Ember.State.create({
25633       beginExtermination: function(manager, context){
25634         manager.transitionTo('rampaging')
25635       },
25636       rampaging: Ember.State.create()
25637     })
25638   })
25639
25640   robotManager.get('currentState.name') // 'charging'
25641   robotManager.send('boot') // throws error, no boot action
25642                             // in current hierarchy
25643   robotManager.get('currentState.name') // remains 'charging'
25644
25645   robotManager.send('beginExtermination') // throws error, no beginExtermination
25646                                           // action in current hierarchy
25647   robotManager.get('currentState.name')   // remains 'charging'
25648
25649   robotManager.send('chargeComplete')
25650   robotManager.get('currentState.name')   // 'charged'
25651
25652   robotManager.send('boot')
25653   robotManager.get('currentState.name')   // 'poweredUp'
25654
25655   robotManager.send('beginExtermination', allHumans)
25656   robotManager.get('currentState.name')   // 'rampaging'
25657   ```
25658
25659   Transition actions can also be created using the `transitionTo` method of the `Ember.State` class. The
25660   following example StateManagers are equivalent:
25661
25662   ```javascript
25663   aManager = Ember.StateManager.create({
25664     stateOne: Ember.State.create({
25665       changeToStateTwo: Ember.State.transitionTo('stateTwo')
25666     }),
25667     stateTwo: Ember.State.create({})
25668   })
25669
25670   bManager = Ember.StateManager.create({
25671     stateOne: Ember.State.create({
25672       changeToStateTwo: function(manager, context){
25673         manager.transitionTo('stateTwo', context)
25674       }
25675     }),
25676     stateTwo: Ember.State.create({})
25677   })
25678   ```
25679
25680   @class StateManager
25681   @namespace Ember
25682   @extends Ember.State
25683 **/
25684 Ember.StateManager = Ember.State.extend({
25685   /**
25686     @private
25687
25688     When creating a new statemanager, look for a default state to transition
25689     into. This state can either be named `start`, or can be specified using the
25690     `initialState` property.
25691
25692     @method init
25693   */
25694   init: function() {
25695     this._super();
25696
25697     set(this, 'stateMeta', Ember.Map.create());
25698
25699     var initialState = get(this, 'initialState');
25700
25701     if (!initialState && get(this, 'states.start')) {
25702       initialState = 'start';
25703     }
25704
25705     if (initialState) {
25706       this.transitionTo(initialState);
25707       Ember.assert('Failed to transition to initial state "' + initialState + '"', !!get(this, 'currentState'));
25708     }
25709   },
25710
25711   stateMetaFor: function(state) {
25712     var meta = get(this, 'stateMeta'),
25713         stateMeta = meta.get(state);
25714
25715     if (!stateMeta) {
25716       stateMeta = {};
25717       meta.set(state, stateMeta);
25718     }
25719
25720     return stateMeta;
25721   },
25722
25723   setStateMeta: function(state, key, value) {
25724     return set(this.stateMetaFor(state), key, value);
25725   },
25726
25727   getStateMeta: function(state, key) {
25728     return get(this.stateMetaFor(state), key);
25729   },
25730
25731   /**
25732     The current state from among the manager's possible states. This property should
25733     not be set directly. Use `transitionTo` to move between states by name.
25734
25735     @property currentState
25736     @type Ember.State
25737   */
25738   currentState: null,
25739
25740   /**
25741    The path of the current state. Returns a string representation of the current
25742    state.
25743
25744    @property currentPath
25745    @type String
25746   */
25747   currentPath: Ember.computed('currentState', function() {
25748     return get(this, 'currentState.path');
25749   }),
25750
25751   /**
25752     The name of transitionEvent that this stateManager will dispatch
25753
25754     @property transitionEvent
25755     @type String
25756     @default 'setup'
25757   */
25758   transitionEvent: 'setup',
25759
25760   /**
25761     If set to true, `errorOnUnhandledEvents` will cause an exception to be
25762     raised if you attempt to send an event to a state manager that is not
25763     handled by the current state or any of its parent states.
25764
25765     @property errorOnUnhandledEvents
25766     @type Boolean
25767     @default true
25768   */
25769   errorOnUnhandledEvent: true,
25770
25771   send: function(event) {
25772     var contexts = [].slice.call(arguments, 1);
25773     Ember.assert('Cannot send event "' + event + '" while currentState is ' + get(this, 'currentState'), get(this, 'currentState'));
25774     return sendEvent.call(this, event, contexts, false);
25775   },
25776   unhandledEvent: function(manager, event) {
25777     if (get(this, 'errorOnUnhandledEvent')) {
25778       throw new Ember.Error(this.toString() + " could not respond to event " + event + " in state " + get(this, 'currentState.path') + ".");
25779     }
25780   },
25781
25782   /**
25783     Finds a state by its state path.
25784
25785     Example:
25786
25787     ```javascript
25788     manager = Ember.StateManager.create({
25789       root: Ember.State.create({
25790         dashboard: Ember.State.create()
25791       })
25792     });
25793
25794     manager.getStateByPath(manager, "root.dashboard")
25795
25796     // returns the dashboard state
25797     ```
25798
25799     @method getStateByPath
25800     @param {Ember.State} root the state to start searching from
25801     @param {String} path the state path to follow
25802     @return {Ember.State} the state at the end of the path
25803   */
25804   getStateByPath: function(root, path) {
25805     var parts = path.split('.'),
25806         state = root;
25807
25808     for (var i=0, len=parts.length; i<len; i++) {
25809       state = get(get(state, 'states'), parts[i]);
25810       if (!state) { break; }
25811     }
25812
25813     return state;
25814   },
25815
25816   findStateByPath: function(state, path) {
25817     var possible;
25818
25819     while (!possible && state) {
25820       possible = this.getStateByPath(state, path);
25821       state = get(state, 'parentState');
25822     }
25823
25824     return possible;
25825   },
25826
25827   /**
25828     A state stores its child states in its `states` hash.
25829     This code takes a path like `posts.show` and looks
25830     up `root.states.posts.states.show`.
25831
25832     It returns a list of all of the states from the
25833     root, which is the list of states to call `enter`
25834     on.
25835
25836     @method getStatesInPath
25837     @param root
25838     @param path
25839   */
25840   getStatesInPath: function(root, path) {
25841     if (!path || path === "") { return undefined; }
25842     var parts = path.split('.'),
25843         result = [],
25844         states,
25845         state;
25846
25847     for (var i=0, len=parts.length; i<len; i++) {
25848       states = get(root, 'states');
25849       if (!states) { return undefined; }
25850       state = get(states, parts[i]);
25851       if (state) { root = state; result.push(state); }
25852       else { return undefined; }
25853     }
25854
25855     return result;
25856   },
25857
25858   goToState: function() {
25859     // not deprecating this yet so people don't constantly need to
25860     // make trivial changes for little reason.
25861     return this.transitionTo.apply(this, arguments);
25862   },
25863
25864   transitionTo: function(path, context) {
25865     // XXX When is transitionTo called with no path
25866     if (Ember.isEmpty(path)) { return; }
25867
25868     // The ES6 signature of this function is `path, ...contexts`
25869     var contexts = context ? Array.prototype.slice.call(arguments, 1) : [],
25870         currentState = get(this, 'currentState') || this;
25871
25872     // First, get the enter, exit and resolve states for the current state
25873     // and specified path. If possible, use an existing cache.
25874     var hash = this.contextFreeTransition(currentState, path);
25875
25876     // Next, process the raw state information for the contexts passed in.
25877     var transition = new Transition(hash).normalize(this, contexts);
25878
25879     this.enterState(transition);
25880     this.triggerSetupContext(transition);
25881   },
25882
25883   contextFreeTransition: function(currentState, path) {
25884     var cache = currentState.pathsCache[path];
25885     if (cache) { return cache; }
25886
25887     var enterStates = this.getStatesInPath(currentState, path),
25888         exitStates = [],
25889         resolveState = currentState;
25890
25891     // Walk up the states. For each state, check whether a state matching
25892     // the `path` is nested underneath. This will find the closest
25893     // parent state containing `path`.
25894     //
25895     // This allows the user to pass in a relative path. For example, for
25896     // the following state hierarchy:
25897     //
25898     //    | |root
25899     //    | |- posts
25900     //    | | |- show (* current)
25901     //    | |- comments
25902     //    | | |- show
25903     //
25904     // If the current state is `<root.posts.show>`, an attempt to
25905     // transition to `comments.show` will match `<root.comments.show>`.
25906     //
25907     // First, this code will look for root.posts.show.comments.show.
25908     // Next, it will look for root.posts.comments.show. Finally,
25909     // it will look for `root.comments.show`, and find the state.
25910     //
25911     // After this process, the following variables will exist:
25912     //
25913     // * resolveState: a common parent state between the current
25914     //   and target state. In the above example, `<root>` is the
25915     //   `resolveState`.
25916     // * enterStates: a list of all of the states represented
25917     //   by the path from the `resolveState`. For example, for
25918     //   the path `root.comments.show`, `enterStates` would have
25919     //   `[<root.comments>, <root.comments.show>]`
25920     // * exitStates: a list of all of the states from the
25921     //   `resolveState` to the `currentState`. In the above
25922     //   example, `exitStates` would have
25923     //   `[<root.posts>`, `<root.posts.show>]`.
25924     while (resolveState && !enterStates) {
25925       exitStates.unshift(resolveState);
25926
25927       resolveState = get(resolveState, 'parentState');
25928       if (!resolveState) {
25929         enterStates = this.getStatesInPath(this, path);
25930         if (!enterStates) {
25931           Ember.assert('Could not find state for path: "'+path+'"');
25932           return;
25933         }
25934       }
25935       enterStates = this.getStatesInPath(resolveState, path);
25936     }
25937
25938     // If the path contains some states that are parents of both the
25939     // current state and the target state, remove them.
25940     //
25941     // For example, in the following hierarchy:
25942     //
25943     // |- root
25944     // | |- post
25945     // | | |- index (* current)
25946     // | | |- show
25947     //
25948     // If the `path` is `root.post.show`, the three variables will
25949     // be:
25950     //
25951     // * resolveState: `<state manager>`
25952     // * enterStates: `[<root>, <root.post>, <root.post.show>]`
25953     // * exitStates: `[<root>, <root.post>, <root.post.index>]`
25954     //
25955     // The goal of this code is to remove the common states, so we
25956     // have:
25957     //
25958     // * resolveState: `<root.post>`
25959     // * enterStates: `[<root.post.show>]`
25960     // * exitStates: `[<root.post.index>]`
25961     //
25962     // This avoid unnecessary calls to the enter and exit transitions.
25963     while (enterStates.length > 0 && enterStates[0] === exitStates[0]) {
25964       resolveState = enterStates.shift();
25965       exitStates.shift();
25966     }
25967
25968     // Cache the enterStates, exitStates, and resolveState for the
25969     // current state and the `path`.
25970     var transitions = currentState.pathsCache[path] = {
25971       exitStates: exitStates,
25972       enterStates: enterStates,
25973       resolveState: resolveState
25974     };
25975
25976     return transitions;
25977   },
25978
25979   triggerSetupContext: function(transitions) {
25980     var contexts = transitions.contexts,
25981         offset = transitions.enterStates.length - contexts.length,
25982         enterStates = transitions.enterStates,
25983         transitionEvent = get(this, 'transitionEvent');
25984
25985     Ember.assert("More contexts provided than states", offset >= 0);
25986
25987     arrayForEach.call(enterStates, function(state, idx) {
25988       state.trigger(transitionEvent, this, contexts[idx-offset]);
25989     }, this);
25990   },
25991
25992   getState: function(name) {
25993     var state = get(this, name),
25994         parentState = get(this, 'parentState');
25995
25996     if (state) {
25997       return state;
25998     } else if (parentState) {
25999       return parentState.getState(name);
26000     }
26001   },
26002
26003   enterState: function(transition) {
26004     var log = this.enableLogging;
26005
26006     var exitStates = transition.exitStates.slice(0).reverse();
26007     arrayForEach.call(exitStates, function(state) {
26008       state.trigger('exit', this);
26009     }, this);
26010
26011     arrayForEach.call(transition.enterStates, function(state) {
26012       if (log) { Ember.Logger.log("STATEMANAGER: Entering " + get(state, 'path')); }
26013       state.trigger('enter', this);
26014     }, this);
26015
26016     set(this, 'currentState', transition.finalState);
26017   }
26018 });
26019
26020 })();
26021
26022
26023
26024 (function() {
26025 /**
26026 Ember States
26027
26028 @module ember
26029 @submodule ember-states
26030 @requires ember-runtime
26031 */
26032
26033 })();
26034
26035
26036 })();
26037 // Version: v1.0.0-pre.3-19-g015138e
26038 // Last commit: 015138e (2013-01-17 23:02:17 -0800)
26039
26040
26041 (function() {
26042 /**
26043 Ember
26044
26045 @module ember
26046 */
26047
26048 })();
26049