(examples) Reorganizes some files.
[profile/ivi/cowhide.git] / lib / ember-latest.js
1 // Version: v1.0.pre-160-g7d62790
2 // Last commit: 7d62790 (2012-09-26 15:59:36 -0700)
3
4
5 (function() {
6 /*global __fail__*/
7
8 /**
9 Ember Debug
10
11 @module ember
12 @submodule ember-debug
13 */
14
15 /**
16 @class Ember
17 */
18
19 if ('undefined' === typeof Ember) {
20   Ember = {};
21
22   if ('undefined' !== typeof window) {
23     window.Em = window.Ember = Em = Ember;
24   }
25 }
26
27 Ember.ENV = 'undefined' === typeof ENV ? {} : ENV;
28
29 if (!('MANDATORY_SETTER' in Ember.ENV)) {
30   Ember.ENV.MANDATORY_SETTER = true; // default to true for debug dist
31 }
32
33 /**
34   Define an assertion that will throw an exception if the condition is not
35   met.  Ember build tools will remove any calls to Ember.assert() when
36   doing a production build. Example:
37
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   @method assert
44   @param {String} desc A description of the assertion.  This will become
45     the text of the Error thrown if the assertion fails.
46
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
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 // Version: v1.0.pre-160-g7d62790
144 // Last commit: 7d62790 (2012-09-26 15:59:36 -0700)
145
146
147 (function() {
148 /*globals Em:true ENV */
149
150 /**
151 @module ember
152 @submodule ember-metal
153 */
154
155 /**
156   All Ember methods and functions are defined inside of this namespace.
157   You generally should not add new properties to this namespace as it may be
158   overwritten by future versions of Ember.
159
160   You can also use the shorthand "Em" instead of "Ember".
161
162   Ember-Runtime is a framework that provides core functions for
163   Ember including cross-platform functions, support for property
164   observing and objects. Its focus is on small size and performance. You can
165   use this in place of or along-side other cross-platform libraries such as
166   jQuery.
167
168   The core Runtime framework is based on the jQuery API with a number of
169   performance optimizations.
170
171   @class Ember
172   @static
173   @version 1.0.pre
174 */
175
176 if ('undefined' === typeof Ember) {
177   // Create core object. Make it act like an instance of Ember.Namespace so that
178   // objects assigned to it are given a sane string representation.
179   Ember = {};
180 }
181
182 // aliases needed to keep minifiers from removing the global context
183 if ('undefined' !== typeof window) {
184   window.Em = window.Ember = Em = Ember;
185 }
186
187 // Make sure these are set whether Ember was already defined or not
188
189 Ember.isNamespace = true;
190
191 Ember.toString = function() { return "Ember"; };
192
193
194 /**
195   @property VERSION
196   @type String
197   @default '1.0.pre'
198   @final
199 */
200 Ember.VERSION = '1.0.pre';
201
202 /**
203   Standard environmental variables.  You can define these in a global `ENV`
204   variable before loading Ember to control various configuration
205   settings.
206
207   @property ENV
208   @type Hash
209 */
210 Ember.ENV = Ember.ENV || ('undefined' === typeof ENV ? {} : ENV);
211
212 Ember.config = Ember.config || {};
213
214 // ..........................................................
215 // BOOTSTRAP
216 //
217
218 /**
219   Determines whether Ember should enhances some built-in object
220   prototypes to provide a more friendly API.  If enabled, a few methods
221   will be added to Function, String, and Array.  Object.prototype will not be
222   enhanced, which is the one that causes most troubles for people.
223
224   In general we recommend leaving this option set to true since it rarely
225   conflicts with other code.  If you need to turn it off however, you can
226   define an ENV.EXTEND_PROTOTYPES config to disable it.
227
228   @property EXTEND_PROTOTYPES
229   @type Boolean
230   @default true
231 */
232 Ember.EXTEND_PROTOTYPES = (Ember.ENV.EXTEND_PROTOTYPES !== false);
233
234 /**
235   Determines whether Ember logs a full stack trace during deprecation warnings
236
237   @property LOG_STACKTRACE_ON_DEPRECATION
238   @type Boolean
239   @default true
240 */
241 Ember.LOG_STACKTRACE_ON_DEPRECATION = (Ember.ENV.LOG_STACKTRACE_ON_DEPRECATION !== false);
242
243 /**
244   Determines whether Ember should add ECMAScript 5 shims to older browsers.
245
246   @property SHIM_ES5
247   @type Boolean
248   @default Ember.EXTEND_PROTOTYPES
249 */
250 Ember.SHIM_ES5 = (Ember.ENV.SHIM_ES5 === false) ? false : Ember.EXTEND_PROTOTYPES;
251
252
253 /**
254   Determines whether computed properties are cacheable by default.
255   This option will be removed for the 1.1 release.
256
257   When caching is enabled by default, you can use `volatile()` to disable
258   caching on individual computed properties.
259
260   @property CP_DEFAULT_CACHEABLE
261   @type Boolean
262   @default true
263 */
264 Ember.CP_DEFAULT_CACHEABLE = (Ember.ENV.CP_DEFAULT_CACHEABLE !== false);
265
266 /**
267   Determines whether views render their templates using themselves
268   as the context, or whether it is inherited from the parent. This option
269   will be removed in the 1.1 release.
270
271   If you need to update your application to use the new context rules, simply
272   prefix property access with `view.`:
273
274   Before:
275
276   ``` handlebars
277   {{#each App.photosController}}
278     Photo Title: {{title}}
279     {{#view App.InfoView contentBinding="this"}}
280       {{content.date}}
281       {{content.cameraType}}
282       {{otherViewProperty}}
283     {{/view}}
284   {{/each}}
285   ```
286
287   After:
288
289   ``` handlebars
290   {{#each App.photosController}}
291     Photo Title: {{title}}
292     {{#view App.InfoView}}
293       {{date}}
294       {{cameraType}}
295       {{view.otherViewProperty}}
296     {{/view}}
297   {{/each}}
298   ```
299
300   @property VIEW_PRESERVES_CONTEXT
301   @type Boolean
302   @default true
303 */
304 Ember.VIEW_PRESERVES_CONTEXT = (Ember.ENV.VIEW_PRESERVES_CONTEXT !== false);
305
306 /**
307   Empty function.  Useful for some operations.
308
309   @method K
310   @private
311   @return {Object}
312 */
313 Ember.K = function() { return this; };
314
315
316 // Stub out the methods defined by the ember-debug package in case it's not loaded
317
318 if ('undefined' === typeof Ember.assert) { Ember.assert = Ember.K; }
319 if ('undefined' === typeof Ember.warn) { Ember.warn = Ember.K; }
320 if ('undefined' === typeof Ember.deprecate) { Ember.deprecate = Ember.K; }
321 if ('undefined' === typeof Ember.deprecateFunc) {
322   Ember.deprecateFunc = function(_, func) { return func; };
323 }
324
325 // These are deprecated but still supported
326
327 if ('undefined' === typeof ember_assert) { window.ember_assert = Ember.K; }
328 if ('undefined' === typeof ember_warn) { window.ember_warn = Ember.K; }
329 if ('undefined' === typeof ember_deprecate) { window.ember_deprecate = Ember.K; }
330 if ('undefined' === typeof ember_deprecateFunc) {
331   window.ember_deprecateFunc = function(_, func) { return func; };
332 }
333
334
335 // ..........................................................
336 // LOGGER
337 //
338
339 /**
340   Inside Ember-Metal, simply uses the window.console object.
341   Override this to provide more robust logging functionality.
342
343   @class Logger
344   @namespace Ember
345 */
346 Ember.Logger = window.console || { log: Ember.K, warn: Ember.K, error: Ember.K, info: Ember.K, debug: Ember.K };
347
348
349 // ..........................................................
350 // ERROR HANDLING
351 //
352
353 /**
354   A function may be assigned to `Ember.onerror` to be called when Ember internals encounter an error.
355   This is useful for specialized error handling and reporting code.
356
357   @event onerror
358   @for Ember
359   @param {Exception} error the error object
360 */
361 Ember.onerror = null;
362
363 /**
364   @private
365
366   Wrap code block in a try/catch if {{#crossLink "Ember/onerror"}}{{/crossLink}} is set.
367
368   @method handleErrors
369   @for Ember
370   @param {Function} func
371   @param [context]
372 */
373 Ember.handleErrors = function(func, context) {
374   // Unfortunately in some browsers we lose the backtrace if we rethrow the existing error,
375   // so in the event that we don't have an `onerror` handler we don't wrap in a try/catch
376   if ('function' === typeof Ember.onerror) {
377     try {
378       return func.apply(context || this);
379     } catch (error) {
380       Ember.onerror(error);
381     }
382   } else {
383     return func.apply(context || this);
384   }
385 };
386
387 })();
388
389
390
391 (function() {
392 /*jshint newcap:false*/
393
394 /**
395 @module ember-metal
396 */
397
398 // NOTE: There is a bug in jshint that doesn't recognize `Object()` without `new`
399 // as being ok unless both `newcap:false` and not `use strict`.
400 // https://github.com/jshint/jshint/issues/392
401
402 // Testing this is not ideal, but we want to use native functions
403 // if available, but not to use versions created by libraries like Prototype
404 var isNativeFunc = function(func) {
405   // This should probably work in all browsers likely to have ES5 array methods
406   return func && Function.prototype.toString.call(func).indexOf('[native code]') > -1;
407 };
408
409 // From: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/map
410 var arrayMap = isNativeFunc(Array.prototype.map) ? Array.prototype.map : function(fun /*, thisp */) {
411   //"use strict";
412
413   if (this === void 0 || this === null) {
414     throw new TypeError();
415   }
416
417   var t = Object(this);
418   var len = t.length >>> 0;
419   if (typeof fun !== "function") {
420     throw new TypeError();
421   }
422
423   var res = new Array(len);
424   var thisp = arguments[1];
425   for (var i = 0; i < len; i++) {
426     if (i in t) {
427       res[i] = fun.call(thisp, t[i], i, t);
428     }
429   }
430
431   return res;
432 };
433
434 // From: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/foreach
435 var arrayForEach = isNativeFunc(Array.prototype.forEach) ? Array.prototype.forEach : function(fun /*, thisp */) {
436   //"use strict";
437
438   if (this === void 0 || this === null) {
439     throw new TypeError();
440   }
441
442   var t = Object(this);
443   var len = t.length >>> 0;
444   if (typeof fun !== "function") {
445     throw new TypeError();
446   }
447
448   var thisp = arguments[1];
449   for (var i = 0; i < len; i++) {
450     if (i in t) {
451       fun.call(thisp, t[i], i, t);
452     }
453   }
454 };
455
456 var arrayIndexOf = isNativeFunc(Array.prototype.indexOf) ? Array.prototype.indexOf : function (obj, fromIndex) {
457   if (fromIndex === null || fromIndex === undefined) { fromIndex = 0; }
458   else if (fromIndex < 0) { fromIndex = Math.max(0, this.length + fromIndex); }
459   for (var i = fromIndex, j = this.length; i < j; i++) {
460     if (this[i] === obj) { return i; }
461   }
462   return -1;
463 };
464
465 Ember.ArrayPolyfills = {
466   map: arrayMap,
467   forEach: arrayForEach,
468   indexOf: arrayIndexOf
469 };
470
471 var utils = Ember.EnumerableUtils = {
472   map: function(obj, callback, thisArg) {
473     return obj.map ? obj.map.call(obj, callback, thisArg) : arrayMap.call(obj, callback, thisArg);
474   },
475
476   forEach: function(obj, callback, thisArg) {
477     return obj.forEach ? obj.forEach.call(obj, callback, thisArg) : arrayForEach.call(obj, callback, thisArg);
478   },
479
480   indexOf: function(obj, element, index) {
481     return obj.indexOf ? obj.indexOf.call(obj, element, index) : arrayIndexOf.call(obj, element, index);
482   },
483
484   indexesOf: function(obj, elements) {
485     return elements === undefined ? [] : utils.map(elements, function(item) {
486       return utils.indexOf(obj, item);
487     });
488   },
489
490   removeObject: function(array, item) {
491     var index = utils.indexOf(array, item);
492     if (index !== -1) { array.splice(index, 1); }
493   }
494 };
495
496
497 if (Ember.SHIM_ES5) {
498   if (!Array.prototype.map) {
499     Array.prototype.map = arrayMap;
500   }
501
502   if (!Array.prototype.forEach) {
503     Array.prototype.forEach = arrayForEach;
504   }
505
506   if (!Array.prototype.indexOf) {
507     Array.prototype.indexOf = arrayIndexOf;
508   }
509 }
510
511 })();
512
513
514
515 (function() {
516 /*globals Node */
517 /**
518 @module ember-metal
519 */
520
521 /**
522   Platform specific methods and feature detectors needed by the framework.
523
524   @class platform
525   @namespace Ember
526   @static
527 */
528 var platform = Ember.platform = {};
529
530
531 /**
532   Identical to Object.create().  Implements if not available natively.
533   @method create
534   @for Ember
535 */
536 Ember.create = Object.create;
537
538 if (!Ember.create) {
539   var K = function() {};
540
541   Ember.create = function(obj, props) {
542     K.prototype = obj;
543     obj = new K();
544     if (props) {
545       K.prototype = obj;
546       for (var prop in props) {
547         K.prototype[prop] = props[prop].value;
548       }
549       obj = new K();
550     }
551     K.prototype = null;
552
553     return obj;
554   };
555
556   Ember.create.isSimulated = true;
557 }
558
559 var defineProperty = Object.defineProperty;
560 var canRedefineProperties, canDefinePropertyOnDOM;
561
562 // Catch IE8 where Object.defineProperty exists but only works on DOM elements
563 if (defineProperty) {
564   try {
565     defineProperty({}, 'a',{get:function(){}});
566   } catch (e) {
567     defineProperty = null;
568   }
569 }
570
571 if (defineProperty) {
572   // Detects a bug in Android <3.2 where you cannot redefine a property using
573   // Object.defineProperty once accessors have already been set.
574   canRedefineProperties = (function() {
575     var obj = {};
576
577     defineProperty(obj, 'a', {
578       configurable: true,
579       enumerable: true,
580       get: function() { },
581       set: function() { }
582     });
583
584     defineProperty(obj, 'a', {
585       configurable: true,
586       enumerable: true,
587       writable: true,
588       value: true
589     });
590
591     return obj.a === true;
592   })();
593
594   // This is for Safari 5.0, which supports Object.defineProperty, but not
595   // on DOM nodes.
596   canDefinePropertyOnDOM = (function(){
597     try {
598       defineProperty(document.createElement('div'), 'definePropertyOnDOM', {});
599       return true;
600     } catch(e) { }
601
602     return false;
603   })();
604
605   if (!canRedefineProperties) {
606     defineProperty = null;
607   } else if (!canDefinePropertyOnDOM) {
608     defineProperty = function(obj, keyName, desc){
609       var isNode;
610
611       if (typeof Node === "object") {
612         isNode = obj instanceof Node;
613       } else {
614         isNode = typeof obj === "object" && typeof obj.nodeType === "number" && typeof obj.nodeName === "string";
615       }
616
617       if (isNode) {
618         // TODO: Should we have a warning here?
619         return (obj[keyName] = desc.value);
620       } else {
621         return Object.defineProperty(obj, keyName, desc);
622       }
623     };
624   }
625 }
626
627 /**
628 @class platform
629 @namespace Ember
630 */
631
632 /**
633   Identical to Object.defineProperty().  Implements as much functionality
634   as possible if not available natively.
635
636   @method defineProperty
637   @param {Object} obj The object to modify
638   @param {String} keyName property name to modify
639   @param {Object} desc descriptor hash
640   @return {void}
641 */
642 platform.defineProperty = defineProperty;
643
644 /**
645   Set to true if the platform supports native getters and setters.
646
647   @property hasPropertyAccessors
648   @final
649 */
650 platform.hasPropertyAccessors = true;
651
652 if (!platform.defineProperty) {
653   platform.hasPropertyAccessors = false;
654
655   platform.defineProperty = function(obj, keyName, desc) {
656     if (!desc.get) { obj[keyName] = desc.value; }
657   };
658
659   platform.defineProperty.isSimulated = true;
660 }
661
662 if (Ember.ENV.MANDATORY_SETTER && !platform.hasPropertyAccessors) {
663   Ember.ENV.MANDATORY_SETTER = false;
664 }
665
666 })();
667
668
669
670 (function() {
671 /**
672 @module ember-metal
673 */
674
675 var o_defineProperty = Ember.platform.defineProperty,
676     o_create = Ember.create,
677     // Used for guid generation...
678     GUID_KEY = '__ember'+ (+ new Date()),
679     uuid         = 0,
680     numberCache  = [],
681     stringCache  = {};
682
683 var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER;
684
685 /**
686   @private
687
688   A unique key used to assign guids and other private metadata to objects.
689   If you inspect an object in your browser debugger you will often see these.
690   They can be safely ignored.
691
692   On browsers that support it, these properties are added with enumeration
693   disabled so they won't show up when you iterate over your properties.
694
695   @property GUID_KEY
696   @for Ember
697   @type String
698   @final
699 */
700 Ember.GUID_KEY = GUID_KEY;
701
702 var GUID_DESC = {
703   writable:    false,
704   configurable: false,
705   enumerable:  false,
706   value: null
707 };
708
709 /**
710   @private
711
712   Generates a new guid, optionally saving the guid to the object that you
713   pass in.  You will rarely need to use this method.  Instead you should
714   call Ember.guidFor(obj), which return an existing guid if available.
715
716   @method generateGuid
717   @for Ember
718   @param {Object} [obj] Object the guid will be used for.  If passed in, the guid will
719     be saved on the object and reused whenever you pass the same object
720     again.
721
722     If no object is passed, just generate a new guid.
723
724   @param {String} [prefix] Prefix to place in front of the guid.  Useful when you want to
725     separate the guid into separate namespaces.
726
727   @return {String} the guid
728 */
729 Ember.generateGuid = function generateGuid(obj, prefix) {
730   if (!prefix) prefix = 'ember';
731   var ret = (prefix + (uuid++));
732   if (obj) {
733     GUID_DESC.value = ret;
734     o_defineProperty(obj, GUID_KEY, GUID_DESC);
735   }
736   return ret ;
737 };
738
739 /**
740   @private
741
742   Returns a unique id for the object.  If the object does not yet have
743   a guid, one will be assigned to it.  You can call this on any object,
744   Ember.Object-based or not, but be aware that it will add a _guid property.
745
746   You can also use this method on DOM Element objects.
747
748   @method guidFor
749   @for Ember
750   @param obj {Object} any object, string, number, Element, or primitive
751   @return {String} the unique guid for this instance.
752 */
753 Ember.guidFor = function guidFor(obj) {
754
755   // special cases where we don't want to add a key to object
756   if (obj === undefined) return "(undefined)";
757   if (obj === null) return "(null)";
758
759   var cache, ret;
760   var type = typeof obj;
761
762   // Don't allow prototype changes to String etc. to change the guidFor
763   switch(type) {
764     case 'number':
765       ret = numberCache[obj];
766       if (!ret) ret = numberCache[obj] = 'nu'+obj;
767       return ret;
768
769     case 'string':
770       ret = stringCache[obj];
771       if (!ret) ret = stringCache[obj] = 'st'+(uuid++);
772       return ret;
773
774     case 'boolean':
775       return obj ? '(true)' : '(false)';
776
777     default:
778       if (obj[GUID_KEY]) return obj[GUID_KEY];
779       if (obj === Object) return '(Object)';
780       if (obj === Array)  return '(Array)';
781       ret = 'ember'+(uuid++);
782       GUID_DESC.value = ret;
783       o_defineProperty(obj, GUID_KEY, GUID_DESC);
784       return ret;
785   }
786 };
787
788 // ..........................................................
789 // META
790 //
791
792 var META_DESC = {
793   writable:    true,
794   configurable: false,
795   enumerable:  false,
796   value: null
797 };
798
799 var META_KEY = Ember.GUID_KEY+'_meta';
800
801 /**
802   The key used to store meta information on object for property observing.
803
804   @property META_KEY
805   @for Ember
806   @private
807   @final
808   @type String
809 */
810 Ember.META_KEY = META_KEY;
811
812 // Placeholder for non-writable metas.
813 var EMPTY_META = {
814   descs: {},
815   watching: {}
816 };
817
818 if (MANDATORY_SETTER) { EMPTY_META.values = {}; }
819
820 Ember.EMPTY_META = EMPTY_META;
821
822 if (Object.freeze) Object.freeze(EMPTY_META);
823
824 var isDefinePropertySimulated = Ember.platform.defineProperty.isSimulated;
825
826 function Meta(obj) {
827   this.descs = {};
828   this.watching = {};
829   this.cache = {};
830   this.source = obj;
831 }
832
833 if (isDefinePropertySimulated) {
834   // on platforms that don't support enumerable false
835   // make meta fail jQuery.isPlainObject() to hide from
836   // jQuery.extend() by having a property that fails
837   // hasOwnProperty check.
838   Meta.prototype.__preventPlainObject__ = true;
839 }
840
841 /**
842   Retrieves the meta hash for an object.  If 'writable' is true ensures the
843   hash is writable for this object as well.
844
845   The meta object contains information about computed property descriptors as
846   well as any watched properties and other information.  You generally will
847   not access this information directly but instead work with higher level
848   methods that manipulate this hash indirectly.
849
850   @method meta
851   @for Ember
852   @private
853
854   @param {Object} obj The object to retrieve meta for
855
856   @param {Boolean} [writable=true] Pass false if you do not intend to modify
857     the meta hash, allowing the method to avoid making an unnecessary copy.
858
859   @return {Hash}
860 */
861 Ember.meta = function meta(obj, writable) {
862
863   var ret = obj[META_KEY];
864   if (writable===false) return ret || EMPTY_META;
865
866   if (!ret) {
867     if (!isDefinePropertySimulated) o_defineProperty(obj, META_KEY, META_DESC);
868
869     ret = new Meta(obj);
870
871     if (MANDATORY_SETTER) { ret.values = {}; }
872
873     obj[META_KEY] = ret;
874
875     // make sure we don't accidentally try to create constructor like desc
876     ret.descs.constructor = null;
877
878   } else if (ret.source !== obj) {
879     if (!isDefinePropertySimulated) o_defineProperty(obj, META_KEY, META_DESC);
880
881     ret = o_create(ret);
882     ret.descs    = o_create(ret.descs);
883     ret.watching = o_create(ret.watching);
884     ret.cache    = {};
885     ret.source   = obj;
886
887     if (MANDATORY_SETTER) { ret.values = o_create(ret.values); }
888
889     obj[META_KEY] = ret;
890   }
891   return ret;
892 };
893
894 Ember.getMeta = function getMeta(obj, property) {
895   var meta = Ember.meta(obj, false);
896   return meta[property];
897 };
898
899 Ember.setMeta = function setMeta(obj, property, value) {
900   var meta = Ember.meta(obj, true);
901   meta[property] = value;
902   return value;
903 };
904
905 /**
906   @private
907
908   In order to store defaults for a class, a prototype may need to create
909   a default meta object, which will be inherited by any objects instantiated
910   from the class's constructor.
911
912   However, the properties of that meta object are only shallow-cloned,
913   so if a property is a hash (like the event system's `listeners` hash),
914   it will by default be shared across all instances of that class.
915
916   This method allows extensions to deeply clone a series of nested hashes or
917   other complex objects. For instance, the event system might pass
918   ['listeners', 'foo:change', 'ember157'] to `prepareMetaPath`, which will
919   walk down the keys provided.
920
921   For each key, if the key does not exist, it is created. If it already
922   exists and it was inherited from its constructor, the constructor's
923   key is cloned.
924
925   You can also pass false for `writable`, which will simply return
926   undefined if `prepareMetaPath` discovers any part of the path that
927   shared or undefined.
928
929   @method metaPath
930   @for Ember
931   @param {Object} obj The object whose meta we are examining
932   @param {Array} path An array of keys to walk down
933   @param {Boolean} writable whether or not to create a new meta
934     (or meta property) if one does not already exist or if it's
935     shared with its constructor
936 */
937 Ember.metaPath = function metaPath(obj, path, writable) {
938   var meta = Ember.meta(obj, writable), keyName, value;
939
940   for (var i=0, l=path.length; i<l; i++) {
941     keyName = path[i];
942     value = meta[keyName];
943
944     if (!value) {
945       if (!writable) { return undefined; }
946       value = meta[keyName] = { __ember_source__: obj };
947     } else if (value.__ember_source__ !== obj) {
948       if (!writable) { return undefined; }
949       value = meta[keyName] = o_create(value);
950       value.__ember_source__ = obj;
951     }
952
953     meta = value;
954   }
955
956   return value;
957 };
958
959 /**
960   @private
961
962   Wraps the passed function so that `this._super` will point to the superFunc
963   when the function is invoked.  This is the primitive we use to implement
964   calls to super.
965
966   @method wrap
967   @for Ember
968   @param {Function} func The function to call
969   @param {Function} superFunc The super function.
970   @return {Function} wrapped function.
971 */
972 Ember.wrap = function(func, superFunc) {
973
974   function K() {}
975
976   var newFunc = function() {
977     var ret, sup = this._super;
978     this._super = superFunc || K;
979     ret = func.apply(this, arguments);
980     this._super = sup;
981     return ret;
982   };
983
984   newFunc.base = func;
985   return newFunc;
986 };
987
988 /**
989   Returns true if the passed object is an array or Array-like.
990
991   Ember Array Protocol:
992
993     - the object has an objectAt property
994     - the object is a native Array
995     - the object is an Object, and has a length property
996
997   Unlike Ember.typeOf this method returns true even if the passed object is
998   not formally array but appears to be array-like (i.e. implements Ember.Array)
999
1000       Ember.isArray(); // false
1001       Ember.isArray([]); // true
1002       Ember.isArray( Ember.ArrayProxy.create({ content: [] }) ); // true
1003
1004   @method isArray
1005   @for Ember
1006   @param {Object} obj The object to test
1007   @return {Boolean}
1008 */
1009 Ember.isArray = function(obj) {
1010   if (!obj || obj.setInterval) { return false; }
1011   if (Array.isArray && Array.isArray(obj)) { return true; }
1012   if (Ember.Array && Ember.Array.detect(obj)) { return true; }
1013   if ((obj.length !== undefined) && 'object'===typeof obj) { return true; }
1014   return false;
1015 };
1016
1017 /**
1018   Forces the passed object to be part of an array.  If the object is already
1019   an array or array-like, returns the object.  Otherwise adds the object to
1020   an array.  If obj is null or undefined, returns an empty array.
1021
1022       Ember.makeArray();          => []
1023       Ember.makeArray(null);      => []
1024       Ember.makeArray(undefined); => []
1025       Ember.makeArray('lindsay'); => ['lindsay']
1026       Ember.makeArray([1,2,42]);  => [1,2,42]
1027
1028       var controller = Ember.ArrayProxy.create({ content: [] });
1029       Ember.makeArray(controller) === controller;   => true
1030
1031   @method makeArray
1032   @for Ember
1033   @param {Object} obj the object
1034   @return {Array}
1035 */
1036 Ember.makeArray = function(obj) {
1037   if (obj === null || obj === undefined) { return []; }
1038   return Ember.isArray(obj) ? obj : [obj];
1039 };
1040
1041 function canInvoke(obj, methodName) {
1042   return !!(obj && typeof obj[methodName] === 'function');
1043 }
1044
1045 /**
1046   Checks to see if the `methodName` exists on the `obj`.
1047
1048   @method canInvoke
1049   @for Ember
1050   @param {Object} obj The object to check for the method
1051   @param {String} methodName The method name to check for
1052 */
1053 Ember.canInvoke = canInvoke;
1054
1055 /**
1056   Checks to see if the `methodName` exists on the `obj`,
1057   and if it does, invokes it with the arguments passed.
1058
1059   @method tryInvoke
1060   @for Ember
1061   @param {Object} obj The object to check for the method
1062   @param {String} methodName The method name to check for
1063   @param {Array} [args] The arguments to pass to the method
1064   @return {anything} the return value of the invoked method or undefined if it cannot be invoked
1065 */
1066 Ember.tryInvoke = function(obj, methodName, args) {
1067   if (canInvoke(obj, methodName)) {
1068     return obj[methodName].apply(obj, args || []);
1069   }
1070 };
1071
1072 })();
1073
1074
1075
1076 (function() {
1077 /**
1078 @module ember-metal
1079 */
1080
1081 /*
1082   JavaScript (before ES6) does not have a Map implementation. Objects,
1083   which are often used as dictionaries, may only have Strings as keys.
1084
1085   Because Ember has a way to get a unique identifier for every object
1086   via `Ember.guidFor`, we can implement a performant Map with arbitrary
1087   keys. Because it is commonly used in low-level bookkeeping, Map is
1088   implemented as a pure JavaScript object for performance.
1089
1090   This implementation follows the current iteration of the ES6 proposal
1091   for maps (http://wiki.ecmascript.org/doku.php?id=harmony:simple_maps_and_sets),
1092   with two exceptions. First, because we need our implementation to be
1093   pleasant on older browsers, we do not use the `delete` name (using
1094   `remove` instead). Second, as we do not have the luxury of in-VM
1095   iteration, we implement a forEach method for iteration.
1096
1097   Map is mocked out to look like an Ember object, so you can do
1098   `Ember.Map.create()` for symmetry with other Ember classes.
1099 */
1100 var guidFor = Ember.guidFor,
1101     indexOf = Ember.ArrayPolyfills.indexOf;
1102
1103 var copy = function(obj) {
1104   var output = {};
1105
1106   for (var prop in obj) {
1107     if (obj.hasOwnProperty(prop)) { output[prop] = obj[prop]; }
1108   }
1109
1110   return output;
1111 };
1112
1113 var copyMap = function(original, newObject) {
1114   var keys = original.keys.copy(),
1115       values = copy(original.values);
1116
1117   newObject.keys = keys;
1118   newObject.values = values;
1119
1120   return newObject;
1121 };
1122
1123 /**
1124   This class is used internally by Ember.js and Ember Data.
1125   Please do not use it at this time. We plan to clean it up
1126   and add many tests soon.
1127
1128   @class OrderedSet
1129   @namespace Ember
1130   @constructor
1131   @private
1132 */
1133 var OrderedSet = Ember.OrderedSet = function() {
1134   this.clear();
1135 };
1136
1137 /**
1138   @method create
1139   @static
1140   @return {Ember.OrderedSet}
1141 */
1142 OrderedSet.create = function() {
1143   return new OrderedSet();
1144 };
1145
1146
1147 OrderedSet.prototype = {
1148   /**
1149     @method clear
1150   */
1151   clear: function() {
1152     this.presenceSet = {};
1153     this.list = [];
1154   },
1155
1156   /**
1157     @method add
1158     @param obj
1159   */
1160   add: function(obj) {
1161     var guid = guidFor(obj),
1162         presenceSet = this.presenceSet,
1163         list = this.list;
1164
1165     if (guid in presenceSet) { return; }
1166
1167     presenceSet[guid] = true;
1168     list.push(obj);
1169   },
1170
1171   /**
1172     @method remove
1173     @param obj
1174   */
1175   remove: function(obj) {
1176     var guid = guidFor(obj),
1177         presenceSet = this.presenceSet,
1178         list = this.list;
1179
1180     delete presenceSet[guid];
1181
1182     var index = indexOf.call(list, obj);
1183     if (index > -1) {
1184       list.splice(index, 1);
1185     }
1186   },
1187
1188   /**
1189     @method isEmpty
1190     @return {Boolean}
1191   */
1192   isEmpty: function() {
1193     return this.list.length === 0;
1194   },
1195
1196   /**
1197     @method has
1198     @param obj
1199     @return {Boolean}
1200   */
1201   has: function(obj) {
1202     var guid = guidFor(obj),
1203         presenceSet = this.presenceSet;
1204
1205     return guid in presenceSet;
1206   },
1207
1208   /**
1209     @method forEach
1210     @param {Function} function
1211     @param target
1212   */
1213   forEach: function(fn, self) {
1214     // allow mutation during iteration
1215     var list = this.list.slice();
1216
1217     for (var i = 0, j = list.length; i < j; i++) {
1218       fn.call(self, list[i]);
1219     }
1220   },
1221
1222   /**
1223     @method toArray
1224     @return {Array}
1225   */
1226   toArray: function() {
1227     return this.list.slice();
1228   },
1229
1230   /**
1231     @method copy
1232     @return {Ember.OrderedSet}
1233   */
1234   copy: function() {
1235     var set = new OrderedSet();
1236
1237     set.presenceSet = copy(this.presenceSet);
1238     set.list = this.list.slice();
1239
1240     return set;
1241   }
1242 };
1243
1244 /**
1245   A Map stores values indexed by keys. Unlike JavaScript's
1246   default Objects, the keys of a Map can be any JavaScript
1247   object.
1248
1249   Internally, a Map has two data structures:
1250
1251     `keys`: an OrderedSet of all of the existing keys
1252     `values`: a JavaScript Object indexed by the
1253       Ember.guidFor(key)
1254
1255   When a key/value pair is added for the first time, we
1256   add the key to the `keys` OrderedSet, and create or
1257   replace an entry in `values`. When an entry is deleted,
1258   we delete its entry in `keys` and `values`.
1259
1260   @class Map
1261   @namespace Ember
1262   @private
1263   @constructor
1264 */
1265 var Map = Ember.Map = function() {
1266   this.keys = Ember.OrderedSet.create();
1267   this.values = {};
1268 };
1269
1270 /**
1271   @method create
1272   @static
1273 */
1274 Map.create = function() {
1275   return new Map();
1276 };
1277
1278 Map.prototype = {
1279   /**
1280     Retrieve the value associated with a given key.
1281
1282     @method get
1283     @param {anything} key
1284     @return {anything} the value associated with the key, or undefined
1285   */
1286   get: function(key) {
1287     var values = this.values,
1288         guid = guidFor(key);
1289
1290     return values[guid];
1291   },
1292
1293   /**
1294     Adds a value to the map. If a value for the given key has already been
1295     provided, the new value will replace the old value.
1296
1297     @method set
1298     @param {anything} key
1299     @param {anything} value
1300   */
1301   set: function(key, value) {
1302     var keys = this.keys,
1303         values = this.values,
1304         guid = guidFor(key);
1305
1306     keys.add(key);
1307     values[guid] = value;
1308   },
1309
1310   /**
1311     Removes a value from the map for an associated key.
1312
1313     @method remove
1314     @param {anything} key
1315     @return {Boolean} true if an item was removed, false otherwise
1316   */
1317   remove: function(key) {
1318     // don't use ES6 "delete" because it will be annoying
1319     // to use in browsers that are not ES6 friendly;
1320     var keys = this.keys,
1321         values = this.values,
1322         guid = guidFor(key),
1323         value;
1324
1325     if (values.hasOwnProperty(guid)) {
1326       keys.remove(key);
1327       value = values[guid];
1328       delete values[guid];
1329       return true;
1330     } else {
1331       return false;
1332     }
1333   },
1334
1335   /**
1336     Check whether a key is present.
1337
1338     @method has
1339     @param {anything} key
1340     @return {Boolean} true if the item was present, false otherwise
1341   */
1342   has: function(key) {
1343     var values = this.values,
1344         guid = guidFor(key);
1345
1346     return values.hasOwnProperty(guid);
1347   },
1348
1349   /**
1350     Iterate over all the keys and values. Calls the function once
1351     for each key, passing in the key and value, in that order.
1352
1353     The keys are guaranteed to be iterated over in insertion order.
1354
1355     @method forEach
1356     @param {Function} callback
1357     @param {anything} self if passed, the `this` value inside the
1358       callback. By default, `this` is the map.
1359   */
1360   forEach: function(callback, self) {
1361     var keys = this.keys,
1362         values = this.values;
1363
1364     keys.forEach(function(key) {
1365       var guid = guidFor(key);
1366       callback.call(self, key, values[guid]);
1367     });
1368   },
1369
1370   /**
1371     @method copy
1372     @return {Ember.Map}
1373   */
1374   copy: function() {
1375     return copyMap(this, new Map());
1376   }
1377 };
1378
1379 /**
1380   @class MapWithDefault
1381   @namespace Ember
1382   @extends Ember.Map
1383   @private
1384   @constructor
1385   @param [options]
1386     @param {anything} [options.defaultValue]
1387 */
1388 var MapWithDefault = Ember.MapWithDefault = function(options) {
1389   Map.call(this);
1390   this.defaultValue = options.defaultValue;
1391 };
1392
1393 /**
1394   @method create
1395   @static
1396   @param [options]
1397     @param {anything} [options.defaultValue]
1398   @return {Ember.MapWithDefault|Ember.Map} If options are passed, returns Ember.MapWithDefault otherwise returns Ember.Map
1399 */
1400 MapWithDefault.create = function(options) {
1401   if (options) {
1402     return new MapWithDefault(options);
1403   } else {
1404     return new Map();
1405   }
1406 };
1407
1408 MapWithDefault.prototype = Ember.create(Map.prototype);
1409
1410 /**
1411   Retrieve the value associated with a given key.
1412
1413   @method get
1414   @param {anything} key
1415   @return {anything} the value associated with the key, or the default value
1416 */
1417 MapWithDefault.prototype.get = function(key) {
1418   var hasValue = this.has(key);
1419
1420   if (hasValue) {
1421     return Map.prototype.get.call(this, key);
1422   } else {
1423     var defaultValue = this.defaultValue(key);
1424     this.set(key, defaultValue);
1425     return defaultValue;
1426   }
1427 };
1428
1429 /**
1430   @method copy
1431   @return {Ember.MapWithDefault}
1432 */
1433 MapWithDefault.prototype.copy = function() {
1434   return copyMap(this, new MapWithDefault({
1435     defaultValue: this.defaultValue
1436   }));
1437 };
1438
1439 })();
1440
1441
1442
1443 (function() {
1444 /**
1445 @module ember-metal
1446 */
1447
1448 var META_KEY = Ember.META_KEY, get, set;
1449
1450 var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER;
1451
1452 var IS_GLOBAL = /^([A-Z$]|([0-9][A-Z$]))/;
1453 var IS_GLOBAL_PATH = /^([A-Z$]|([0-9][A-Z$])).*[\.\*]/;
1454 var HAS_THIS  = /^this[\.\*]/;
1455 var FIRST_KEY = /^([^\.\*]+)/;
1456
1457 // ..........................................................
1458 // GET AND SET
1459 //
1460 // If we are on a platform that supports accessors we can get use those.
1461 // Otherwise simulate accessors by looking up the property directly on the
1462 // object.
1463
1464 /**
1465   Gets the value of a property on an object.  If the property is computed,
1466   the function will be invoked.  If the property is not defined but the
1467   object implements the unknownProperty() method then that will be invoked.
1468
1469   If you plan to run on IE8 and older browsers then you should use this
1470   method anytime you want to retrieve a property on an object that you don't
1471   know for sure is private.  (My convention only properties beginning with
1472   an underscore '_' are considered private.)
1473
1474   On all newer browsers, you only need to use this method to retrieve
1475   properties if the property might not be defined on the object and you want
1476   to respect the unknownProperty() handler.  Otherwise you can ignore this
1477   method.
1478
1479   Note that if the obj itself is null, this method will simply return
1480   undefined.
1481
1482   @method get
1483   @for Ember
1484   @param {Object} obj The object to retrieve from.
1485   @param {String} keyName The property key to retrieve
1486   @return {Object} the property value or null.
1487 */
1488 get = function get(obj, keyName) {
1489   // Helpers that operate with 'this' within an #each
1490   if (keyName === '') {
1491     return obj;
1492   }
1493
1494   if (!keyName && 'string'===typeof obj) {
1495     keyName = obj;
1496     obj = null;
1497   }
1498
1499   if (!obj || keyName.indexOf('.') !== -1) {
1500     return getPath(obj, keyName);
1501   }
1502
1503   Ember.assert("You need to provide an object and key to `get`.", !!obj && keyName);
1504
1505   var meta = obj[META_KEY], desc = meta && meta.descs[keyName], ret;
1506   if (desc) {
1507     return desc.get(obj, keyName);
1508   } else {
1509     if (MANDATORY_SETTER && meta && meta.watching[keyName] > 0) {
1510       ret = meta.values[keyName];
1511     } else {
1512       ret = obj[keyName];
1513     }
1514
1515     if (ret === undefined &&
1516         'object' === typeof obj && !(keyName in obj) && 'function' === typeof obj.unknownProperty) {
1517       return obj.unknownProperty(keyName);
1518     }
1519
1520     return ret;
1521   }
1522 };
1523
1524 /**
1525   Sets the value of a property on an object, respecting computed properties
1526   and notifying observers and other listeners of the change.  If the
1527   property is not defined but the object implements the unknownProperty()
1528   method then that will be invoked as well.
1529
1530   If you plan to run on IE8 and older browsers then you should use this
1531   method anytime you want to set a property on an object that you don't
1532   know for sure is private.  (My convention only properties beginning with
1533   an underscore '_' are considered private.)
1534
1535   On all newer browsers, you only need to use this method to set
1536   properties if the property might not be defined on the object and you want
1537   to respect the unknownProperty() handler.  Otherwise you can ignore this
1538   method.
1539
1540   @method set
1541   @for Ember
1542   @param {Object} obj The object to modify.
1543   @param {String} keyName The property key to set
1544   @param {Object} value The value to set
1545   @return {Object} the passed value.
1546 */
1547 set = function set(obj, keyName, value, tolerant) {
1548   if (typeof obj === 'string') {
1549     Ember.assert("Path '" + obj + "' must be global if no obj is given.", IS_GLOBAL.test(obj));
1550     value = keyName;
1551     keyName = obj;
1552     obj = null;
1553   }
1554
1555   if (!obj || keyName.indexOf('.') !== -1) {
1556     return setPath(obj, keyName, value, tolerant);
1557   }
1558
1559   Ember.assert("You need to provide an object and key to `set`.", !!obj && keyName !== undefined);
1560   Ember.assert('calling set on destroyed object', !obj.isDestroyed);
1561
1562   var meta = obj[META_KEY], desc = meta && meta.descs[keyName],
1563       isUnknown, currentValue;
1564   if (desc) {
1565     desc.set(obj, keyName, value);
1566   }
1567   else {
1568     isUnknown = 'object' === typeof obj && !(keyName in obj);
1569
1570     // setUnknownProperty is called if `obj` is an object,
1571     // the property does not already exist, and the
1572     // `setUnknownProperty` method exists on the object
1573     if (isUnknown && 'function' === typeof obj.setUnknownProperty) {
1574       obj.setUnknownProperty(keyName, value);
1575     } else if (meta && meta.watching[keyName] > 0) {
1576       if (MANDATORY_SETTER) {
1577         currentValue = meta.values[keyName];
1578       } else {
1579         currentValue = obj[keyName];
1580       }
1581       // only trigger a change if the value has changed
1582       if (value !== currentValue) {
1583         Ember.propertyWillChange(obj, keyName);
1584         if (MANDATORY_SETTER) {
1585           if (currentValue === undefined && !(keyName in obj)) {
1586             Ember.defineProperty(obj, keyName, null, value); // setup mandatory setter
1587           } else {
1588             meta.values[keyName] = value;
1589           }
1590         } else {
1591           obj[keyName] = value;
1592         }
1593         Ember.propertyDidChange(obj, keyName);
1594       }
1595     } else {
1596       obj[keyName] = value;
1597     }
1598   }
1599   return value;
1600 };
1601
1602 function firstKey(path) {
1603   return path.match(FIRST_KEY)[0];
1604 }
1605
1606 // assumes path is already normalized
1607 function normalizeTuple(target, path) {
1608   var hasThis  = HAS_THIS.test(path),
1609       isGlobal = !hasThis && IS_GLOBAL_PATH.test(path),
1610       key;
1611
1612   if (!target || isGlobal) target = window;
1613   if (hasThis) path = path.slice(5);
1614
1615   if (target === window) {
1616     key = firstKey(path);
1617     target = get(target, key);
1618     path   = path.slice(key.length+1);
1619   }
1620
1621   // must return some kind of path to be valid else other things will break.
1622   if (!path || path.length===0) throw new Error('Invalid Path');
1623
1624   return [ target, path ];
1625 }
1626
1627 function getPath(root, path) {
1628   var hasThis, parts, tuple, idx, len;
1629
1630   // If there is no root and path is a key name, return that
1631   // property from the global object.
1632   // E.g. get('Ember') -> Ember
1633   if (root === null && path.indexOf('.') === -1) { return get(window, path); }
1634
1635   // detect complicated paths and normalize them
1636   hasThis  = HAS_THIS.test(path);
1637
1638   if (!root || hasThis) {
1639     tuple = normalizeTuple(root, path);
1640     root = tuple[0];
1641     path = tuple[1];
1642     tuple.length = 0;
1643   }
1644
1645   parts = path.split(".");
1646   len = parts.length;
1647   for (idx=0; root && idx<len; idx++) {
1648     root = get(root, parts[idx], true);
1649     if (root && root.isDestroyed) { return undefined; }
1650   }
1651   return root;
1652 }
1653
1654 function setPath(root, path, value, tolerant) {
1655   var keyName;
1656
1657   // get the last part of the path
1658   keyName = path.slice(path.lastIndexOf('.') + 1);
1659
1660   // get the first part of the part
1661   path    = path.slice(0, path.length-(keyName.length+1));
1662
1663   // unless the path is this, look up the first part to
1664   // get the root
1665   if (path !== 'this') {
1666     root = getPath(root, path);
1667   }
1668
1669   if (!keyName || keyName.length === 0) {
1670     throw new Error('You passed an empty path');
1671   }
1672
1673   if (!root) {
1674     if (tolerant) { return; }
1675     else { throw new Error('Object in path '+path+' could not be found or was destroyed.'); }
1676   }
1677
1678   return set(root, keyName, value);
1679 }
1680
1681 /**
1682   @private
1683
1684   Normalizes a target/path pair to reflect that actual target/path that should
1685   be observed, etc.  This takes into account passing in global property
1686   paths (i.e. a path beginning with a captial letter not defined on the
1687   target) and * separators.
1688
1689   @method normalizeTuple
1690   @for Ember
1691   @param {Object} target The current target.  May be null.
1692   @param {String} path A path on the target or a global property path.
1693   @return {Array} a temporary array with the normalized target/path pair.
1694 */
1695 Ember.normalizeTuple = function(target, path) {
1696   return normalizeTuple(target, path);
1697 };
1698
1699 Ember.getWithDefault = function(root, key, defaultValue) {
1700   var value = get(root, key);
1701
1702   if (value === undefined) { return defaultValue; }
1703   return value;
1704 };
1705
1706
1707 Ember.get = get;
1708 Ember.getPath = Ember.deprecateFunc('getPath is deprecated since get now supports paths', Ember.get);
1709
1710 Ember.set = set;
1711 Ember.setPath = Ember.deprecateFunc('setPath is deprecated since set now supports paths', Ember.set);
1712
1713 /**
1714   Error-tolerant form of Ember.set. Will not blow up if any part of the
1715   chain is undefined, null, or destroyed.
1716
1717   This is primarily used when syncing bindings, which may try to update after
1718   an object has been destroyed.
1719
1720   @method trySet
1721   @for Ember
1722   @param {Object} obj The object to modify.
1723   @param {String} keyName The property key to set
1724   @param {Object} value The value to set
1725 */
1726 Ember.trySet = function(root, path, value) {
1727   return set(root, path, value, true);
1728 };
1729 Ember.trySetPath = Ember.deprecateFunc('trySetPath has been renamed to trySet', Ember.trySet);
1730
1731 /**
1732   Returns true if the provided path is global (e.g., "MyApp.fooController.bar")
1733   instead of local ("foo.bar.baz").
1734
1735   @method isGlobalPath
1736   @for Ember
1737   @private
1738   @param {String} path
1739   @return Boolean
1740 */
1741 Ember.isGlobalPath = function(path) {
1742   return IS_GLOBAL.test(path);
1743 };
1744
1745
1746
1747 if (Ember.config.overrideAccessors) {
1748   Ember.config.overrideAccessors();
1749   get = Ember.get;
1750   set = Ember.set;
1751 }
1752
1753 })();
1754
1755
1756
1757 (function() {
1758 /**
1759 @module ember-metal
1760 */
1761
1762 var GUID_KEY = Ember.GUID_KEY,
1763     META_KEY = Ember.META_KEY,
1764     EMPTY_META = Ember.EMPTY_META,
1765     metaFor = Ember.meta,
1766     o_create = Ember.create,
1767     objectDefineProperty = Ember.platform.defineProperty;
1768
1769 var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER;
1770
1771 // ..........................................................
1772 // DESCRIPTOR
1773 //
1774
1775 /**
1776   Objects of this type can implement an interface to responds requests to
1777   get and set.  The default implementation handles simple properties.
1778
1779   You generally won't need to create or subclass this directly.
1780
1781   @class Descriptor
1782   @namespace Ember
1783   @private
1784   @constructor
1785 */
1786 var Descriptor = Ember.Descriptor = function() {};
1787
1788 // ..........................................................
1789 // DEFINING PROPERTIES API
1790 //
1791
1792 /**
1793   @private
1794
1795   NOTE: This is a low-level method used by other parts of the API.  You almost
1796   never want to call this method directly.  Instead you should use Ember.mixin()
1797   to define new properties.
1798
1799   Defines a property on an object.  This method works much like the ES5
1800   Object.defineProperty() method except that it can also accept computed
1801   properties and other special descriptors.
1802
1803   Normally this method takes only three parameters.  However if you pass an
1804   instance of Ember.Descriptor as the third param then you can pass an optional
1805   value as the fourth parameter.  This is often more efficient than creating
1806   new descriptor hashes for each property.
1807
1808   ## Examples
1809
1810       // ES5 compatible mode
1811       Ember.defineProperty(contact, 'firstName', {
1812         writable: true,
1813         configurable: false,
1814         enumerable: true,
1815         value: 'Charles'
1816       });
1817
1818       // define a simple property
1819       Ember.defineProperty(contact, 'lastName', undefined, 'Jolley');
1820
1821       // define a computed property
1822       Ember.defineProperty(contact, 'fullName', Ember.computed(function() {
1823         return this.firstName+' '+this.lastName;
1824       }).property('firstName', 'lastName').cacheable());
1825
1826   @method defineProperty
1827   @for Ember
1828   @param {Object} obj the object to define this property on. This may be a prototype.
1829   @param {String} keyName the name of the property
1830   @param {Ember.Descriptor} [desc] an instance of Ember.Descriptor (typically a
1831     computed property) or an ES5 descriptor.
1832     You must provide this or `data` but not both.
1833   @param {anything} [data] something other than a descriptor, that will
1834     become the explicit value of this property.
1835 */
1836 Ember.defineProperty = function(obj, keyName, desc, data, meta) {
1837   var descs, existingDesc, watching, value;
1838
1839   if (!meta) meta = metaFor(obj);
1840   descs = meta.descs;
1841   existingDesc = meta.descs[keyName];
1842   watching = meta.watching[keyName] > 0;
1843
1844   if (existingDesc instanceof Ember.Descriptor) {
1845     existingDesc.teardown(obj, keyName);
1846   }
1847
1848   if (desc instanceof Ember.Descriptor) {
1849     value = desc;
1850
1851     descs[keyName] = desc;
1852     if (MANDATORY_SETTER && watching) {
1853       objectDefineProperty(obj, keyName, {
1854         configurable: true,
1855         enumerable: true,
1856         writable: true,
1857         value: undefined // make enumerable
1858       });
1859     } else {
1860       obj[keyName] = undefined; // make enumerable
1861     }
1862     desc.setup(obj, keyName);
1863   } else {
1864     descs[keyName] = undefined; // shadow descriptor in proto
1865     if (desc == null) {
1866       value = data;
1867
1868       if (MANDATORY_SETTER && watching) {
1869         meta.values[keyName] = data;
1870         objectDefineProperty(obj, keyName, {
1871           configurable: true,
1872           enumerable: true,
1873           set: function() {
1874             Ember.assert('Must use Ember.set() to access this property', false);
1875           },
1876           get: function() {
1877             var meta = this[META_KEY];
1878             return meta && meta.values[keyName];
1879           }
1880         });
1881       } else {
1882         obj[keyName] = data;
1883       }
1884     } else {
1885       value = desc;
1886
1887       // compatibility with ES5
1888       objectDefineProperty(obj, keyName, desc);
1889     }
1890   }
1891
1892   // if key is being watched, override chains that
1893   // were initialized with the prototype
1894   if (watching) { Ember.overrideChains(obj, keyName, meta); }
1895
1896   // The `value` passed to the `didDefineProperty` hook is
1897   // either the descriptor or data, whichever was passed.
1898   if (obj.didDefineProperty) { obj.didDefineProperty(obj, keyName, value); }
1899
1900   return this;
1901 };
1902
1903
1904 })();
1905
1906
1907
1908 (function() {
1909 /**
1910 @module ember-metal
1911 */
1912
1913 var AFTER_OBSERVERS = ':change';
1914 var BEFORE_OBSERVERS = ':before';
1915 var guidFor = Ember.guidFor;
1916
1917 var deferred = 0;
1918 var array_Slice = [].slice;
1919
1920 var ObserverSet = function () {
1921   this.targetSet = {};
1922 };
1923 ObserverSet.prototype.add = function (target, path) {
1924   var targetSet = this.targetSet,
1925     targetGuid = Ember.guidFor(target),
1926     pathSet = targetSet[targetGuid];
1927   if (!pathSet) {
1928     targetSet[targetGuid] = pathSet = {};
1929   }
1930   if (pathSet[path]) {
1931     return false;
1932   } else {
1933     return pathSet[path] = true;
1934   }
1935 };
1936 ObserverSet.prototype.clear = function () {
1937   this.targetSet = {};
1938 };
1939
1940 var DeferredEventQueue = function() {
1941   this.targetSet = {};
1942   this.queue = [];
1943 };
1944
1945 DeferredEventQueue.prototype.push = function(target, eventName, keyName) {
1946   var targetSet = this.targetSet,
1947     queue = this.queue,
1948     targetGuid = Ember.guidFor(target),
1949     eventNameSet = targetSet[targetGuid],
1950     index;
1951
1952   if (!eventNameSet) {
1953     targetSet[targetGuid] = eventNameSet = {};
1954   }
1955   index = eventNameSet[eventName];
1956   if (index === undefined) {
1957     eventNameSet[eventName] = queue.push(Ember.deferEvent(target, eventName, [target, keyName])) - 1;
1958   } else {
1959     queue[index] = Ember.deferEvent(target, eventName, [target, keyName]);
1960   }
1961 };
1962
1963 DeferredEventQueue.prototype.flush = function() {
1964   var queue = this.queue;
1965   this.queue = [];
1966   this.targetSet = {};
1967   for (var i=0, len=queue.length; i < len; ++i) {
1968     queue[i]();
1969   }
1970 };
1971
1972 var queue = new DeferredEventQueue(), beforeObserverSet = new ObserverSet();
1973
1974 function notifyObservers(obj, eventName, keyName, forceNotification) {
1975   if (deferred && !forceNotification) {
1976     queue.push(obj, eventName, keyName);
1977   } else {
1978     Ember.sendEvent(obj, eventName, [obj, keyName]);
1979   }
1980 }
1981
1982 function flushObserverQueue() {
1983   beforeObserverSet.clear();
1984
1985   queue.flush();
1986 }
1987
1988 /**
1989   @method beginPropertyChanges
1990   @chainable
1991 */
1992 Ember.beginPropertyChanges = function() {
1993   deferred++;
1994   return this;
1995 };
1996
1997 /**
1998   @method endPropertyChanges
1999 */
2000 Ember.endPropertyChanges = function() {
2001   deferred--;
2002   if (deferred<=0) flushObserverQueue();
2003 };
2004
2005 /**
2006   Make a series of property changes together in an
2007   exception-safe way.
2008
2009       Ember.changeProperties(function() {
2010         obj1.set('foo', mayBlowUpWhenSet);
2011         obj2.set('bar', baz);
2012       });
2013
2014   @method changeProperties
2015   @param {Function} callback
2016   @param [binding]
2017 */
2018 Ember.changeProperties = function(cb, binding){
2019   Ember.beginPropertyChanges();
2020   try {
2021     cb.call(binding);
2022   } finally {
2023     Ember.endPropertyChanges();
2024   }
2025 };
2026
2027 /**
2028   Set a list of properties on an object. These properties are set inside
2029   a single `beginPropertyChanges` and `endPropertyChanges` batch, so
2030   observers will be buffered.
2031
2032   @method setProperties
2033   @param target
2034   @param {Hash} properties
2035   @return target
2036 */
2037 Ember.setProperties = function(self, hash) {
2038   Ember.changeProperties(function(){
2039     for(var prop in hash) {
2040       if (hash.hasOwnProperty(prop)) Ember.set(self, prop, hash[prop]);
2041     }
2042   });
2043   return self;
2044 };
2045
2046
2047 function changeEvent(keyName) {
2048   return keyName+AFTER_OBSERVERS;
2049 }
2050
2051 function beforeEvent(keyName) {
2052   return keyName+BEFORE_OBSERVERS;
2053 }
2054
2055 /**
2056   @method addObserver
2057   @param obj
2058   @param {String} path
2059   @param {Object|Function} targetOrMethod
2060   @param {Function|String} [method]
2061 */
2062 Ember.addObserver = function(obj, path, target, method) {
2063   Ember.addListener(obj, changeEvent(path), target, method);
2064   Ember.watch(obj, path);
2065   return this;
2066 };
2067
2068 Ember.observersFor = function(obj, path) {
2069   return Ember.listenersFor(obj, changeEvent(path));
2070 };
2071
2072 /**
2073   @method removeObserver
2074   @param obj
2075   @param {String} path
2076   @param {Object|Function} targetOrMethod
2077   @param {Function|String} [method]
2078 */
2079 Ember.removeObserver = function(obj, path, target, method) {
2080   Ember.unwatch(obj, path);
2081   Ember.removeListener(obj, changeEvent(path), target, method);
2082   return this;
2083 };
2084
2085 /**
2086   @method addBeforeObserver
2087   @param obj
2088   @param {String} path
2089   @param {Object|Function} targetOrMethod
2090   @param {Function|String} [method]
2091 */
2092 Ember.addBeforeObserver = function(obj, path, target, method) {
2093   Ember.addListener(obj, beforeEvent(path), target, method);
2094   Ember.watch(obj, path);
2095   return this;
2096 };
2097
2098 // Suspend observer during callback.
2099 //
2100 // This should only be used by the target of the observer
2101 // while it is setting the observed path.
2102 Ember._suspendBeforeObserver = function(obj, path, target, method, callback) {
2103   return Ember._suspendListener(obj, beforeEvent(path), target, method, callback);
2104 };
2105
2106 Ember._suspendObserver = function(obj, path, target, method, callback) {
2107   return Ember._suspendListener(obj, changeEvent(path), target, method, callback);
2108 };
2109
2110 var map = Ember.ArrayPolyfills.map;
2111
2112 Ember._suspendBeforeObservers = function(obj, paths, target, method, callback) {
2113   var events = map.call(paths, beforeEvent);
2114   return Ember._suspendListeners(obj, events, target, method, callback);
2115 };
2116
2117 Ember._suspendObservers = function(obj, paths, target, method, callback) {
2118   var events = map.call(paths, changeEvent);
2119   return Ember._suspendListeners(obj, events, target, method, callback);
2120 };
2121
2122 Ember.beforeObserversFor = function(obj, path) {
2123   return Ember.listenersFor(obj, beforeEvent(path));
2124 };
2125
2126 /**
2127   @method removeBeforeObserver
2128   @param obj
2129   @param {String} path
2130   @param {Object|Function} targetOrMethod
2131   @param {Function|String} [method]
2132 */
2133 Ember.removeBeforeObserver = function(obj, path, target, method) {
2134   Ember.unwatch(obj, path);
2135   Ember.removeListener(obj, beforeEvent(path), target, method);
2136   return this;
2137 };
2138
2139 Ember.notifyObservers = function(obj, keyName) {
2140   if (obj.isDestroying) { return; }
2141
2142   notifyObservers(obj, changeEvent(keyName), keyName);
2143 };
2144
2145 Ember.notifyBeforeObservers = function(obj, keyName) {
2146   if (obj.isDestroying) { return; }
2147
2148   var guid, set, forceNotification = false;
2149
2150   if (deferred) {
2151     if (beforeObserverSet.add(obj, keyName)) {
2152       forceNotification = true;
2153     } else {
2154       return;
2155     }
2156   }
2157
2158   notifyObservers(obj, beforeEvent(keyName), keyName, forceNotification);
2159 };
2160
2161
2162 })();
2163
2164
2165
2166 (function() {
2167 /**
2168 @module ember-metal
2169 */
2170
2171 var guidFor = Ember.guidFor, // utils.js
2172     metaFor = Ember.meta, // utils.js
2173     get = Ember.get, // accessors.js
2174     set = Ember.set, // accessors.js
2175     normalizeTuple = Ember.normalizeTuple, // accessors.js
2176     GUID_KEY = Ember.GUID_KEY, // utils.js
2177     META_KEY = Ember.META_KEY, // utils.js
2178     // circular reference observer depends on Ember.watch
2179     // we should move change events to this file or its own property_events.js
2180     notifyObservers = Ember.notifyObservers, // observer.js
2181     forEach = Ember.ArrayPolyfills.forEach, // array.js
2182     FIRST_KEY = /^([^\.\*]+)/,
2183     IS_PATH = /[\.\*]/;
2184
2185 var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER,
2186 o_defineProperty = Ember.platform.defineProperty;
2187
2188 function firstKey(path) {
2189   return path.match(FIRST_KEY)[0];
2190 }
2191
2192 // returns true if the passed path is just a keyName
2193 function isKeyName(path) {
2194   return path==='*' || !IS_PATH.test(path);
2195 }
2196
2197 // ..........................................................
2198 // DEPENDENT KEYS
2199 //
2200
2201 var DEP_SKIP = { __emberproto__: true }; // skip some keys and toString
2202
2203 function iterDeps(method, obj, depKey, seen, meta) {
2204
2205   var guid = guidFor(obj);
2206   if (!seen[guid]) seen[guid] = {};
2207   if (seen[guid][depKey]) return;
2208   seen[guid][depKey] = true;
2209
2210   var deps = meta.deps;
2211   deps = deps && deps[depKey];
2212   if (deps) {
2213     for(var key in deps) {
2214       if (DEP_SKIP[key]) continue;
2215       var desc = meta.descs[key];
2216       if (desc && desc._suspended === obj) continue;
2217       method(obj, key);
2218     }
2219   }
2220 }
2221
2222
2223 var WILL_SEEN, DID_SEEN;
2224
2225 // called whenever a property is about to change to clear the cache of any dependent keys (and notify those properties of changes, etc...)
2226 function dependentKeysWillChange(obj, depKey, meta) {
2227   if (obj.isDestroying) { return; }
2228
2229   var seen = WILL_SEEN, top = !seen;
2230   if (top) { seen = WILL_SEEN = {}; }
2231   iterDeps(propertyWillChange, obj, depKey, seen, meta);
2232   if (top) { WILL_SEEN = null; }
2233 }
2234
2235 // called whenever a property has just changed to update dependent keys
2236 function dependentKeysDidChange(obj, depKey, meta) {
2237   if (obj.isDestroying) { return; }
2238
2239   var seen = DID_SEEN, top = !seen;
2240   if (top) { seen = DID_SEEN = {}; }
2241   iterDeps(propertyDidChange, obj, depKey, seen, meta);
2242   if (top) { DID_SEEN = null; }
2243 }
2244
2245 // ..........................................................
2246 // CHAIN
2247 //
2248
2249 function addChainWatcher(obj, keyName, node) {
2250   if (!obj || ('object' !== typeof obj)) return; // nothing to do
2251   var m = metaFor(obj);
2252   var nodes = m.chainWatchers;
2253   if (!nodes || nodes.__emberproto__ !== obj) {
2254     nodes = m.chainWatchers = { __emberproto__: obj };
2255   }
2256
2257   if (!nodes[keyName]) { nodes[keyName] = {}; }
2258   nodes[keyName][guidFor(node)] = node;
2259   Ember.watch(obj, keyName);
2260 }
2261
2262 function removeChainWatcher(obj, keyName, node) {
2263   if (!obj || 'object' !== typeof obj) { return; } // nothing to do
2264   var m = metaFor(obj, false),
2265       nodes = m.chainWatchers;
2266   if (!nodes || nodes.__emberproto__ !== obj) { return; } //nothing to do
2267   if (nodes[keyName]) { delete nodes[keyName][guidFor(node)]; }
2268   Ember.unwatch(obj, keyName);
2269 }
2270
2271 var pendingQueue = [];
2272
2273 // attempts to add the pendingQueue chains again.  If some of them end up
2274 // back in the queue and reschedule is true, schedules a timeout to try
2275 // again.
2276 function flushPendingChains() {
2277   if (pendingQueue.length === 0) { return; } // nothing to do
2278
2279   var queue = pendingQueue;
2280   pendingQueue = [];
2281
2282   forEach.call(queue, function(q) { q[0].add(q[1]); });
2283
2284   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);
2285 }
2286
2287 function isProto(pvalue) {
2288   return metaFor(pvalue, false).proto === pvalue;
2289 }
2290
2291 // A ChainNode watches a single key on an object.  If you provide a starting
2292 // value for the key then the node won't actually watch it.  For a root node
2293 // pass null for parent and key and object for value.
2294 var ChainNode = function(parent, key, value, separator) {
2295   var obj;
2296   this._parent = parent;
2297   this._key    = key;
2298
2299   // _watching is true when calling get(this._parent, this._key) will
2300   // return the value of this node.
2301   //
2302   // It is false for the root of a chain (because we have no parent)
2303   // and for global paths (because the parent node is the object with
2304   // the observer on it)
2305   this._watching = value===undefined;
2306
2307   this._value  = value;
2308   this._separator = separator || '.';
2309   this._paths = {};
2310   if (this._watching) {
2311     this._object = parent.value();
2312     if (this._object) { addChainWatcher(this._object, this._key, this); }
2313   }
2314
2315   // Special-case: the EachProxy relies on immediate evaluation to
2316   // establish its observers.
2317   //
2318   // TODO: Replace this with an efficient callback that the EachProxy
2319   // can implement.
2320   if (this._parent && this._parent._key === '@each') {
2321     this.value();
2322   }
2323 };
2324
2325 var ChainNodePrototype = ChainNode.prototype;
2326
2327 ChainNodePrototype.value = function() {
2328   if (this._value === undefined && this._watching) {
2329     var obj = this._parent.value();
2330     this._value = (obj && !isProto(obj)) ? get(obj, this._key) : undefined;
2331   }
2332   return this._value;
2333 };
2334
2335 ChainNodePrototype.destroy = function() {
2336   if (this._watching) {
2337     var obj = this._object;
2338     if (obj) { removeChainWatcher(obj, this._key, this); }
2339     this._watching = false; // so future calls do nothing
2340   }
2341 };
2342
2343 // copies a top level object only
2344 ChainNodePrototype.copy = function(obj) {
2345   var ret = new ChainNode(null, null, obj, this._separator),
2346       paths = this._paths, path;
2347   for (path in paths) {
2348     if (paths[path] <= 0) { continue; } // this check will also catch non-number vals.
2349     ret.add(path);
2350   }
2351   return ret;
2352 };
2353
2354 // called on the root node of a chain to setup watchers on the specified
2355 // path.
2356 ChainNodePrototype.add = function(path) {
2357   var obj, tuple, key, src, separator, paths;
2358
2359   paths = this._paths;
2360   paths[path] = (paths[path] || 0) + 1;
2361
2362   obj = this.value();
2363   tuple = normalizeTuple(obj, path);
2364
2365   // the path was a local path
2366   if (tuple[0] && tuple[0] === obj) {
2367     path = tuple[1];
2368     key  = firstKey(path);
2369     path = path.slice(key.length+1);
2370
2371   // global path, but object does not exist yet.
2372   // put into a queue and try to connect later.
2373   } else if (!tuple[0]) {
2374     pendingQueue.push([this, path]);
2375     tuple.length = 0;
2376     return;
2377
2378   // global path, and object already exists
2379   } else {
2380     src  = tuple[0];
2381     key  = path.slice(0, 0-(tuple[1].length+1));
2382     separator = path.slice(key.length, key.length+1);
2383     path = tuple[1];
2384   }
2385
2386   tuple.length = 0;
2387   this.chain(key, path, src, separator);
2388 };
2389
2390 // called on the root node of a chain to teardown watcher on the specified
2391 // path
2392 ChainNodePrototype.remove = function(path) {
2393   var obj, tuple, key, src, paths;
2394
2395   paths = this._paths;
2396   if (paths[path] > 0) { paths[path]--; }
2397
2398   obj = this.value();
2399   tuple = normalizeTuple(obj, path);
2400   if (tuple[0] === obj) {
2401     path = tuple[1];
2402     key  = firstKey(path);
2403     path = path.slice(key.length+1);
2404   } else {
2405     src  = tuple[0];
2406     key  = path.slice(0, 0-(tuple[1].length+1));
2407     path = tuple[1];
2408   }
2409
2410   tuple.length = 0;
2411   this.unchain(key, path);
2412 };
2413
2414 ChainNodePrototype.count = 0;
2415
2416 ChainNodePrototype.chain = function(key, path, src, separator) {
2417   var chains = this._chains, node;
2418   if (!chains) { chains = this._chains = {}; }
2419
2420   node = chains[key];
2421   if (!node) { node = chains[key] = new ChainNode(this, key, src, separator); }
2422   node.count++; // count chains...
2423
2424   // chain rest of path if there is one
2425   if (path && path.length>0) {
2426     key = firstKey(path);
2427     path = path.slice(key.length+1);
2428     node.chain(key, path); // NOTE: no src means it will observe changes...
2429   }
2430 };
2431
2432 ChainNodePrototype.unchain = function(key, path) {
2433   var chains = this._chains, node = chains[key];
2434
2435   // unchain rest of path first...
2436   if (path && path.length>1) {
2437     key  = firstKey(path);
2438     path = path.slice(key.length+1);
2439     node.unchain(key, path);
2440   }
2441
2442   // delete node if needed.
2443   node.count--;
2444   if (node.count<=0) {
2445     delete chains[node._key];
2446     node.destroy();
2447   }
2448
2449 };
2450
2451 ChainNodePrototype.willChange = function() {
2452   var chains = this._chains;
2453   if (chains) {
2454     for(var key in chains) {
2455       if (!chains.hasOwnProperty(key)) { continue; }
2456       chains[key].willChange();
2457     }
2458   }
2459
2460   if (this._parent) { this._parent.chainWillChange(this, this._key, 1); }
2461 };
2462
2463 ChainNodePrototype.chainWillChange = function(chain, path, depth) {
2464   if (this._key) { path = this._key + this._separator + path; }
2465
2466   if (this._parent) {
2467     this._parent.chainWillChange(this, path, depth+1);
2468   } else {
2469     if (depth > 1) { Ember.propertyWillChange(this.value(), path); }
2470     path = 'this.' + path;
2471     if (this._paths[path] > 0) { Ember.propertyWillChange(this.value(), path); }
2472   }
2473 };
2474
2475 ChainNodePrototype.chainDidChange = function(chain, path, depth) {
2476   if (this._key) { path = this._key + this._separator + path; }
2477   if (this._parent) {
2478     this._parent.chainDidChange(this, path, depth+1);
2479   } else {
2480     if (depth > 1) { Ember.propertyDidChange(this.value(), path); }
2481     path = 'this.' + path;
2482     if (this._paths[path] > 0) { Ember.propertyDidChange(this.value(), path); }
2483   }
2484 };
2485
2486 ChainNodePrototype.didChange = function(suppressEvent) {
2487   // invalidate my own value first.
2488   if (this._watching) {
2489     var obj = this._parent.value();
2490     if (obj !== this._object) {
2491       removeChainWatcher(this._object, this._key, this);
2492       this._object = obj;
2493       addChainWatcher(obj, this._key, this);
2494     }
2495     this._value  = undefined;
2496
2497     // Special-case: the EachProxy relies on immediate evaluation to
2498     // establish its observers.
2499     if (this._parent && this._parent._key === '@each')
2500       this.value();
2501   }
2502
2503   // then notify chains...
2504   var chains = this._chains;
2505   if (chains) {
2506     for(var key in chains) {
2507       if (!chains.hasOwnProperty(key)) { continue; }
2508       chains[key].didChange(suppressEvent);
2509     }
2510   }
2511
2512   if (suppressEvent) { return; }
2513
2514   // and finally tell parent about my path changing...
2515   if (this._parent) { this._parent.chainDidChange(this, this._key, 1); }
2516 };
2517
2518 // get the chains for the current object.  If the current object has
2519 // chains inherited from the proto they will be cloned and reconfigured for
2520 // the current object.
2521 function chainsFor(obj) {
2522   var m = metaFor(obj), ret = m.chains;
2523   if (!ret) {
2524     ret = m.chains = new ChainNode(null, null, obj);
2525   } else if (ret.value() !== obj) {
2526     ret = m.chains = ret.copy(obj);
2527   }
2528   return ret;
2529 }
2530
2531 function notifyChains(obj, m, keyName, methodName, arg) {
2532   var nodes = m.chainWatchers;
2533
2534   if (!nodes || nodes.__emberproto__ !== obj) { return; } // nothing to do
2535
2536   nodes = nodes[keyName];
2537   if (!nodes) { return; }
2538
2539   for(var key in nodes) {
2540     if (!nodes.hasOwnProperty(key)) { continue; }
2541     nodes[key][methodName](arg);
2542   }
2543 }
2544
2545 Ember.overrideChains = function(obj, keyName, m) {
2546   notifyChains(obj, m, keyName, 'didChange', true);
2547 };
2548
2549 function chainsWillChange(obj, keyName, m) {
2550   notifyChains(obj, m, keyName, 'willChange');
2551 }
2552
2553 function chainsDidChange(obj, keyName, m) {
2554   notifyChains(obj, m, keyName, 'didChange');
2555 }
2556
2557 // ..........................................................
2558 // WATCH
2559 //
2560
2561 /**
2562   @private
2563
2564   Starts watching a property on an object.  Whenever the property changes,
2565   invokes Ember.propertyWillChange and Ember.propertyDidChange.  This is the
2566   primitive used by observers and dependent keys; usually you will never call
2567   this method directly but instead use higher level methods like
2568   Ember.addObserver().
2569
2570   @method watch
2571   @for Ember
2572   @param obj
2573   @param {String} keyName
2574 */
2575 Ember.watch = function(obj, keyName) {
2576   // can't watch length on Array - it is special...
2577   if (keyName === 'length' && Ember.typeOf(obj) === 'array') { return this; }
2578
2579   var m = metaFor(obj), watching = m.watching, desc;
2580
2581   // activate watching first time
2582   if (!watching[keyName]) {
2583     watching[keyName] = 1;
2584     if (isKeyName(keyName)) {
2585       desc = m.descs[keyName];
2586       if (desc && desc.willWatch) { desc.willWatch(obj, keyName); }
2587
2588       if ('function' === typeof obj.willWatchProperty) {
2589         obj.willWatchProperty(keyName);
2590       }
2591
2592       if (MANDATORY_SETTER && keyName in obj) {
2593         m.values[keyName] = obj[keyName];
2594         o_defineProperty(obj, keyName, {
2595           configurable: true,
2596           enumerable: true,
2597           set: function() {
2598             Ember.assert('Must use Ember.set() to access this property', false);
2599           },
2600           get: function() {
2601             var meta = this[META_KEY];
2602             return meta && meta.values[keyName];
2603           }
2604         });
2605       }
2606     } else {
2607       chainsFor(obj).add(keyName);
2608     }
2609
2610   }  else {
2611     watching[keyName] = (watching[keyName] || 0) + 1;
2612   }
2613   return this;
2614 };
2615
2616 Ember.isWatching = function isWatching(obj, key) {
2617   var meta = obj[META_KEY];
2618   return (meta && meta.watching[key]) > 0;
2619 };
2620
2621 Ember.watch.flushPending = flushPendingChains;
2622
2623 Ember.unwatch = function(obj, keyName) {
2624   // can't watch length on Array - it is special...
2625   if (keyName === 'length' && Ember.typeOf(obj) === 'array') { return this; }
2626
2627   var m = metaFor(obj), watching = m.watching, desc;
2628
2629   if (watching[keyName] === 1) {
2630     watching[keyName] = 0;
2631
2632     if (isKeyName(keyName)) {
2633       desc = m.descs[keyName];
2634       if (desc && desc.didUnwatch) { desc.didUnwatch(obj, keyName); }
2635
2636       if ('function' === typeof obj.didUnwatchProperty) {
2637         obj.didUnwatchProperty(keyName);
2638       }
2639
2640       if (MANDATORY_SETTER && keyName in obj) {
2641         o_defineProperty(obj, keyName, {
2642           configurable: true,
2643           enumerable: true,
2644           writable: true,
2645           value: m.values[keyName]
2646         });
2647         delete m.values[keyName];
2648       }
2649     } else {
2650       chainsFor(obj).remove(keyName);
2651     }
2652
2653   } else if (watching[keyName]>1) {
2654     watching[keyName]--;
2655   }
2656
2657   return this;
2658 };
2659
2660 /**
2661   @private
2662
2663   Call on an object when you first beget it from another object.  This will
2664   setup any chained watchers on the object instance as needed.  This method is
2665   safe to call multiple times.
2666
2667   @method rewatch
2668   @for Ember
2669   @param obj
2670 */
2671 Ember.rewatch = function(obj) {
2672   var m = metaFor(obj, false), chains = m.chains;
2673
2674   // make sure the object has its own guid.
2675   if (GUID_KEY in obj && !obj.hasOwnProperty(GUID_KEY)) {
2676     Ember.generateGuid(obj, 'ember');
2677   }
2678
2679   // make sure any chained watchers update.
2680   if (chains && chains.value() !== obj) {
2681     m.chains = chains.copy(obj);
2682   }
2683
2684   return this;
2685 };
2686
2687 Ember.finishChains = function(obj) {
2688   var m = metaFor(obj, false), chains = m.chains;
2689   if (chains) {
2690     if (chains.value() !== obj) {
2691       m.chains = chains = chains.copy(obj);
2692     }
2693     chains.didChange(true);
2694   }
2695 };
2696
2697 // ..........................................................
2698 // PROPERTY CHANGES
2699 //
2700
2701 /**
2702   This function is called just before an object property is about to change.
2703   It will notify any before observers and prepare caches among other things.
2704
2705   Normally you will not need to call this method directly but if for some
2706   reason you can't directly watch a property you can invoke this method
2707   manually along with `Ember.propertyDidChange()` which you should call just
2708   after the property value changes.
2709
2710   @method propertyWillChange
2711   @for Ember
2712   @param {Object} obj The object with the property that will change
2713   @param {String} keyName The property key (or path) that will change.
2714   @return {void}
2715 */
2716 function propertyWillChange(obj, keyName, value) {
2717   var m = metaFor(obj, false),
2718       watching = m.watching[keyName] > 0 || keyName === 'length',
2719       proto = m.proto,
2720       desc = m.descs[keyName];
2721
2722   if (!watching) { return; }
2723   if (proto === obj) { return; }
2724   if (desc && desc.willChange) { desc.willChange(obj, keyName); }
2725   dependentKeysWillChange(obj, keyName, m);
2726   chainsWillChange(obj, keyName, m);
2727   Ember.notifyBeforeObservers(obj, keyName);
2728 }
2729
2730 Ember.propertyWillChange = propertyWillChange;
2731
2732 /**
2733   This function is called just after an object property has changed.
2734   It will notify any observers and clear caches among other things.
2735
2736   Normally you will not need to call this method directly but if for some
2737   reason you can't directly watch a property you can invoke this method
2738   manually along with `Ember.propertyWilLChange()` which you should call just
2739   before the property value changes.
2740
2741   @method propertyDidChange
2742   @for Ember
2743   @param {Object} obj The object with the property that will change
2744   @param {String} keyName The property key (or path) that will change.
2745   @return {void}
2746 */
2747 function propertyDidChange(obj, keyName) {
2748   var m = metaFor(obj, false),
2749       watching = m.watching[keyName] > 0 || keyName === 'length',
2750       proto = m.proto,
2751       desc = m.descs[keyName];
2752
2753   if (proto === obj) { return; }
2754
2755   // shouldn't this mean that we're watching this key?
2756   if (desc && desc.didChange) { desc.didChange(obj, keyName); }
2757   if (!watching && keyName !== 'length') { return; }
2758
2759   dependentKeysDidChange(obj, keyName, m);
2760   chainsDidChange(obj, keyName, m);
2761   Ember.notifyObservers(obj, keyName);
2762 }
2763
2764 Ember.propertyDidChange = propertyDidChange;
2765
2766 var NODE_STACK = [];
2767
2768 /**
2769   Tears down the meta on an object so that it can be garbage collected.
2770   Multiple calls will have no effect.
2771
2772   @method destroy
2773   @for Ember
2774   @param {Object} obj  the object to destroy
2775   @return {void}
2776 */
2777 Ember.destroy = function (obj) {
2778   var meta = obj[META_KEY], node, nodes, key, nodeObject;
2779   if (meta) {
2780     obj[META_KEY] = null;
2781     // remove chainWatchers to remove circular references that would prevent GC
2782     node = meta.chains;
2783     if (node) {
2784       NODE_STACK.push(node);
2785       // process tree
2786       while (NODE_STACK.length > 0) {
2787         node = NODE_STACK.pop();
2788         // push children
2789         nodes = node._chains;
2790         if (nodes) {
2791           for (key in nodes) {
2792             if (nodes.hasOwnProperty(key)) {
2793               NODE_STACK.push(nodes[key]);
2794             }
2795           }
2796         }
2797         // remove chainWatcher in node object
2798         if (node._watching) {
2799           nodeObject = node._object;
2800           if (nodeObject) {
2801             removeChainWatcher(nodeObject, node._key, node);
2802           }
2803         }
2804       }
2805     }
2806   }
2807 };
2808
2809 })();
2810
2811
2812
2813 (function() {
2814 /**
2815 @module ember-metal
2816 */
2817
2818 Ember.warn("Computed properties will soon be cacheable by default. To enable this in your app, set `ENV.CP_DEFAULT_CACHEABLE = true`.", Ember.CP_DEFAULT_CACHEABLE);
2819
2820
2821 var get = Ember.get,
2822     metaFor = Ember.meta,
2823     guidFor = Ember.guidFor,
2824     a_slice = [].slice,
2825     o_create = Ember.create,
2826     META_KEY = Ember.META_KEY,
2827     watch = Ember.watch,
2828     unwatch = Ember.unwatch;
2829
2830 // ..........................................................
2831 // DEPENDENT KEYS
2832 //
2833
2834 // data structure:
2835 //  meta.deps = {
2836 //   'depKey': {
2837 //     'keyName': count,
2838 //     __emberproto__: SRC_OBJ [to detect clones]
2839 //     },
2840 //   __emberproto__: SRC_OBJ
2841 //  }
2842
2843 /*
2844   This function returns a map of unique dependencies for a
2845   given object and key.
2846 */
2847 function keysForDep(obj, depsMeta, depKey) {
2848   var keys = depsMeta[depKey];
2849   if (!keys) {
2850     // if there are no dependencies yet for a the given key
2851     // create a new empty list of dependencies for the key
2852     keys = depsMeta[depKey] = { __emberproto__: obj };
2853   } else if (keys.__emberproto__ !== obj) {
2854     // otherwise if the dependency list is inherited from
2855     // a superclass, clone the hash
2856     keys = depsMeta[depKey] = o_create(keys);
2857     keys.__emberproto__ = obj;
2858   }
2859   return keys;
2860 }
2861
2862 /* return obj[META_KEY].deps */
2863 function metaForDeps(obj, meta) {
2864   var deps = meta.deps;
2865   // If the current object has no dependencies...
2866   if (!deps) {
2867     // initialize the dependencies with a pointer back to
2868     // the current object
2869     deps = meta.deps = { __emberproto__: obj };
2870   } else if (deps.__emberproto__ !== obj) {
2871     // otherwise if the dependencies are inherited from the
2872     // object's superclass, clone the deps
2873     deps = meta.deps = o_create(deps);
2874     deps.__emberproto__ = obj;
2875   }
2876   return deps;
2877 }
2878
2879 function addDependentKeys(desc, obj, keyName, meta) {
2880   // the descriptor has a list of dependent keys, so
2881   // add all of its dependent keys.
2882   var depKeys = desc._dependentKeys, depsMeta, idx, len, depKey, keys;
2883   if (!depKeys) return;
2884
2885   depsMeta = metaForDeps(obj, meta);
2886
2887   for(idx = 0, len = depKeys.length; idx < len; idx++) {
2888     depKey = depKeys[idx];
2889     // Lookup keys meta for depKey
2890     keys = keysForDep(obj, depsMeta, depKey);
2891     // Increment the number of times depKey depends on keyName.
2892     keys[keyName] = (keys[keyName] || 0) + 1;
2893     // Watch the depKey
2894     watch(obj, depKey);
2895   }
2896 }
2897
2898 function removeDependentKeys(desc, obj, keyName, meta) {
2899   // the descriptor has a list of dependent keys, so
2900   // add all of its dependent keys.
2901   var depKeys = desc._dependentKeys, depsMeta, idx, len, depKey, keys;
2902   if (!depKeys) return;
2903
2904   depsMeta = metaForDeps(obj, meta);
2905
2906   for(idx = 0, len = depKeys.length; idx < len; idx++) {
2907     depKey = depKeys[idx];
2908     // Lookup keys meta for depKey
2909     keys = keysForDep(obj, depsMeta, depKey);
2910     // Increment the number of times depKey depends on keyName.
2911     keys[keyName] = (keys[keyName] || 0) - 1;
2912     // Watch the depKey
2913     unwatch(obj, depKey);
2914   }
2915 }
2916
2917 // ..........................................................
2918 // COMPUTED PROPERTY
2919 //
2920
2921 /**
2922   @class ComputedProperty
2923   @namespace Ember
2924   @extends Ember.Descriptor
2925   @constructor
2926 */
2927 function ComputedProperty(func, opts) {
2928   this.func = func;
2929   this._cacheable = (opts && opts.cacheable !== undefined) ? opts.cacheable : Ember.CP_DEFAULT_CACHEABLE;
2930   this._dependentKeys = opts && opts.dependentKeys;
2931 }
2932
2933 Ember.ComputedProperty = ComputedProperty;
2934 ComputedProperty.prototype = new Ember.Descriptor();
2935
2936 var ComputedPropertyPrototype = ComputedProperty.prototype;
2937
2938 /**
2939   Call on a computed property to set it into cacheable mode.  When in this
2940   mode the computed property will automatically cache the return value of
2941   your function until one of the dependent keys changes.
2942
2943       MyApp.president = Ember.Object.create({
2944         fullName: function() {
2945           return this.get('firstName') + ' ' + this.get('lastName');
2946
2947           // After calculating the value of this function, Ember.js will
2948           // return that value without re-executing this function until
2949           // one of the dependent properties change.
2950         }.property('firstName', 'lastName').cacheable()
2951       });
2952
2953   Properties are cacheable by default.
2954
2955   @method cacheable
2956   @param {Boolean} aFlag optional set to false to disable caching
2957   @chainable
2958 */
2959 ComputedPropertyPrototype.cacheable = function(aFlag) {
2960   this._cacheable = aFlag !== false;
2961   return this;
2962 };
2963
2964 /**
2965   Call on a computed property to set it into non-cached mode.  When in this
2966   mode the computed property will not automatically cache the return value.
2967
2968       MyApp.outsideService = Ember.Object.create({
2969         value: function() {
2970           return OutsideService.getValue();
2971         }.property().volatile()
2972       });
2973
2974   @method volatile
2975   @chainable
2976 */
2977 ComputedPropertyPrototype.volatile = function() {
2978   return this.cacheable(false);
2979 };
2980
2981 /**
2982   Sets the dependent keys on this computed property.  Pass any number of
2983   arguments containing key paths that this computed property depends on.
2984
2985       MyApp.president = Ember.Object.create({
2986         fullName: Ember.computed(function() {
2987           return this.get('firstName') + ' ' + this.get('lastName');
2988
2989           // Tell Ember.js that this computed property depends on firstName
2990           // and lastName
2991         }).property('firstName', 'lastName')
2992       });
2993
2994   @method property
2995   @param {String} path* zero or more property paths
2996   @chainable
2997 */
2998 ComputedPropertyPrototype.property = function() {
2999   var args = [];
3000   for (var i = 0, l = arguments.length; i < l; i++) {
3001     args.push(arguments[i]);
3002   }
3003   this._dependentKeys = args;
3004   return this;
3005 };
3006
3007 /**
3008   In some cases, you may want to annotate computed properties with additional
3009   metadata about how they function or what values they operate on. For example,
3010   computed property functions may close over variables that are then no longer
3011   available for introspection.
3012
3013   You can pass a hash of these values to a computed property like this:
3014
3015       person: function() {
3016         var personId = this.get('personId');
3017         return App.Person.create({ id: personId });
3018       }.property().meta({ type: App.Person })
3019
3020   The hash that you pass to the `meta()` function will be saved on the
3021   computed property descriptor under the `_meta` key. Ember runtime
3022   exposes a public API for retrieving these values from classes,
3023   via the `metaForProperty()` function.
3024
3025   @method meta
3026   @param {Hash} meta
3027   @chainable
3028 */
3029
3030 ComputedPropertyPrototype.meta = function(meta) {
3031   if (arguments.length === 0) {
3032     return this._meta || {};
3033   } else {
3034     this._meta = meta;
3035     return this;
3036   }
3037 };
3038
3039 /* impl descriptor API */
3040 ComputedPropertyPrototype.willWatch = function(obj, keyName) {
3041   // watch already creates meta for this instance
3042   var meta = obj[META_KEY];
3043   Ember.assert('watch should have setup meta to be writable', meta.source === obj);
3044   if (!(keyName in meta.cache)) {
3045     addDependentKeys(this, obj, keyName, meta);
3046   }
3047 };
3048
3049 ComputedPropertyPrototype.didUnwatch = function(obj, keyName) {
3050   var meta = obj[META_KEY];
3051   Ember.assert('unwatch should have setup meta to be writable', meta.source === obj);
3052   if (!(keyName in meta.cache)) {
3053     // unwatch already creates meta for this instance
3054     removeDependentKeys(this, obj, keyName, meta);
3055   }
3056 };
3057
3058 /* impl descriptor API */
3059 ComputedPropertyPrototype.didChange = function(obj, keyName) {
3060   // _suspended is set via a CP.set to ensure we don't clear
3061   // the cached value set by the setter
3062   if (this._cacheable && this._suspended !== obj) {
3063     var meta = metaFor(obj);
3064     if (keyName in meta.cache) {
3065       delete meta.cache[keyName];
3066       if (!meta.watching[keyName]) {
3067         removeDependentKeys(this, obj, keyName, meta);
3068       }
3069     }
3070   }
3071 };
3072
3073 /* impl descriptor API */
3074 ComputedPropertyPrototype.get = function(obj, keyName) {
3075   var ret, cache, meta;
3076   if (this._cacheable) {
3077     meta = metaFor(obj);
3078     cache = meta.cache;
3079     if (keyName in cache) { return cache[keyName]; }
3080     ret = cache[keyName] = this.func.call(obj, keyName);
3081     if (!meta.watching[keyName]) {
3082       addDependentKeys(this, obj, keyName, meta);
3083     }
3084   } else {
3085     ret = this.func.call(obj, keyName);
3086   }
3087   return ret;
3088 };
3089
3090 /* impl descriptor API */
3091 ComputedPropertyPrototype.set = function(obj, keyName, value) {
3092   var cacheable = this._cacheable,
3093       meta = metaFor(obj, cacheable),
3094       watched = meta.watching[keyName],
3095       oldSuspended = this._suspended,
3096       hadCachedValue = false,
3097       ret;
3098   this._suspended = obj;
3099   try {
3100     ret = this.func.call(obj, keyName, value);
3101
3102     if (cacheable && keyName in meta.cache) {
3103       if (meta.cache[keyName] === ret) {
3104         return;
3105       }
3106       hadCachedValue = true;
3107     }
3108
3109     if (watched) { Ember.propertyWillChange(obj, keyName); }
3110
3111     if (cacheable && hadCachedValue) {
3112       delete meta.cache[keyName];
3113     }
3114
3115     if (cacheable) {
3116       if (!watched && !hadCachedValue) {
3117         addDependentKeys(this, obj, keyName, meta);
3118       }
3119       meta.cache[keyName] = ret;
3120     }
3121
3122     if (watched) { Ember.propertyDidChange(obj, keyName); }
3123   } finally {
3124     this._suspended = oldSuspended;
3125   }
3126   return ret;
3127 };
3128
3129 /* called when property is defined */
3130 ComputedPropertyPrototype.setup = function(obj, keyName) {
3131   var meta = obj[META_KEY];
3132   if (meta && meta.watching[keyName]) {
3133     addDependentKeys(this, obj, keyName, metaFor(obj));
3134   }
3135 };
3136
3137 /* called before property is overridden */
3138 ComputedPropertyPrototype.teardown = function(obj, keyName) {
3139   var meta = metaFor(obj);
3140
3141   if (meta.watching[keyName] || keyName in meta.cache) {
3142     removeDependentKeys(this, obj, keyName, meta);
3143   }
3144
3145   if (this._cacheable) { delete meta.cache[keyName]; }
3146
3147   return null; // no value to restore
3148 };
3149
3150
3151 /**
3152   This helper returns a new property descriptor that wraps the passed
3153   computed property function.  You can use this helper to define properties
3154   with mixins or via Ember.defineProperty().
3155
3156   The function you pass will be used to both get and set property values.
3157   The function should accept two parameters, key and value.  If value is not
3158   undefined you should set the value first.  In either case return the
3159   current value of the property.
3160
3161   @method computed
3162   @for Ember
3163   @param {Function} func The computed property function.
3164   @return {Ember.ComputedProperty} property descriptor instance
3165 */
3166 Ember.computed = function(func) {
3167   var args;
3168
3169   if (arguments.length > 1) {
3170     args = a_slice.call(arguments, 0, -1);
3171     func = a_slice.call(arguments, -1)[0];
3172   }
3173
3174   var cp = new ComputedProperty(func);
3175
3176   if (args) {
3177     cp.property.apply(cp, args);
3178   }
3179
3180   return cp;
3181 };
3182
3183 /**
3184   Returns the cached value for a property, if one exists.
3185   This can be useful for peeking at the value of a computed
3186   property that is generated lazily, without accidentally causing
3187   it to be created.
3188
3189   @method cacheFor
3190   @for Ember
3191   @param {Object} obj the object whose property you want to check
3192   @param {String} key the name of the property whose cached value you want
3193                       to return
3194 */
3195 Ember.cacheFor = function cacheFor(obj, key) {
3196   var cache = metaFor(obj, false).cache;
3197
3198   if (cache && key in cache) {
3199     return cache[key];
3200   }
3201 };
3202
3203 /**
3204   @method computed.not
3205   @for Ember
3206   @param {String} dependentKey
3207 */
3208 Ember.computed.not = function(dependentKey) {
3209   return Ember.computed(dependentKey, function(key) {
3210     return !get(this, dependentKey);
3211   }).cacheable();
3212 };
3213
3214 /**
3215   @method computed.empty
3216   @for Ember
3217   @param {String} dependentKey
3218 */
3219 Ember.computed.empty = function(dependentKey) {
3220   return Ember.computed(dependentKey, function(key) {
3221     var val = get(this, dependentKey);
3222     return val === undefined || val === null || val === '' || (Ember.isArray(val) && get(val, 'length') === 0);
3223   }).cacheable();
3224 };
3225
3226 /**
3227   @method computed.bool
3228   @for Ember
3229   @param {String} dependentKey
3230 */
3231 Ember.computed.bool = function(dependentKey) {
3232   return Ember.computed(dependentKey, function(key) {
3233     return !!get(this, dependentKey);
3234   }).cacheable();
3235 };
3236
3237 })();
3238
3239
3240
3241 (function() {
3242 /**
3243 @module ember-metal
3244 */
3245
3246 var o_create = Ember.create,
3247     meta = Ember.meta,
3248     metaPath = Ember.metaPath,
3249     guidFor = Ember.guidFor,
3250     a_slice = [].slice;
3251
3252 /*
3253   The event system uses a series of nested hashes to store listeners on an
3254   object. When a listener is registered, or when an event arrives, these
3255   hashes are consulted to determine which target and action pair to invoke.
3256
3257   The hashes are stored in the object's meta hash, and look like this:
3258
3259       // Object's meta hash
3260       {
3261         listeners: {               // variable name: `listenerSet`
3262           "foo:changed": {         // variable name: `targetSet`
3263             [targetGuid]: {        // variable name: `actionSet`
3264               [methodGuid]: {      // variable name: `action`
3265                 target: [Object object],
3266                 method: [Function function]
3267               }
3268             }
3269           }
3270         }
3271       }
3272
3273 */
3274
3275 // Gets the set of all actions, keyed on the guid of each action's
3276 // method property.
3277 function actionSetFor(obj, eventName, target, writable) {
3278   return metaPath(obj, ['listeners', eventName, guidFor(target)], writable);
3279 }
3280
3281 // Gets the set of all targets, keyed on the guid of each action's
3282 // target property.
3283 function targetSetFor(obj, eventName) {
3284   var listenerSet = meta(obj, false).listeners;
3285   if (!listenerSet) { return false; }
3286
3287   return listenerSet[eventName] || false;
3288 }
3289
3290 // TODO: This knowledge should really be a part of the
3291 // meta system.
3292 var SKIP_PROPERTIES = { __ember_source__: true };
3293
3294 function iterateSet(obj, eventName, callback, params) {
3295   var targetSet = targetSetFor(obj, eventName);
3296   if (!targetSet) { return false; }
3297   // Iterate through all elements of the target set
3298   for(var targetGuid in targetSet) {
3299     if (SKIP_PROPERTIES[targetGuid]) { continue; }
3300
3301     var actionSet = targetSet[targetGuid];
3302     if (actionSet) {
3303       // Iterate through the elements of the action set
3304       for(var methodGuid in actionSet) {
3305         if (SKIP_PROPERTIES[methodGuid]) { continue; }
3306
3307         var action = actionSet[methodGuid];
3308         if (action) {
3309           if (callback(action, params, obj) === true) {
3310             return true;
3311           }
3312         }
3313       }
3314     }
3315   }
3316   return false;
3317 }
3318
3319 function invokeAction(action, params, sender) {
3320   var method = action.method, target = action.target;
3321   // If there is no target, the target is the object
3322   // on which the event was fired.
3323   if (!target) { target = sender; }
3324   if ('string' === typeof method) { method = target[method]; }
3325   if (params) {
3326     method.apply(target, params);
3327   } else {
3328     method.apply(target);
3329   }
3330 }
3331
3332 /**
3333   Add an event listener
3334
3335   @method addListener
3336   @for Ember
3337   @param obj
3338   @param {String} eventName
3339   @param {Object|Function} targetOrMethod A target object or a function
3340   @param {Function|String} method A function or the name of a function to be called on `target`
3341 */
3342 function addListener(obj, eventName, target, method) {
3343   Ember.assert("You must pass at least an object and event name to Ember.addListener", !!obj && !!eventName);
3344
3345   if (!method && 'function' === typeof target) {
3346     method = target;
3347     target = null;
3348   }
3349
3350   var actionSet = actionSetFor(obj, eventName, target, true),
3351       methodGuid = guidFor(method);
3352
3353   if (!actionSet[methodGuid]) {
3354     actionSet[methodGuid] = { target: target, method: method };
3355   }
3356
3357   if ('function' === typeof obj.didAddListener) {
3358     obj.didAddListener(eventName, target, method);
3359   }
3360 }
3361
3362 /**
3363   Remove an event listener
3364
3365   Arguments should match those passed to {{#crossLink "Ember/addListener"}}{{/crossLink}}
3366
3367   @method removeListener
3368   @for Ember
3369   @param obj
3370   @param {String} eventName
3371   @param {Object|Function} targetOrMethod A target object or a function
3372   @param {Function|String} method A function or the name of a function to be called on `target`
3373 */
3374 function removeListener(obj, eventName, target, method) {
3375   Ember.assert("You must pass at least an object and event name to Ember.removeListener", !!obj && !!eventName);
3376
3377   if (!method && 'function' === typeof target) {
3378     method = target;
3379     target = null;
3380   }
3381
3382   var actionSet = actionSetFor(obj, eventName, target, true),
3383       methodGuid = guidFor(method);
3384
3385   // we can't simply delete this parameter, because if we do, we might
3386   // re-expose the property from the prototype chain.
3387   if (actionSet && actionSet[methodGuid]) { actionSet[methodGuid] = null; }
3388
3389   if ('function' === typeof obj.didRemoveListener) {
3390     obj.didRemoveListener(eventName, target, method);
3391   }
3392 }
3393
3394 /**
3395   @private
3396
3397   Suspend listener during callback.
3398
3399   This should only be used by the target of the event listener
3400   when it is taking an action that would cause the event, e.g.
3401   an object might suspend its property change listener while it is
3402   setting that property.
3403
3404   @method suspendListener
3405   @for Ember
3406   @param obj
3407   @param {String} eventName
3408   @param {Object|Function} targetOrMethod A target object or a function
3409   @param {Function|String} method A function or the name of a function to be called on `target`
3410   @param {Function} callback
3411 */
3412 function suspendListener(obj, eventName, target, method, callback) {
3413   if (!method && 'function' === typeof target) {
3414     method = target;
3415     target = null;
3416   }
3417
3418   var actionSet = actionSetFor(obj, eventName, target, true),
3419       methodGuid = guidFor(method),
3420       action = actionSet && actionSet[methodGuid];
3421
3422   actionSet[methodGuid] = null;
3423   try {
3424     return callback.call(target);
3425   } finally {
3426     actionSet[methodGuid] = action;
3427   }
3428 }
3429
3430 /**
3431   @private
3432
3433   Suspend listener during callback.
3434
3435   This should only be used by the target of the event listener
3436   when it is taking an action that would cause the event, e.g.
3437   an object might suspend its property change listener while it is
3438   setting that property.
3439
3440   @method suspendListener
3441   @for Ember
3442   @param obj
3443   @param {Array} eventName Array of event names
3444   @param {Object|Function} targetOrMethod A target object or a function
3445   @param {Function|String} method A function or the name of a function to be called on `target`
3446   @param {Function} callback
3447 */
3448 function suspendListeners(obj, eventNames, target, method, callback) {
3449   if (!method && 'function' === typeof target) {
3450     method = target;
3451     target = null;
3452   }
3453
3454   var oldActions = [],
3455       actionSets = [],
3456       eventName, actionSet, methodGuid, action, i, l;
3457
3458   for (i=0, l=eventNames.length; i<l; i++) {
3459     eventName = eventNames[i];
3460     actionSet = actionSetFor(obj, eventName, target, true),
3461     methodGuid = guidFor(method);
3462
3463     oldActions.push(actionSet && actionSet[methodGuid]);
3464     actionSets.push(actionSet);
3465
3466     actionSet[methodGuid] = null;
3467   }
3468
3469   try {
3470     return callback.call(target);
3471   } finally {
3472     for (i=0, l=oldActions.length; i<l; i++) {
3473       eventName = eventNames[i];
3474       actionSets[i][methodGuid] = oldActions[i];
3475     }
3476   }
3477 }
3478
3479 /**
3480   @private
3481
3482   Return a list of currently watched events
3483
3484   @method watchedEvents
3485   @for Ember
3486   @param obj
3487 */
3488 function watchedEvents(obj) {
3489   var listeners = meta(obj, false).listeners, ret = [];
3490
3491   if (listeners) {
3492     for(var eventName in listeners) {
3493       if (!SKIP_PROPERTIES[eventName] && listeners[eventName]) {
3494         ret.push(eventName);
3495       }
3496     }
3497   }
3498   return ret;
3499 }
3500
3501 /**
3502   @method sendEvent
3503   @for Ember
3504   @param obj
3505   @param {String} eventName
3506   @param {Array} params
3507   @return true
3508 */
3509 function sendEvent(obj, eventName, params) {
3510   // first give object a chance to handle it
3511   if (obj !== Ember && 'function' === typeof obj.sendEvent) {
3512     obj.sendEvent(eventName, params);
3513   }
3514
3515   iterateSet(obj, eventName, invokeAction, params);
3516   return true;
3517 }
3518
3519 /**
3520   @private
3521   @method deferEvent
3522   @for Ember
3523   @param obj
3524   @param {String} eventName
3525   @param {Array} params
3526 */
3527 function deferEvent(obj, eventName, params) {
3528   var actions = [];
3529   iterateSet(obj, eventName, function (action) {
3530     actions.push(action);
3531   });
3532
3533   return function() {
3534     if (obj.isDestroyed) { return; }
3535
3536     if (obj !== Ember && 'function' === typeof obj.sendEvent) {
3537       obj.sendEvent(eventName, params);
3538     }
3539
3540     for (var i=0, len=actions.length; i < len; ++i) {
3541       invokeAction(actions[i], params, obj);
3542     }
3543   };
3544 }
3545
3546 /**
3547   @private
3548   @method hasListeners
3549   @for Ember
3550   @param obj
3551   @param {String} eventName
3552 */
3553 function hasListeners(obj, eventName) {
3554   if (iterateSet(obj, eventName, function() { return true; })) {
3555     return true;
3556   }
3557
3558   // no listeners!  might as well clean this up so it is faster later.
3559   var set = metaPath(obj, ['listeners'], true);
3560   set[eventName] = null;
3561
3562   return false;
3563 }
3564
3565 /**
3566   @private
3567   @method listenersFor
3568   @for Ember
3569   @param obj
3570   @param {String} eventName
3571 */
3572 function listenersFor(obj, eventName) {
3573   var ret = [];
3574   iterateSet(obj, eventName, function (action) {
3575     ret.push([action.target, action.method]);
3576   });
3577   return ret;
3578 }
3579
3580 Ember.addListener = addListener;
3581 Ember.removeListener = removeListener;
3582 Ember._suspendListener = suspendListener;
3583 Ember._suspendListeners = suspendListeners;
3584 Ember.sendEvent = sendEvent;
3585 Ember.hasListeners = hasListeners;
3586 Ember.watchedEvents = watchedEvents;
3587 Ember.listenersFor = listenersFor;
3588 Ember.deferEvent = deferEvent;
3589
3590 })();
3591
3592
3593
3594 (function() {
3595 // Ember.Logger
3596 // Ember.watch.flushPending
3597 // Ember.beginPropertyChanges, Ember.endPropertyChanges
3598 // Ember.guidFor
3599
3600 /**
3601 @module ember-metal
3602 */
3603
3604 // ..........................................................
3605 // HELPERS
3606 //
3607
3608 var slice = [].slice,
3609     forEach = Ember.ArrayPolyfills.forEach;
3610
3611 // invokes passed params - normalizing so you can pass target/func,
3612 // target/string or just func
3613 function invoke(target, method, args, ignore) {
3614
3615   if (method === undefined) {
3616     method = target;
3617     target = undefined;
3618   }
3619
3620   if ('string' === typeof method) { method = target[method]; }
3621   if (args && ignore > 0) {
3622     args = args.length > ignore ? slice.call(args, ignore) : null;
3623   }
3624
3625   return Ember.handleErrors(function() {
3626     // IE8's Function.prototype.apply doesn't accept undefined/null arguments.
3627     return method.apply(target || this, args || []);
3628   }, this);
3629 }
3630
3631
3632 // ..........................................................
3633 // RUNLOOP
3634 //
3635
3636 var timerMark; // used by timers...
3637
3638 /**
3639 Ember RunLoop (Private)
3640
3641 @class RunLoop
3642 @namespace Ember
3643 @private
3644 @constructor
3645 */
3646 var RunLoop = function(prev) {
3647   this._prev = prev || null;
3648   this.onceTimers = {};
3649 };
3650
3651 RunLoop.prototype = {
3652   /**
3653     @method end
3654   */
3655   end: function() {
3656     this.flush();
3657   },
3658
3659   /**
3660     @method prev
3661   */
3662   prev: function() {
3663     return this._prev;
3664   },
3665
3666   // ..........................................................
3667   // Delayed Actions
3668   //
3669
3670   /**
3671     @method schedule
3672     @param {String} queueName
3673     @param target
3674     @param method
3675   */
3676   schedule: function(queueName, target, method) {
3677     var queues = this._queues, queue;
3678     if (!queues) { queues = this._queues = {}; }
3679     queue = queues[queueName];
3680     if (!queue) { queue = queues[queueName] = []; }
3681
3682     var args = arguments.length > 3 ? slice.call(arguments, 3) : null;
3683     queue.push({ target: target, method: method, args: args });
3684     return this;
3685   },
3686
3687   /**
3688     @method flush
3689     @param {String} queueName
3690   */
3691   flush: function(queueName) {
3692     var queueNames, idx, len, queue, log;
3693
3694     if (!this._queues) { return this; } // nothing to do
3695
3696     function iter(item) {
3697       invoke(item.target, item.method, item.args);
3698     }
3699
3700     Ember.watch.flushPending(); // make sure all chained watchers are setup
3701
3702     if (queueName) {
3703       while (this._queues && (queue = this._queues[queueName])) {
3704         this._queues[queueName] = null;
3705
3706         // the sync phase is to allow property changes to propagate.  don't
3707         // invoke observers until that is finished.
3708         if (queueName === 'sync') {
3709           log = Ember.LOG_BINDINGS;
3710           if (log) { Ember.Logger.log('Begin: Flush Sync Queue'); }
3711
3712           Ember.beginPropertyChanges();
3713           try {
3714             forEach.call(queue, iter);
3715           } finally {
3716             Ember.endPropertyChanges();
3717           }
3718
3719           if (log) { Ember.Logger.log('End: Flush Sync Queue'); }
3720
3721         } else {
3722           forEach.call(queue, iter);
3723         }
3724       }
3725
3726     } else {
3727       queueNames = Ember.run.queues;
3728       len = queueNames.length;
3729       idx = 0;
3730
3731       outerloop:
3732       while (idx < len) {
3733         queueName = queueNames[idx];
3734         queue = this._queues && this._queues[queueName];
3735         delete this._queues[queueName];
3736
3737         if (queue) {
3738           // the sync phase is to allow property changes to propagate.  don't
3739           // invoke observers until that is finished.
3740           if (queueName === 'sync') {
3741             log = Ember.LOG_BINDINGS;
3742             if (log) { Ember.Logger.log('Begin: Flush Sync Queue'); }
3743
3744             Ember.beginPropertyChanges();
3745             try {
3746               forEach.call(queue, iter);
3747             } finally {
3748               Ember.endPropertyChanges();
3749             }
3750
3751             if (log) { Ember.Logger.log('End: Flush Sync Queue'); }
3752           } else {
3753             forEach.call(queue, iter);
3754           }
3755         }
3756
3757         // Loop through prior queues
3758         for (var i = 0; i <= idx; i++) {
3759           if (this._queues && this._queues[queueNames[i]]) {
3760             // Start over at the first queue with contents
3761             idx = i;
3762             continue outerloop;
3763           }
3764         }
3765
3766         idx++;
3767       }
3768     }
3769
3770     timerMark = null;
3771
3772     return this;
3773   }
3774
3775 };
3776
3777 Ember.RunLoop = RunLoop;
3778
3779 // ..........................................................
3780 // Ember.run - this is ideally the only public API the dev sees
3781 //
3782
3783 /**
3784   Runs the passed target and method inside of a RunLoop, ensuring any
3785   deferred actions including bindings and views updates are flushed at the
3786   end.
3787
3788   Normally you should not need to invoke this method yourself.  However if
3789   you are implementing raw event handlers when interfacing with other
3790   libraries or plugins, you should probably wrap all of your code inside this
3791   call.
3792
3793       Ember.run(function(){
3794         // code to be execute within a RunLoop 
3795       });
3796
3797   @class run
3798   @namespace Ember
3799   @static
3800   @constructor
3801   @param {Object} [target] target of method to call
3802   @param {Function|String} method Method to invoke.
3803     May be a function or a string.  If you pass a string
3804     then it will be looked up on the passed target.
3805   @param {Object} [args*] Any additional arguments you wish to pass to the method.
3806   @return {Object} return value from invoking the passed function.
3807 */
3808 Ember.run = function(target, method) {
3809   var ret, loop;
3810   run.begin();
3811   try {
3812     if (target || method) { ret = invoke(target, method, arguments, 2); }
3813   } finally {
3814     run.end();
3815   }
3816   return ret;
3817 };
3818
3819 var run = Ember.run;
3820
3821
3822 /**
3823   Begins a new RunLoop.  Any deferred actions invoked after the begin will
3824   be buffered until you invoke a matching call to Ember.run.end().  This is
3825   an lower-level way to use a RunLoop instead of using Ember.run().
3826
3827       Ember.run.begin();
3828       // code to be execute within a RunLoop 
3829       Ember.run.end();
3830
3831   @method begin
3832   @return {void}
3833 */
3834 Ember.run.begin = function() {
3835   run.currentRunLoop = new RunLoop(run.currentRunLoop);
3836 };
3837
3838 /**
3839   Ends a RunLoop.  This must be called sometime after you call Ember.run.begin()
3840   to flush any deferred actions.  This is a lower-level way to use a RunLoop
3841   instead of using Ember.run().
3842
3843       Ember.run.begin();
3844       // code to be execute within a RunLoop 
3845       Ember.run.end();
3846
3847   @method end
3848   @return {void}
3849 */
3850 Ember.run.end = function() {
3851   Ember.assert('must have a current run loop', run.currentRunLoop);
3852   try {
3853     run.currentRunLoop.end();
3854   }
3855   finally {
3856     run.currentRunLoop = run.currentRunLoop.prev();
3857   }
3858 };
3859
3860 /**
3861   Array of named queues.  This array determines the order in which queues
3862   are flushed at the end of the RunLoop.  You can define your own queues by
3863   simply adding the queue name to this array.  Normally you should not need
3864   to inspect or modify this property.
3865
3866   @property queues
3867   @type Array
3868   @default ['sync', 'actions', 'destroy', 'timers']
3869 */
3870 Ember.run.queues = ['sync', 'actions', 'destroy', 'timers'];
3871
3872 /**
3873   Adds the passed target/method and any optional arguments to the named
3874   queue to be executed at the end of the RunLoop.  If you have not already
3875   started a RunLoop when calling this method one will be started for you
3876   automatically.
3877
3878   At the end of a RunLoop, any methods scheduled in this way will be invoked.
3879   Methods will be invoked in an order matching the named queues defined in
3880   the run.queues property.
3881
3882       Ember.run.schedule('timers', this, function(){
3883         // this will be executed at the end of the RunLoop, when timers are run
3884         console.log("scheduled on timers queue");
3885       });
3886       Ember.run.schedule('sync', this, function(){
3887         // this will be executed at the end of the RunLoop, when bindings are synced
3888         console.log("scheduled on sync queue");
3889       });
3890       // Note the functions will be run in order based on the run queues order. Output would be:
3891       //   scheduled on sync queue
3892       //   scheduled on timers queue
3893
3894   @method schedule
3895   @param {String} queue The name of the queue to schedule against.
3896     Default queues are 'sync' and 'actions'
3897
3898   @param {Object} [target] target object to use as the context when invoking a method.
3899
3900   @param {String|Function} method The method to invoke.  If you pass a string it
3901     will be resolved on the target object at the time the scheduled item is
3902     invoked allowing you to change the target function.
3903
3904   @param {Object} [arguments*] Optional arguments to be passed to the queued method.
3905
3906   @return {void}
3907 */
3908 Ember.run.schedule = function(queue, target, method) {
3909   var loop = run.autorun();
3910   loop.schedule.apply(loop, arguments);
3911 };
3912
3913 var scheduledAutorun;
3914 function autorun() {
3915   scheduledAutorun = null;
3916   if (run.currentRunLoop) { run.end(); }
3917 }
3918
3919 // Used by global test teardown
3920 Ember.run.hasScheduledTimers = function() {
3921   return !!(scheduledAutorun || scheduledLater || scheduledNext);
3922 };
3923
3924 // Used by global test teardown
3925 Ember.run.cancelTimers = function () {
3926   if (scheduledAutorun) {
3927     clearTimeout(scheduledAutorun);
3928     scheduledAutorun = null;
3929   }
3930   if (scheduledLater) {
3931     clearTimeout(scheduledLater);
3932     scheduledLater = null;
3933   }
3934   if (scheduledNext) {
3935     clearTimeout(scheduledNext);
3936     scheduledNext = null;
3937   }
3938   timers = {};
3939 };
3940
3941 /**
3942   Begins a new RunLoop if necessary and schedules a timer to flush the
3943   RunLoop at a later time.  This method is used by parts of Ember to
3944   ensure the RunLoop always finishes.  You normally do not need to call this
3945   method directly.  Instead use Ember.run().
3946
3947
3948   @method autorun
3949   @example
3950     Ember.run.autorun();
3951   @return {Ember.RunLoop} the new current RunLoop
3952 */
3953 Ember.run.autorun = function() {
3954   if (!run.currentRunLoop) {
3955     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);
3956
3957     run.begin();
3958
3959     if (!scheduledAutorun) {
3960       scheduledAutorun = setTimeout(autorun, 1);
3961     }
3962   }
3963
3964   return run.currentRunLoop;
3965 };
3966
3967 /**
3968   Immediately flushes any events scheduled in the 'sync' queue.  Bindings
3969   use this queue so this method is a useful way to immediately force all
3970   bindings in the application to sync.
3971
3972   You should call this method anytime you need any changed state to propagate
3973   throughout the app immediately without repainting the UI.
3974
3975       Ember.run.sync();
3976
3977   @method sync
3978   @return {void}
3979 */
3980 Ember.run.sync = function() {
3981   run.autorun();
3982   run.currentRunLoop.flush('sync');
3983 };
3984
3985 // ..........................................................
3986 // TIMERS
3987 //
3988
3989 var timers = {}; // active timers...
3990
3991 var scheduledLater;
3992 function invokeLaterTimers() {
3993   scheduledLater = null;
3994   var now = (+ new Date()), earliest = -1;
3995   for (var key in timers) {
3996     if (!timers.hasOwnProperty(key)) { continue; }
3997     var timer = timers[key];
3998     if (timer && timer.expires) {
3999       if (now >= timer.expires) {
4000         delete timers[key];
4001         invoke(timer.target, timer.method, timer.args, 2);
4002       } else {
4003         if (earliest<0 || (timer.expires < earliest)) earliest=timer.expires;
4004       }
4005     }
4006   }
4007
4008   // schedule next timeout to fire...
4009   if (earliest > 0) { scheduledLater = setTimeout(invokeLaterTimers, earliest-(+ new Date())); }
4010 }
4011
4012 /**
4013   Invokes the passed target/method and optional arguments after a specified
4014   period if time.  The last parameter of this method must always be a number
4015   of milliseconds.
4016
4017   You should use this method whenever you need to run some action after a
4018   period of time instead of using setTimeout().  This method will ensure that
4019   items that expire during the same script execution cycle all execute
4020   together, which is often more efficient than using a real setTimeout.
4021
4022       Ember.run.later(myContext, function(){
4023         // code here will execute within a RunLoop in about 500ms with this == myContext
4024       }, 500);
4025
4026   @method later
4027   @param {Object} [target] target of method to invoke
4028
4029   @param {Function|String} method The method to invoke.
4030     If you pass a string it will be resolved on the
4031     target at the time the method is invoked.
4032
4033   @param {Object} [args*] Optional arguments to pass to the timeout.
4034
4035   @param {Number} wait
4036     Number of milliseconds to wait.
4037
4038   @return {String} a string you can use to cancel the timer in
4039     {{#crossLink "Ember/run.cancel"}}{{/crossLink}} later.
4040 */
4041 Ember.run.later = function(target, method) {
4042   var args, expires, timer, guid, wait;
4043
4044   // setTimeout compatibility...
4045   if (arguments.length===2 && 'function' === typeof target) {
4046     wait   = method;
4047     method = target;
4048     target = undefined;
4049     args   = [target, method];
4050   } else {
4051     args = slice.call(arguments);
4052     wait = args.pop();
4053   }
4054
4055   expires = (+ new Date()) + wait;
4056   timer   = { target: target, method: method, expires: expires, args: args };
4057   guid    = Ember.guidFor(timer);
4058   timers[guid] = timer;
4059   run.once(timers, invokeLaterTimers);
4060   return guid;
4061 };
4062
4063 function invokeOnceTimer(guid, onceTimers) {
4064   if (onceTimers[this.tguid]) { delete onceTimers[this.tguid][this.mguid]; }
4065   if (timers[guid]) { invoke(this.target, this.method, this.args); }
4066   delete timers[guid];
4067 }
4068
4069 function scheduleOnce(queue, target, method, args) {
4070   var tguid = Ember.guidFor(target),
4071     mguid = Ember.guidFor(method),
4072     onceTimers = run.autorun().onceTimers,
4073     guid = onceTimers[tguid] && onceTimers[tguid][mguid],
4074     timer;
4075
4076   if (guid && timers[guid]) {
4077     timers[guid].args = args; // replace args
4078   } else {
4079     timer = {
4080       target: target,
4081       method: method,
4082       args:   args,
4083       tguid:  tguid,
4084       mguid:  mguid
4085     };
4086
4087     guid  = Ember.guidFor(timer);
4088     timers[guid] = timer;
4089     if (!onceTimers[tguid]) { onceTimers[tguid] = {}; }
4090     onceTimers[tguid][mguid] = guid; // so it isn't scheduled more than once
4091
4092     run.schedule(queue, timer, invokeOnceTimer, guid, onceTimers);
4093   }
4094
4095   return guid;
4096 }
4097
4098 /**
4099   Schedules an item to run one time during the current RunLoop.  Calling
4100   this method with the same target/method combination will have no effect.
4101
4102   Note that although you can pass optional arguments these will not be
4103   considered when looking for duplicates.  New arguments will replace previous
4104   calls.
4105
4106       Ember.run(function(){
4107         var doFoo = function() { foo(); }
4108         Ember.run.once(myContext, doFoo);
4109         Ember.run.once(myContext, doFoo);
4110         // doFoo will only be executed once at the end of the RunLoop
4111       });
4112
4113   @method once
4114   @param {Object} [target] target of method to invoke
4115
4116   @param {Function|String} method The method to invoke.
4117     If you pass a string it will be resolved on the
4118     target at the time the method is invoked.
4119
4120   @param {Object} [args*] Optional arguments to pass to the timeout.
4121
4122
4123   @return {Object} timer
4124 */
4125 Ember.run.once = function(target, method) {
4126   return scheduleOnce('actions', target, method, slice.call(arguments, 2));
4127 };
4128
4129 Ember.run.scheduleOnce = function(queue, target, method, args) {
4130   return scheduleOnce(queue, target, method, slice.call(arguments, 3));
4131 };
4132
4133 var scheduledNext;
4134 function invokeNextTimers() {
4135   scheduledNext = null;
4136   for(var key in timers) {
4137     if (!timers.hasOwnProperty(key)) { continue; }
4138     var timer = timers[key];
4139     if (timer.next) {
4140       delete timers[key];
4141       invoke(timer.target, timer.method, timer.args, 2);
4142     }
4143   }
4144 }
4145
4146 /**
4147   Schedules an item to run after control has been returned to the system.
4148   This is often equivalent to calling setTimeout(function...,1).
4149
4150       Ember.run.next(myContext, function(){
4151         // code to be executed in the next RunLoop, which will be scheduled after the current one
4152       });
4153
4154   @method next
4155   @param {Object} [target] target of method to invoke
4156
4157   @param {Function|String} method The method to invoke.
4158     If you pass a string it will be resolved on the
4159     target at the time the method is invoked.
4160
4161   @param {Object} [args*] Optional arguments to pass to the timeout.
4162
4163   @return {Object} timer
4164 */
4165 Ember.run.next = function(target, method) {
4166   var guid,
4167       timer = {
4168         target: target,
4169         method: method,
4170         args: slice.call(arguments),
4171         next: true
4172       };
4173
4174   guid = Ember.guidFor(timer);
4175   timers[guid] = timer;
4176
4177   if (!scheduledNext) { scheduledNext = setTimeout(invokeNextTimers, 1); }
4178   return guid;
4179 };
4180
4181 /**
4182   Cancels a scheduled item.  Must be a value returned by `Ember.run.later()`,
4183   `Ember.run.once()`, or `Ember.run.next()`.
4184
4185       var runNext = Ember.run.next(myContext, function(){
4186         // will not be executed
4187       });
4188       Ember.run.cancel(runNext);
4189
4190       var runLater = Ember.run.later(myContext, function(){
4191         // will not be executed
4192       }, 500);
4193       Ember.run.cancel(runLater);
4194
4195       var runOnce = Ember.run.once(myContext, function(){
4196         // will not be executed
4197       });
4198       Ember.run.cancel(runOnce);
4199
4200   @method cancel
4201   @param {Object} timer Timer object to cancel
4202   @return {void}
4203 */
4204 Ember.run.cancel = function(timer) {
4205   delete timers[timer];
4206 };
4207
4208 })();
4209
4210
4211
4212 (function() {
4213 // Ember.Logger
4214 // get, set, trySet
4215 // guidFor, isArray, meta
4216 // addObserver, removeObserver
4217 // Ember.run.schedule
4218 /**
4219 @module ember-metal
4220 */
4221
4222 // ..........................................................
4223 // CONSTANTS
4224 //
4225
4226 /**
4227   Debug parameter you can turn on. This will log all bindings that fire to
4228   the console. This should be disabled in production code. Note that you
4229   can also enable this from the console or temporarily.
4230
4231   @property LOG_BINDINGS
4232   @for Ember
4233   @type Boolean
4234   @default false
4235 */
4236 Ember.LOG_BINDINGS = false || !!Ember.ENV.LOG_BINDINGS;
4237
4238 var get     = Ember.get,
4239     set     = Ember.set,
4240     guidFor = Ember.guidFor,
4241     isGlobalPath = Ember.isGlobalPath;
4242
4243
4244 function getWithGlobals(obj, path) {
4245   return get(isGlobalPath(path) ? window : obj, path);
4246 }
4247
4248 // ..........................................................
4249 // BINDING
4250 //
4251
4252 var Binding = function(toPath, fromPath) {
4253   this._direction = 'fwd';
4254   this._from = fromPath;
4255   this._to   = toPath;
4256   this._directionMap = Ember.Map.create();
4257 };
4258
4259 /**
4260 @class Binding
4261 @namespace Ember
4262 */
4263
4264 Binding.prototype = {
4265   /**
4266     This copies the Binding so it can be connected to another object.
4267
4268     @method copy
4269     @return {Ember.Binding}
4270   */
4271   copy: function () {
4272     var copy = new Binding(this._to, this._from);
4273     if (this._oneWay) { copy._oneWay = true; }
4274     return copy;
4275   },
4276
4277   // ..........................................................
4278   // CONFIG
4279   //
4280
4281   /**
4282     This will set "from" property path to the specified value. It will not
4283     attempt to resolve this property path to an actual object until you
4284     connect the binding.
4285
4286     The binding will search for the property path starting at the root object
4287     you pass when you connect() the binding.  It follows the same rules as
4288     `get()` - see that method for more information.
4289
4290     @method from
4291     @param {String} propertyPath the property path to connect to
4292     @return {Ember.Binding} receiver
4293   */
4294   from: function(path) {
4295     this._from = path;
4296     return this;
4297   },
4298
4299   /**
4300     This will set the "to" property path to the specified value. It will not
4301     attempt to resolve this property path to an actual object until you
4302     connect the binding.
4303
4304     The binding will search for the property path starting at the root object
4305     you pass when you connect() the binding.  It follows the same rules as
4306     `get()` - see that method for more information.
4307
4308     @method to
4309     @param {String|Tuple} propertyPath A property path or tuple
4310     @return {Ember.Binding} this
4311   */
4312   to: function(path) {
4313     this._to = path;
4314     return this;
4315   },
4316
4317   /**
4318     Configures the binding as one way. A one-way binding will relay changes
4319     on the "from" side to the "to" side, but not the other way around. This
4320     means that if you change the "to" side directly, the "from" side may have
4321     a different value.
4322
4323     @method oneWay
4324     @return {Ember.Binding} receiver
4325   */
4326   oneWay: function() {
4327     this._oneWay = true;
4328     return this;
4329   },
4330
4331   toString: function() {
4332     var oneWay = this._oneWay ? '[oneWay]' : '';
4333     return "Ember.Binding<" + guidFor(this) + ">(" + this._from + " -> " + this._to + ")" + oneWay;
4334   },
4335
4336   // ..........................................................
4337   // CONNECT AND SYNC
4338   //
4339
4340   /**
4341     Attempts to connect this binding instance so that it can receive and relay
4342     changes. This method will raise an exception if you have not set the
4343     from/to properties yet.
4344
4345     @method connect
4346     @param {Object} obj The root object for this binding.
4347     @return {Ember.Binding} this
4348   */
4349   connect: function(obj) {
4350     Ember.assert('Must pass a valid object to Ember.Binding.connect()', !!obj);
4351
4352     var fromPath = this._from, toPath = this._to;
4353     Ember.trySet(obj, toPath, getWithGlobals(obj, fromPath));
4354
4355     // add an observer on the object to be notified when the binding should be updated
4356     Ember.addObserver(obj, fromPath, this, this.fromDidChange);
4357
4358     // if the binding is a two-way binding, also set up an observer on the target
4359     if (!this._oneWay) { Ember.addObserver(obj, toPath, this, this.toDidChange); }
4360
4361     this._readyToSync = true;
4362
4363     return this;
4364   },
4365
4366   /**
4367     Disconnects the binding instance. Changes will no longer be relayed. You
4368     will not usually need to call this method.
4369
4370     @method disconnect
4371     @param {Object} obj The root object you passed when connecting the binding.
4372     @return {Ember.Binding} this
4373   */
4374   disconnect: function(obj) {
4375     Ember.assert('Must pass a valid object to Ember.Binding.disconnect()', !!obj);
4376
4377     var twoWay = !this._oneWay;
4378
4379     // remove an observer on the object so we're no longer notified of
4380     // changes that should update bindings.
4381     Ember.removeObserver(obj, this._from, this, this.fromDidChange);
4382
4383     // if the binding is two-way, remove the observer from the target as well
4384     if (twoWay) { Ember.removeObserver(obj, this._to, this, this.toDidChange); }
4385
4386     this._readyToSync = false; // disable scheduled syncs...
4387     return this;
4388   },
4389
4390   // ..........................................................
4391   // PRIVATE
4392   //
4393
4394   /* called when the from side changes */
4395   fromDidChange: function(target) {
4396     this._scheduleSync(target, 'fwd');
4397   },
4398
4399   /* called when the to side changes */
4400   toDidChange: function(target) {
4401     this._scheduleSync(target, 'back');
4402   },
4403
4404   _scheduleSync: function(obj, dir) {
4405     var directionMap = this._directionMap;
4406     var existingDir = directionMap.get(obj);
4407
4408     // if we haven't scheduled the binding yet, schedule it
4409     if (!existingDir) {
4410       Ember.run.schedule('sync', this, this._sync, obj);
4411       directionMap.set(obj, dir);
4412     }
4413
4414     // If both a 'back' and 'fwd' sync have been scheduled on the same object,
4415     // default to a 'fwd' sync so that it remains deterministic.
4416     if (existingDir === 'back' && dir === 'fwd') {
4417       directionMap.set(obj, 'fwd');
4418     }
4419   },
4420
4421   _sync: function(obj) {
4422     var log = Ember.LOG_BINDINGS;
4423
4424     // don't synchronize destroyed objects or disconnected bindings
4425     if (obj.isDestroyed || !this._readyToSync) { return; }
4426
4427     // get the direction of the binding for the object we are
4428     // synchronizing from
4429     var directionMap = this._directionMap;
4430     var direction = directionMap.get(obj);
4431
4432     var fromPath = this._from, toPath = this._to;
4433
4434     directionMap.remove(obj);
4435
4436     // if we're synchronizing from the remote object...
4437     if (direction === 'fwd') {
4438       var fromValue = getWithGlobals(obj, this._from);
4439       if (log) {
4440         Ember.Logger.log(' ', this.toString(), '->', fromValue, obj);
4441       }
4442       if (this._oneWay) {
4443         Ember.trySet(obj, toPath, fromValue);
4444       } else {
4445         Ember._suspendObserver(obj, toPath, this, this.toDidChange, function () {
4446           Ember.trySet(obj, toPath, fromValue);
4447         });
4448       }
4449     // if we're synchronizing *to* the remote object
4450     } else if (direction === 'back') {
4451       var toValue = get(obj, this._to);
4452       if (log) {
4453         Ember.Logger.log(' ', this.toString(), '<-', toValue, obj);
4454       }
4455       Ember._suspendObserver(obj, fromPath, this, this.fromDidChange, function () {
4456         Ember.trySet(Ember.isGlobalPath(fromPath) ? window : obj, fromPath, toValue);
4457       });
4458     }
4459   }
4460
4461 };
4462
4463 function mixinProperties(to, from) {
4464   for (var key in from) {
4465     if (from.hasOwnProperty(key)) {
4466       to[key] = from[key];
4467     }
4468   }
4469 }
4470
4471 mixinProperties(Binding, {
4472
4473   /**
4474     See {{#crossLink "Ember.Binding/from"}}{{/crossLink}}
4475
4476     @method from
4477     @static
4478   */
4479   from: function() {
4480     var C = this, binding = new C();
4481     return binding.from.apply(binding, arguments);
4482   },
4483
4484   /**
4485     See {{#crossLink "Ember.Binding/to"}}{{/crossLink}}
4486
4487     @method to
4488     @static
4489   */
4490   to: function() {
4491     var C = this, binding = new C();
4492     return binding.to.apply(binding, arguments);
4493   },
4494
4495   /**
4496     Creates a new Binding instance and makes it apply in a single direction.
4497     A one-way binding will relay changes on the "from" side object (supplied
4498     as the `from` argument) the "to" side, but not the other way around.
4499     This means that if you change the "to" side directly, the "from" side may have
4500     a different value.
4501
4502     See {{#crossLink "Binding/oneWay"}}{{/crossLink}}
4503
4504     @method oneWay
4505     @param {String} from from path.
4506     @param {Boolean} [flag] (Optional) passing nothing here will make the binding oneWay.  You can
4507       instead pass false to disable oneWay, making the binding two way again.
4508   */
4509   oneWay: function(from, flag) {
4510     var C = this, binding = new C(null, from);
4511     return binding.oneWay(flag);
4512   }
4513
4514 });
4515
4516 /**
4517   An Ember.Binding connects the properties of two objects so that whenever the
4518   value of one property changes, the other property will be changed also.
4519
4520   ## Automatic Creation of Bindings with `/^*Binding/`-named Properties
4521   You do not usually create Binding objects directly but instead describe
4522   bindings in your class or object definition using automatic binding detection.
4523
4524   Properties ending in a `Binding` suffix will be converted to Ember.Binding instances.
4525   The value of this property should be a string representing a path to another object or
4526   a custom binding instanced created using Binding helpers (see "Customizing Your Bindings"):
4527
4528       valueBinding: "MyApp.someController.title"
4529
4530   This will create a binding from `MyApp.someController.title` to the `value`
4531   property of your object instance automatically. Now the two values will be
4532   kept in sync.
4533
4534   ## One Way Bindings
4535
4536   One especially useful binding customization you can use is the `oneWay()`
4537   helper. This helper tells Ember that you are only interested in
4538   receiving changes on the object you are binding from. For example, if you
4539   are binding to a preference and you want to be notified if the preference
4540   has changed, but your object will not be changing the preference itself, you
4541   could do:
4542
4543       bigTitlesBinding: Ember.Binding.oneWay("MyApp.preferencesController.bigTitles")
4544
4545   This way if the value of MyApp.preferencesController.bigTitles changes the
4546   "bigTitles" property of your object will change also. However, if you
4547   change the value of your "bigTitles" property, it will not update the
4548   preferencesController.
4549
4550   One way bindings are almost twice as fast to setup and twice as fast to
4551   execute because the binding only has to worry about changes to one side.
4552
4553   You should consider using one way bindings anytime you have an object that
4554   may be created frequently and you do not intend to change a property; only
4555   to monitor it for changes. (such as in the example above).
4556
4557   ## Adding Bindings Manually
4558
4559   All of the examples above show you how to configure a custom binding, but
4560   the result of these customizations will be a binding template, not a fully
4561   active Binding instance. The binding will actually become active only when you
4562   instantiate the object the binding belongs to. It is useful however, to
4563   understand what actually happens when the binding is activated.
4564
4565   For a binding to function it must have at least a "from" property and a "to"
4566   property. The from property path points to the object/key that you want to
4567   bind from while the to path points to the object/key you want to bind to.
4568
4569   When you define a custom binding, you are usually describing the property
4570   you want to bind from (such as "MyApp.someController.value" in the examples
4571   above). When your object is created, it will automatically assign the value
4572   you want to bind "to" based on the name of your binding key. In the
4573   examples above, during init, Ember objects will effectively call
4574   something like this on your binding:
4575
4576       binding = Ember.Binding.from(this.valueBinding).to("value");
4577
4578   This creates a new binding instance based on the template you provide, and
4579   sets the to path to the "value" property of the new object. Now that the
4580   binding is fully configured with a "from" and a "to", it simply needs to be
4581   connected to become active. This is done through the connect() method:
4582
4583       binding.connect(this);
4584
4585   Note that when you connect a binding you pass the object you want it to be
4586   connected to.  This object will be used as the root for both the from and
4587   to side of the binding when inspecting relative paths.  This allows the
4588   binding to be automatically inherited by subclassed objects as well.
4589
4590   Now that the binding is connected, it will observe both the from and to side
4591   and relay changes.
4592
4593   If you ever needed to do so (you almost never will, but it is useful to
4594   understand this anyway), you could manually create an active binding by
4595   using the Ember.bind() helper method. (This is the same method used by
4596   to setup your bindings on objects):
4597
4598       Ember.bind(MyApp.anotherObject, "value", "MyApp.someController.value");
4599
4600   Both of these code fragments have the same effect as doing the most friendly
4601   form of binding creation like so:
4602
4603       MyApp.anotherObject = Ember.Object.create({
4604         valueBinding: "MyApp.someController.value",
4605
4606         // OTHER CODE FOR THIS OBJECT...
4607
4608       });
4609
4610   Ember's built in binding creation method makes it easy to automatically
4611   create bindings for you. You should always use the highest-level APIs
4612   available, even if you understand how it works underneath.
4613
4614   @class Binding
4615   @namespace Ember
4616   @since Ember 0.9
4617 */
4618 Ember.Binding = Binding;
4619
4620
4621 /**
4622   Global helper method to create a new binding.  Just pass the root object
4623   along with a to and from path to create and connect the binding.
4624
4625   @method bind
4626   @for Ember
4627   @param {Object} obj The root object of the transform.
4628
4629   @param {String} to The path to the 'to' side of the binding.
4630     Must be relative to obj.
4631
4632   @param {String} from The path to the 'from' side of the binding.
4633     Must be relative to obj or a global path.
4634
4635   @return {Ember.Binding} binding instance
4636 */
4637 Ember.bind = function(obj, to, from) {
4638   return new Ember.Binding(to, from).connect(obj);
4639 };
4640
4641 /**
4642   @method oneWay
4643   @for Ember
4644   @param {Object} obj The root object of the transform.
4645
4646   @param {String} to The path to the 'to' side of the binding.
4647     Must be relative to obj.
4648
4649   @param {String} from The path to the 'from' side of the binding.
4650     Must be relative to obj or a global path.
4651
4652   @return {Ember.Binding} binding instance
4653 */
4654 Ember.oneWay = function(obj, to, from) {
4655   return new Ember.Binding(to, from).oneWay().connect(obj);
4656 };
4657
4658 })();
4659
4660
4661
4662 (function() {
4663 /**
4664 @module ember-metal
4665 */
4666
4667 var Mixin, REQUIRED, Alias,
4668     classToString, superClassString,
4669     a_map = Ember.ArrayPolyfills.map,
4670     a_indexOf = Ember.ArrayPolyfills.indexOf,
4671     a_forEach = Ember.ArrayPolyfills.forEach,
4672     a_slice = [].slice,
4673     EMPTY_META = {}, // dummy for non-writable meta
4674     META_SKIP = { __emberproto__: true, __ember_count__: true },
4675     o_create = Ember.create,
4676     defineProperty = Ember.defineProperty,
4677     guidFor = Ember.guidFor;
4678
4679 function mixinsMeta(obj) {
4680   var m = Ember.meta(obj, true), ret = m.mixins;
4681   if (!ret) {
4682     ret = m.mixins = { __emberproto__: obj };
4683   } else if (ret.__emberproto__ !== obj) {
4684     ret = m.mixins = o_create(ret);
4685     ret.__emberproto__ = obj;
4686   }
4687   return ret;
4688 }
4689
4690 function initMixin(mixin, args) {
4691   if (args && args.length > 0) {
4692     mixin.mixins = a_map.call(args, function(x) {
4693       if (x instanceof Mixin) { return x; }
4694
4695       // Note: Manually setup a primitive mixin here.  This is the only
4696       // way to actually get a primitive mixin.  This way normal creation
4697       // of mixins will give you combined mixins...
4698       var mixin = new Mixin();
4699       mixin.properties = x;
4700       return mixin;
4701     });
4702   }
4703   return mixin;
4704 }
4705
4706 function isMethod(obj) {
4707   return 'function' === typeof obj &&
4708          obj.isMethod !== false &&
4709          obj !== Boolean && obj !== Object && obj !== Number && obj !== Array && obj !== Date && obj !== String;
4710 }
4711
4712 function mergeMixins(mixins, m, descs, values, base) {
4713   var len = mixins.length, idx, mixin, guid, props, value, key, ovalue, concats;
4714
4715   function removeKeys(keyName) {
4716     delete descs[keyName];
4717     delete values[keyName];
4718   }
4719
4720   for(idx=0; idx < len; idx++) {
4721     mixin = mixins[idx];
4722     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]');
4723
4724     if (mixin instanceof Mixin) {
4725       guid = guidFor(mixin);
4726       if (m[guid]) { continue; }
4727       m[guid] = mixin;
4728       props = mixin.properties;
4729     } else {
4730       props = mixin; // apply anonymous mixin properties
4731     }
4732
4733     if (props) {
4734       // reset before adding each new mixin to pickup concats from previous
4735       concats = values.concatenatedProperties || base.concatenatedProperties;
4736       if (props.concatenatedProperties) {
4737         concats = concats ? concats.concat(props.concatenatedProperties) : props.concatenatedProperties;
4738       }
4739
4740       for (key in props) {
4741         if (!props.hasOwnProperty(key)) { continue; }
4742         value = props[key];
4743         if (value instanceof Ember.Descriptor) {
4744           if (value === REQUIRED && descs[key]) { continue; }
4745
4746           descs[key]  = value;
4747           values[key] = undefined;
4748         } else {
4749           // impl super if needed...
4750           if (isMethod(value)) {
4751             ovalue = descs[key] === undefined && values[key];
4752             if (!ovalue) { ovalue = base[key]; }
4753             if ('function' !== typeof ovalue) { ovalue = null; }
4754             if (ovalue) {
4755               var o = value.__ember_observes__, ob = value.__ember_observesBefore__;
4756               value = Ember.wrap(value, ovalue);
4757               value.__ember_observes__ = o;
4758               value.__ember_observesBefore__ = ob;
4759             }
4760           } else if ((concats && a_indexOf.call(concats, key) >= 0) || key === 'concatenatedProperties') {
4761             var baseValue = values[key] || base[key];
4762             value = baseValue ? baseValue.concat(value) : Ember.makeArray(value);
4763           }
4764
4765           descs[key] = undefined;
4766           values[key] = value;
4767         }
4768       }
4769
4770       // manually copy toString() because some JS engines do not enumerate it
4771       if (props.hasOwnProperty('toString')) {
4772         base.toString = props.toString;
4773       }
4774
4775     } else if (mixin.mixins) {
4776       mergeMixins(mixin.mixins, m, descs, values, base);
4777       if (mixin._without) { a_forEach.call(mixin._without, removeKeys); }
4778     }
4779   }
4780 }
4781
4782 function writableReq(obj) {
4783   var m = Ember.meta(obj), req = m.required;
4784   if (!req || req.__emberproto__ !== obj) {
4785     req = m.required = req ? o_create(req) : { __ember_count__: 0 };
4786     req.__emberproto__ = obj;
4787   }
4788   return req;
4789 }
4790
4791 var IS_BINDING = Ember.IS_BINDING = /^.+Binding$/;
4792
4793 function detectBinding(obj, key, value, m) {
4794   if (IS_BINDING.test(key)) {
4795     var bindings = m.bindings;
4796     if (!bindings) {
4797       bindings = m.bindings = { __emberproto__: obj };
4798     } else if (bindings.__emberproto__ !== obj) {
4799       bindings = m.bindings = o_create(m.bindings);
4800       bindings.__emberproto__ = obj;
4801     }
4802     bindings[key] = value;
4803   }
4804 }
4805
4806 function connectBindings(obj, m) {
4807   // TODO Mixin.apply(instance) should disconnect binding if exists
4808   var bindings = m.bindings, key, binding, to;
4809   if (bindings) {
4810     for (key in bindings) {
4811       binding = key !== '__emberproto__' && bindings[key];
4812       if (binding) {
4813         to = key.slice(0, -7); // strip Binding off end
4814         if (binding instanceof Ember.Binding) {
4815           binding = binding.copy(); // copy prototypes' instance
4816           binding.to(to);
4817         } else { // binding is string path
4818           binding = new Ember.Binding(to, binding);
4819         }
4820         binding.connect(obj);
4821         obj[key] = binding;
4822       }
4823     }
4824     // mark as applied
4825     m.bindings = { __emberproto__: obj };
4826   }
4827 }
4828
4829 function finishPartial(obj, m) {
4830   connectBindings(obj, m || Ember.meta(obj));
4831   return obj;
4832 }
4833
4834 function applyMixin(obj, mixins, partial) {
4835   var descs = {}, values = {}, m = Ember.meta(obj), req = m.required,
4836       key, value, desc, prevValue, paths, len, idx;
4837
4838   // Go through all mixins and hashes passed in, and:
4839   //
4840   // * Handle concatenated properties
4841   // * Set up _super wrapping if necessary
4842   // * Set up computed property descriptors
4843   // * Copying `toString` in broken browsers
4844   mergeMixins(mixins, mixinsMeta(obj), descs, values, obj);
4845
4846   for(key in values) {
4847     if (key === 'contructor') { continue; }
4848     if (!values.hasOwnProperty(key)) { continue; }
4849
4850     desc = descs[key];
4851     value = values[key];
4852
4853     if (desc === REQUIRED) {
4854       if (!(key in obj)) {
4855         Ember.assert('Required property not defined: '+key, !!partial);
4856
4857         // for partial applies add to hash of required keys
4858         req = writableReq(obj);
4859         req.__ember_count__++;
4860         req[key] = true;
4861       }
4862     } else {
4863       while (desc && desc instanceof Alias) {
4864         var altKey = desc.methodName;
4865         if (descs[altKey] || values[altKey]) {
4866           value = values[altKey];
4867           desc  = descs[altKey];
4868         } else if (m.descs[altKey]) {
4869           desc  = m.descs[altKey];
4870           value = undefined;
4871         } else {
4872           desc = undefined;
4873           value = obj[altKey];
4874         }
4875       }
4876
4877       if (desc === undefined && value === undefined) { continue; }
4878
4879       prevValue = obj[key];
4880
4881       if ('function' === typeof prevValue) {
4882         if ((paths = prevValue.__ember_observesBefore__)) {
4883           len = paths.length;
4884           for (idx=0; idx < len; idx++) {
4885             Ember.removeBeforeObserver(obj, paths[idx], null, key);
4886           }
4887         } else if ((paths = prevValue.__ember_observes__)) {
4888           len = paths.length;
4889           for (idx=0; idx < len; idx++) {
4890             Ember.removeObserver(obj, paths[idx], null, key);
4891           }
4892         }
4893       }
4894
4895       detectBinding(obj, key, value, m);
4896
4897       defineProperty(obj, key, desc, value, m);
4898
4899       if ('function' === typeof value) {
4900         if (paths = value.__ember_observesBefore__) {
4901           len = paths.length;
4902           for (idx=0; idx < len; idx++) {
4903             Ember.addBeforeObserver(obj, paths[idx], null, key);
4904           }
4905         } else if (paths = value.__ember_observes__) {
4906           len = paths.length;
4907           for (idx=0; idx < len; idx++) {
4908             Ember.addObserver(obj, paths[idx], null, key);
4909           }
4910         }
4911       }
4912
4913       if (req && req[key]) {
4914         req = writableReq(obj);
4915         req.__ember_count__--;
4916         req[key] = false;
4917       }
4918     }
4919   }
4920
4921   if (!partial) { // don't apply to prototype
4922     finishPartial(obj, m);
4923   }
4924
4925   // Make sure no required attrs remain
4926   if (!partial && req && req.__ember_count__>0) {
4927     var keys = [];
4928     for (key in req) {
4929       if (META_SKIP[key]) { continue; }
4930       keys.push(key);
4931     }
4932     // TODO: Remove surrounding if clause from production build
4933     Ember.assert('Required properties not defined: '+keys.join(','));
4934   }
4935   return obj;
4936 }
4937
4938 /**
4939   @method mixin
4940   @for Ember
4941   @param obj
4942   @param mixins*
4943   @return obj
4944 */
4945 Ember.mixin = function(obj) {
4946   var args = a_slice.call(arguments, 1);
4947   applyMixin(obj, args, false);
4948   return obj;
4949 };
4950
4951 /**
4952   The `Ember.Mixin` class allows you to create mixins, whose properties can be
4953   added to other classes. For instance,
4954
4955       App.Editable = Ember.Mixin.create({
4956         edit: function() {
4957           console.log('starting to edit');
4958           this.set('isEditing', true);
4959         },
4960         isEditing: false
4961       });
4962
4963       // Mix mixins into classes by passing them as the first arguments to
4964       // .extend or .create.
4965       App.CommentView = Ember.View.extend(App.Editable, {
4966         template: Ember.Handlebars.compile('{{#if isEditing}}...{{else}}...{{/if}}')
4967       });
4968
4969       commentView = App.CommentView.create();
4970       commentView.edit(); // => outputs 'starting to edit'
4971
4972   Note that Mixins are created with `Ember.Mixin.create`, not
4973   `Ember.Mixin.extend`.
4974
4975   @class Mixin
4976   @namespace Ember
4977 */
4978 Ember.Mixin = function() { return initMixin(this, arguments); };
4979
4980 Mixin = Ember.Mixin;
4981
4982 Mixin._apply = applyMixin;
4983
4984 Mixin.applyPartial = function(obj) {
4985   var args = a_slice.call(arguments, 1);
4986   return applyMixin(obj, args, true);
4987 };
4988
4989 Mixin.finishPartial = finishPartial;
4990
4991 /**
4992   @method create
4993   @static
4994   @param arguments*
4995 */
4996 Mixin.create = function() {
4997   classToString.processed = false;
4998   var M = this;
4999   return initMixin(new M(), arguments);
5000 };
5001
5002 var MixinPrototype = Mixin.prototype;
5003
5004 /**
5005   @method reopen
5006   @param arguments*
5007 */
5008 MixinPrototype.reopen = function() {
5009   var mixin, tmp;
5010
5011   if (this.properties) {
5012     mixin = Mixin.create();
5013     mixin.properties = this.properties;
5014     delete this.properties;
5015     this.mixins = [mixin];
5016   } else if (!this.mixins) {
5017     this.mixins = [];
5018   }
5019
5020   var len = arguments.length, mixins = this.mixins, idx;
5021
5022   for(idx=0; idx < len; idx++) {
5023     mixin = arguments[idx];
5024     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]');
5025
5026     if (mixin instanceof Mixin) {
5027       mixins.push(mixin);
5028     } else {
5029       tmp = Mixin.create();
5030       tmp.properties = mixin;
5031       mixins.push(tmp);
5032     }
5033   }
5034
5035   return this;
5036 };
5037
5038 /**
5039   @method apply
5040   @param obj
5041   @return applied object
5042 */
5043 MixinPrototype.apply = function(obj) {
5044   return applyMixin(obj, [this], false);
5045 };
5046
5047 MixinPrototype.applyPartial = function(obj) {
5048   return applyMixin(obj, [this], true);
5049 };
5050
5051 function _detect(curMixin, targetMixin, seen) {
5052   var guid = guidFor(curMixin);
5053
5054   if (seen[guid]) { return false; }
5055   seen[guid] = true;
5056
5057   if (curMixin === targetMixin) { return true; }
5058   var mixins = curMixin.mixins, loc = mixins ? mixins.length : 0;
5059   while (--loc >= 0) {
5060     if (_detect(mixins[loc], targetMixin, seen)) { return true; }
5061   }
5062   return false;
5063 }
5064
5065 /**
5066   @method detect
5067   @param obj
5068   @return {Boolean}
5069 */
5070 MixinPrototype.detect = function(obj) {
5071   if (!obj) { return false; }
5072   if (obj instanceof Mixin) { return _detect(obj, this, {}); }
5073   var mixins = Ember.meta(obj, false).mixins;
5074   if (mixins) {
5075     return !!mixins[guidFor(this)];
5076   }
5077   return false;
5078 };
5079
5080 MixinPrototype.without = function() {
5081   var ret = new Mixin(this);
5082   ret._without = a_slice.call(arguments);
5083   return ret;
5084 };
5085
5086 function _keys(ret, mixin, seen) {
5087   if (seen[guidFor(mixin)]) { return; }
5088   seen[guidFor(mixin)] = true;
5089
5090   if (mixin.properties) {
5091     var props = mixin.properties;
5092     for (var key in props) {
5093       if (props.hasOwnProperty(key)) { ret[key] = true; }
5094     }
5095   } else if (mixin.mixins) {
5096     a_forEach.call(mixin.mixins, function(x) { _keys(ret, x, seen); });
5097   }
5098 }
5099
5100 MixinPrototype.keys = function() {
5101   var keys = {}, seen = {}, ret = [];
5102   _keys(keys, this, seen);
5103   for(var key in keys) {
5104     if (keys.hasOwnProperty(key)) { ret.push(key); }
5105   }
5106   return ret;
5107 };
5108
5109 /* make Mixins have nice displayNames */
5110
5111 var NAME_KEY = Ember.GUID_KEY+'_name';
5112 var get = Ember.get;
5113
5114 function processNames(paths, root, seen) {
5115   var idx = paths.length;
5116   for(var key in root) {
5117     if (!root.hasOwnProperty || !root.hasOwnProperty(key)) { continue; }
5118     var obj = root[key];
5119     paths[idx] = key;
5120
5121     if (obj && obj.toString === classToString) {
5122       obj[NAME_KEY] = paths.join('.');
5123     } else if (obj && get(obj, 'isNamespace')) {
5124       if (seen[guidFor(obj)]) { continue; }
5125       seen[guidFor(obj)] = true;
5126       processNames(paths, obj, seen);
5127     }
5128   }
5129   paths.length = idx; // cut out last item
5130 }
5131
5132 function findNamespaces() {
5133   var Namespace = Ember.Namespace, obj, isNamespace;
5134
5135   if (Namespace.PROCESSED) { return; }
5136
5137   for (var prop in window) {
5138     //  get(window.globalStorage, 'isNamespace') would try to read the storage for domain isNamespace and cause exception in Firefox.
5139     // globalStorage is a storage obsoleted by the WhatWG storage specification. See https://developer.mozilla.org/en/DOM/Storage#globalStorage
5140     if (prop === "globalStorage" && window.StorageList && window.globalStorage instanceof window.StorageList) { continue; }
5141     // Unfortunately, some versions of IE don't support window.hasOwnProperty
5142     if (window.hasOwnProperty && !window.hasOwnProperty(prop)) { continue; }
5143
5144     // At times we are not allowed to access certain properties for security reasons.
5145     // There are also times where even if we can access them, we are not allowed to access their properties.
5146     try {
5147       obj = window[prop];
5148       isNamespace = obj && get(obj, 'isNamespace');
5149     } catch (e) {
5150       continue;
5151     }
5152
5153     if (isNamespace) {
5154       Ember.deprecate("Namespaces should not begin with lowercase.", /^[A-Z]/.test(prop));
5155       obj[NAME_KEY] = prop;
5156     }
5157   }
5158 }
5159
5160 /**
5161   @private
5162   @method identifyNamespaces
5163   @for Ember
5164 */
5165 Ember.identifyNamespaces = findNamespaces;
5166
5167 superClassString = function(mixin) {
5168   var superclass = mixin.superclass;
5169   if (superclass) {
5170     if (superclass[NAME_KEY]) { return superclass[NAME_KEY]; }
5171     else { return superClassString(superclass); }
5172   } else {
5173     return;
5174   }
5175 };
5176
5177 classToString = function() {
5178   var Namespace = Ember.Namespace, namespace;
5179
5180   // TODO: Namespace should really be in Metal
5181   if (Namespace) {
5182     if (!this[NAME_KEY] && !classToString.processed) {
5183       if (!Namespace.PROCESSED) {
5184         findNamespaces();
5185         Namespace.PROCESSED = true;
5186       }
5187
5188       classToString.processed = true;
5189
5190       var namespaces = Namespace.NAMESPACES;
5191       for (var i=0, l=namespaces.length; i<l; i++) {
5192         namespace = namespaces[i];
5193         processNames([namespace.toString()], namespace, {});
5194       }
5195     }
5196   }
5197
5198   if (this[NAME_KEY]) {
5199     return this[NAME_KEY];
5200   } else {
5201     var str = superClassString(this);
5202     if (str) {
5203       return "(subclass of " + str + ")";
5204     } else {
5205       return "(unknown mixin)";
5206     }
5207   }
5208 };
5209
5210 MixinPrototype.toString = classToString;
5211
5212 // returns the mixins currently applied to the specified object
5213 // TODO: Make Ember.mixin
5214 Mixin.mixins = function(obj) {
5215   var ret = [], mixins = Ember.meta(obj, false).mixins, key, mixin;
5216   if (mixins) {
5217     for(key in mixins) {
5218       if (META_SKIP[key]) { continue; }
5219       mixin = mixins[key];
5220
5221       // skip primitive mixins since these are always anonymous
5222       if (!mixin.properties) { ret.push(mixins[key]); }
5223     }
5224   }
5225   return ret;
5226 };
5227
5228 REQUIRED = new Ember.Descriptor();
5229 REQUIRED.toString = function() { return '(Required Property)'; };
5230
5231 /**
5232   Denotes a required property for a mixin
5233
5234   @method required
5235   @for Ember
5236 */
5237 Ember.required = function() {
5238   return REQUIRED;
5239 };
5240
5241 Alias = function(methodName) {
5242   this.methodName = methodName;
5243 };
5244 Alias.prototype = new Ember.Descriptor();
5245
5246 /**
5247   Makes a property or method available via an additional name.
5248
5249       App.PaintSample = Ember.Object.extend({
5250         color: 'red',
5251         colour: Ember.alias('color'),
5252         name: function(){
5253           return "Zed";
5254         },
5255         moniker: Ember.alias("name")
5256       });
5257       var paintSample = App.PaintSample.create()
5258       paintSample.get('colour'); //=> 'red'
5259       paintSample.moniker(); //=> 'Zed'
5260
5261   @method alias
5262   @for Ember
5263   @param {String} methodName name of the method or property to alias
5264   @return {Ember.Descriptor}
5265 */
5266 Ember.alias = function(methodName) {
5267   return new Alias(methodName);
5268 };
5269
5270 // ..........................................................
5271 // OBSERVER HELPER
5272 //
5273
5274 /**
5275   @method observer
5276   @for Ember
5277   @param {Function} func
5278   @param {String} propertyNames*
5279   @return func
5280 */
5281 Ember.observer = function(func) {
5282   var paths = a_slice.call(arguments, 1);
5283   func.__ember_observes__ = paths;
5284   return func;
5285 };
5286
5287 // If observers ever become asynchronous, Ember.immediateObserver
5288 // must remain synchronous.
5289 /**
5290   @method immediateObserver
5291   @for Ember
5292   @param {Function} func
5293   @param {String} propertyNames*
5294   @return func
5295 */
5296 Ember.immediateObserver = function() {
5297   for (var i=0, l=arguments.length; i<l; i++) {
5298     var arg = arguments[i];
5299     Ember.assert("Immediate observers must observe internal properties only, not properties on other objects.", typeof arg !== "string" || arg.indexOf('.') === -1);
5300   }
5301
5302   return Ember.observer.apply(this, arguments);
5303 };
5304
5305 /**
5306   @method beforeObserver
5307   @for Ember
5308   @param {Function} func
5309   @param {String} propertyNames*
5310   @return func
5311 */
5312 Ember.beforeObserver = function(func) {
5313   var paths = a_slice.call(arguments, 1);
5314   func.__ember_observesBefore__ = paths;
5315   return func;
5316 };
5317
5318 })();
5319
5320
5321
5322 (function() {
5323 /**
5324 Ember Metal
5325
5326 @module ember
5327 @submodule ember-metal
5328 */
5329
5330 })();
5331
5332 (function() {
5333 /*globals ENV */
5334 /**
5335 @module ember
5336 @submodule ember-runtime
5337 */
5338
5339 var indexOf = Ember.EnumerableUtils.indexOf;
5340
5341 // ........................................
5342 // TYPING & ARRAY MESSAGING
5343 //
5344
5345 var TYPE_MAP = {};
5346 var t = "Boolean Number String Function Array Date RegExp Object".split(" ");
5347 Ember.ArrayPolyfills.forEach.call(t, function(name) {
5348   TYPE_MAP[ "[object " + name + "]" ] = name.toLowerCase();
5349 });
5350
5351 var toString = Object.prototype.toString;
5352
5353 /**
5354   Returns a consistent type for the passed item.
5355
5356   Use this instead of the built-in `typeof` to get the type of an item.
5357   It will return the same result across all browsers and includes a bit
5358   more detail.  Here is what will be returned:
5359
5360       | Return Value  | Meaning                                              |
5361       |---------------|------------------------------------------------------|
5362       | 'string'      | String primitive                                     |
5363       | 'number'      | Number primitive                                     |
5364       | 'boolean'     | Boolean primitive                                    |
5365       | 'null'        | Null value                                           |
5366       | 'undefined'   | Undefined value                                      |
5367       | 'function'    | A function                                           |
5368       | 'array'       | An instance of Array                                 |
5369       | 'class'       | A Ember class (created using Ember.Object.extend())  |
5370       | 'instance'    | A Ember object instance                              |
5371       | 'error'       | An instance of the Error object                      |
5372       | 'object'      | A JavaScript object not inheriting from Ember.Object |
5373
5374   Examples:
5375
5376       Ember.typeOf();                      => 'undefined'
5377       Ember.typeOf(null);                  => 'null'
5378       Ember.typeOf(undefined);             => 'undefined'
5379       Ember.typeOf('michael');             => 'string'
5380       Ember.typeOf(101);                   => 'number'
5381       Ember.typeOf(true);                  => 'boolean'
5382       Ember.typeOf(Ember.makeArray);       => 'function'
5383       Ember.typeOf([1,2,90]);              => 'array'
5384       Ember.typeOf(Ember.Object.extend()); => 'class'
5385       Ember.typeOf(Ember.Object.create()); => 'instance'
5386       Ember.typeOf(new Error('teamocil')); => 'error'
5387
5388       // "normal" JavaScript object
5389       Ember.typeOf({a: 'b'});              => 'object'
5390
5391   @method typeOf
5392   @for Ember
5393   @param item {Object} the item to check
5394   @return {String} the type
5395 */
5396 Ember.typeOf = function(item) {
5397   var ret;
5398
5399   ret = (item === null || item === undefined) ? String(item) : TYPE_MAP[toString.call(item)] || 'object';
5400
5401   if (ret === 'function') {
5402     if (Ember.Object && Ember.Object.detect(item)) ret = 'class';
5403   } else if (ret === 'object') {
5404     if (item instanceof Error) ret = 'error';
5405     else if (Ember.Object && item instanceof Ember.Object) ret = 'instance';
5406     else ret = 'object';
5407   }
5408
5409   return ret;
5410 };
5411
5412 /**
5413   Returns true if the passed value is null or undefined.  This avoids errors
5414   from JSLint complaining about use of ==, which can be technically
5415   confusing.
5416
5417       Ember.none();             => true
5418       Ember.none(null);         => true
5419       Ember.none(undefined);    => true
5420       Ember.none('');           => false
5421       Ember.none([]);           => false
5422       Ember.none(function(){}); => false
5423
5424   @method none
5425   @for Ember
5426   @param {Object} obj Value to test
5427   @return {Boolean}
5428 */
5429 Ember.none = function(obj) {
5430   return obj === null || obj === undefined;
5431 };
5432
5433 /**
5434   Verifies that a value is null or an empty string | array | function.
5435
5436   Constrains the rules on `Ember.none` by returning false for empty
5437   string and empty arrays.
5438
5439       Ember.empty();               => true
5440       Ember.empty(null);           => true
5441       Ember.empty(undefined);      => true
5442       Ember.empty('');             => true
5443       Ember.empty([]);             => true
5444       Ember.empty('tobias fünke'); => false
5445       Ember.empty([0,1,2]);        => false
5446
5447   @method empty
5448   @for Ember
5449   @param {Object} obj Value to test
5450   @return {Boolean}
5451 */
5452 Ember.empty = function(obj) {
5453   return obj === null || obj === undefined || (obj.length === 0 && typeof obj !== 'function') || (typeof obj === 'object' && Ember.get(obj, 'length') === 0);
5454 };
5455
5456 /**
5457  This will compare two javascript values of possibly different types.
5458  It will tell you which one is greater than the other by returning:
5459
5460   - -1 if the first is smaller than the second,
5461   - 0 if both are equal,
5462   - 1 if the first is greater than the second.
5463
5464  The order is calculated based on Ember.ORDER_DEFINITION, if types are different.
5465  In case they have the same type an appropriate comparison for this type is made.
5466
5467     Ember.compare('hello', 'hello');  => 0
5468     Ember.compare('abc', 'dfg');      => -1
5469     Ember.compare(2, 1);              => 1
5470
5471  @method compare
5472  @for Ember
5473  @param {Object} v First value to compare
5474  @param {Object} w Second value to compare
5475  @return {Number} -1 if v < w, 0 if v = w and 1 if v > w.
5476 */
5477 Ember.compare = function compare(v, w) {
5478   if (v === w) { return 0; }
5479
5480   var type1 = Ember.typeOf(v);
5481   var type2 = Ember.typeOf(w);
5482
5483   var Comparable = Ember.Comparable;
5484   if (Comparable) {
5485     if (type1==='instance' && Comparable.detect(v.constructor)) {
5486       return v.constructor.compare(v, w);
5487     }
5488
5489     if (type2 === 'instance' && Comparable.detect(w.constructor)) {
5490       return 1-w.constructor.compare(w, v);
5491     }
5492   }
5493
5494   // If we haven't yet generated a reverse-mapping of Ember.ORDER_DEFINITION,
5495   // do so now.
5496   var mapping = Ember.ORDER_DEFINITION_MAPPING;
5497   if (!mapping) {
5498     var order = Ember.ORDER_DEFINITION;
5499     mapping = Ember.ORDER_DEFINITION_MAPPING = {};
5500     var idx, len;
5501     for (idx = 0, len = order.length; idx < len;  ++idx) {
5502       mapping[order[idx]] = idx;
5503     }
5504
5505     // We no longer need Ember.ORDER_DEFINITION.
5506     delete Ember.ORDER_DEFINITION;
5507   }
5508
5509   var type1Index = mapping[type1];
5510   var type2Index = mapping[type2];
5511
5512   if (type1Index < type2Index) { return -1; }
5513   if (type1Index > type2Index) { return 1; }
5514
5515   // types are equal - so we have to check values now
5516   switch (type1) {
5517     case 'boolean':
5518     case 'number':
5519       if (v < w) { return -1; }
5520       if (v > w) { return 1; }
5521       return 0;
5522
5523     case 'string':
5524       var comp = v.localeCompare(w);
5525       if (comp < 0) { return -1; }
5526       if (comp > 0) { return 1; }
5527       return 0;
5528
5529     case 'array':
5530       var vLen = v.length;
5531       var wLen = w.length;
5532       var l = Math.min(vLen, wLen);
5533       var r = 0;
5534       var i = 0;
5535       while (r === 0 && i < l) {
5536         r = compare(v[i],w[i]);
5537         i++;
5538       }
5539       if (r !== 0) { return r; }
5540
5541       // all elements are equal now
5542       // shorter array should be ordered first
5543       if (vLen < wLen) { return -1; }
5544       if (vLen > wLen) { return 1; }
5545       // arrays are equal now
5546       return 0;
5547
5548     case 'instance':
5549       if (Ember.Comparable && Ember.Comparable.detect(v)) {
5550         return v.compare(v, w);
5551       }
5552       return 0;
5553
5554     case 'date':
5555       var vNum = v.getTime();
5556       var wNum = w.getTime();
5557       if (vNum < wNum) { return -1; }
5558       if (vNum > wNum) { return 1; }
5559       return 0;
5560
5561     default:
5562       return 0;
5563   }
5564 };
5565
5566 function _copy(obj, deep, seen, copies) {
5567   var ret, loc, key;
5568
5569   // primitive data types are immutable, just return them.
5570   if ('object' !== typeof obj || obj===null) return obj;
5571
5572   // avoid cyclical loops
5573   if (deep && (loc=indexOf(seen, obj))>=0) return copies[loc];
5574
5575   Ember.assert('Cannot clone an Ember.Object that does not implement Ember.Copyable', !(obj instanceof Ember.Object) || (Ember.Copyable && Ember.Copyable.detect(obj)));
5576
5577   // IMPORTANT: this specific test will detect a native array only.  Any other
5578   // object will need to implement Copyable.
5579   if (Ember.typeOf(obj) === 'array') {
5580     ret = obj.slice();
5581     if (deep) {
5582       loc = ret.length;
5583       while(--loc>=0) ret[loc] = _copy(ret[loc], deep, seen, copies);
5584     }
5585   } else if (Ember.Copyable && Ember.Copyable.detect(obj)) {
5586     ret = obj.copy(deep, seen, copies);
5587   } else {
5588     ret = {};
5589     for(key in obj) {
5590       if (!obj.hasOwnProperty(key)) continue;
5591       ret[key] = deep ? _copy(obj[key], deep, seen, copies) : obj[key];
5592     }
5593   }
5594
5595   if (deep) {
5596     seen.push(obj);
5597     copies.push(ret);
5598   }
5599
5600   return ret;
5601 }
5602
5603 /**
5604   Creates a clone of the passed object. This function can take just about
5605   any type of object and create a clone of it, including primitive values
5606   (which are not actually cloned because they are immutable).
5607
5608   If the passed object implements the clone() method, then this function
5609   will simply call that method and return the result.
5610
5611   @method copy
5612   @for Ember
5613   @param {Object} object The object to clone
5614   @param {Boolean} deep If true, a deep copy of the object is made
5615   @return {Object} The cloned object
5616 */
5617 Ember.copy = function(obj, deep) {
5618   // fast paths
5619   if ('object' !== typeof obj || obj===null) return obj; // can't copy primitives
5620   if (Ember.Copyable && Ember.Copyable.detect(obj)) return obj.copy(deep);
5621   return _copy(obj, deep, deep ? [] : null, deep ? [] : null);
5622 };
5623
5624 /**
5625   Convenience method to inspect an object. This method will attempt to
5626   convert the object into a useful string description.
5627
5628   @method inspect
5629   @for Ember
5630   @param {Object} obj The object you want to inspect.
5631   @return {String} A description of the object
5632 */
5633 Ember.inspect = function(obj) {
5634   var v, ret = [];
5635   for(var key in obj) {
5636     if (obj.hasOwnProperty(key)) {
5637       v = obj[key];
5638       if (v === 'toString') { continue; } // ignore useless items
5639       if (Ember.typeOf(v) === 'function') { v = "function() { ... }"; }
5640       ret.push(key + ": " + v);
5641     }
5642   }
5643   return "{" + ret.join(" , ") + "}";
5644 };
5645
5646 /**
5647   Compares two objects, returning true if they are logically equal.  This is
5648   a deeper comparison than a simple triple equal. For sets it will compare the
5649   internal objects.  For any other object that implements `isEqual()` it will 
5650   respect that method.
5651
5652       Ember.isEqual('hello', 'hello');  => true
5653       Ember.isEqual(1, 2);              => false
5654       Ember.isEqual([4,2], [4,2]);      => false
5655
5656   @method isEqual
5657   @for Ember
5658   @param {Object} a first object to compare
5659   @param {Object} b second object to compare
5660   @return {Boolean}
5661 */
5662 Ember.isEqual = function(a, b) {
5663   if (a && 'function'===typeof a.isEqual) return a.isEqual(b);
5664   return a === b;
5665 };
5666
5667 // Used by Ember.compare
5668 Ember.ORDER_DEFINITION = Ember.ENV.ORDER_DEFINITION || [
5669   'undefined',
5670   'null',
5671   'boolean',
5672   'number',
5673   'string',
5674   'array',
5675   'object',
5676   'instance',
5677   'function',
5678   'class',
5679   'date'
5680 ];
5681
5682 /**
5683   Returns all of the keys defined on an object or hash. This is useful
5684   when inspecting objects for debugging.  On browsers that support it, this
5685   uses the native Object.keys implementation.
5686
5687   @method keys
5688   @for Ember
5689   @param {Object} obj
5690   @return {Array} Array containing keys of obj
5691 */
5692 Ember.keys = Object.keys;
5693
5694 if (!Ember.keys) {
5695   Ember.keys = function(obj) {
5696     var ret = [];
5697     for(var key in obj) {
5698       if (obj.hasOwnProperty(key)) { ret.push(key); }
5699     }
5700     return ret;
5701   };
5702 }
5703
5704 // ..........................................................
5705 // ERROR
5706 //
5707
5708 var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
5709
5710 /**
5711   A subclass of the JavaScript Error object for use in Ember.
5712
5713   @class Error
5714   @namespace Ember
5715   @extends Error
5716   @constructor
5717 */
5718 Ember.Error = function() {
5719   var tmp = Error.prototype.constructor.apply(this, arguments);
5720
5721   // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
5722   for (var idx = 0; idx < errorProps.length; idx++) {
5723     this[errorProps[idx]] = tmp[errorProps[idx]];
5724   }
5725 };
5726
5727 Ember.Error.prototype = Ember.create(Error.prototype);
5728
5729 })();
5730
5731
5732
5733 (function() {
5734 /**
5735 @module ember
5736 @submodule ember-runtime
5737 */
5738
5739 var STRING_DASHERIZE_REGEXP = (/[ _]/g);
5740 var STRING_DASHERIZE_CACHE = {};
5741 var STRING_DECAMELIZE_REGEXP = (/([a-z])([A-Z])/g);
5742 var STRING_CAMELIZE_REGEXP = (/(\-|_|\s)+(.)?/g);
5743 var STRING_UNDERSCORE_REGEXP_1 = (/([a-z\d])([A-Z]+)/g);
5744 var STRING_UNDERSCORE_REGEXP_2 = (/\-|\s+/g);
5745
5746 /**
5747   Defines the hash of localized strings for the current language.  Used by
5748   the `Ember.String.loc()` helper.  To localize, add string values to this
5749   hash.
5750
5751   @property STRINGS
5752   @for Ember
5753   @type Hash
5754 */
5755 Ember.STRINGS = {};
5756
5757 /**
5758   Defines string helper methods including string formatting and localization.
5759   Unless Ember.EXTEND_PROTOTYPES = false these methods will also be added to the
5760   String.prototype as well.
5761
5762   @class String
5763   @namespace Ember
5764   @static
5765 */
5766 Ember.String = {
5767
5768   /**
5769     Apply formatting options to the string.  This will look for occurrences
5770     of %@ in your string and substitute them with the arguments you pass into
5771     this method.  If you want to control the specific order of replacement,
5772     you can add a number after the key as well to indicate which argument
5773     you want to insert.
5774
5775     Ordered insertions are most useful when building loc strings where values
5776     you need to insert may appear in different orders.
5777
5778         "Hello %@ %@".fmt('John', 'Doe') => "Hello John Doe"
5779         "Hello %@2, %@1".fmt('John', 'Doe') => "Hello Doe, John"
5780
5781     @method fmt
5782     @param {Object...} [args]
5783     @return {String} formatted string
5784   */
5785   fmt: function(str, formats) {
5786     // first, replace any ORDERED replacements.
5787     var idx  = 0; // the current index for non-numerical replacements
5788     return str.replace(/%@([0-9]+)?/g, function(s, argIndex) {
5789       argIndex = (argIndex) ? parseInt(argIndex,0) - 1 : idx++ ;
5790       s = formats[argIndex];
5791       return ((s === null) ? '(null)' : (s === undefined) ? '' : s).toString();
5792     }) ;
5793   },
5794
5795   /**
5796     Formats the passed string, but first looks up the string in the localized
5797     strings hash.  This is a convenient way to localize text.  See
5798     `Ember.String.fmt()` for more information on formatting.
5799
5800     Note that it is traditional but not required to prefix localized string
5801     keys with an underscore or other character so you can easily identify
5802     localized strings.
5803
5804         Ember.STRINGS = {
5805           '_Hello World': 'Bonjour le monde',
5806           '_Hello %@ %@': 'Bonjour %@ %@'
5807         };
5808
5809         Ember.String.loc("_Hello World");
5810         => 'Bonjour le monde';
5811
5812         Ember.String.loc("_Hello %@ %@", ["John", "Smith"]);
5813         => "Bonjour John Smith";
5814
5815     @method loc
5816     @param {String} str The string to format
5817     @param {Array} formats Optional array of parameters to interpolate into string.
5818     @return {String} formatted string
5819   */
5820   loc: function(str, formats) {
5821     str = Ember.STRINGS[str] || str;
5822     return Ember.String.fmt(str, formats) ;
5823   },
5824
5825   /**
5826     Splits a string into separate units separated by spaces, eliminating any
5827     empty strings in the process.  This is a convenience method for split that
5828     is mostly useful when applied to the String.prototype.
5829
5830         Ember.String.w("alpha beta gamma").forEach(function(key) {
5831           console.log(key);
5832         });
5833         > alpha
5834         > beta
5835         > gamma
5836
5837     @method w
5838     @param {String} str The string to split
5839     @return {String} split string
5840   */
5841   w: function(str) { return str.split(/\s+/); },
5842
5843   /**
5844     Converts a camelized string into all lower case separated by underscores.
5845     
5846         'innerHTML'.decamelize()         => 'inner_html'
5847         'action_name'.decamelize()       => 'action_name'
5848         'css-class-name'.decamelize()    => 'css-class-name'
5849         'my favorite items'.decamelize() => 'my favorite items'
5850
5851     @method decamelize
5852     @param {String} str The string to decamelize.
5853     @return {String} the decamelized string.
5854   */
5855   decamelize: function(str) {
5856     return str.replace(STRING_DECAMELIZE_REGEXP, '$1_$2').toLowerCase();
5857   },
5858
5859   /**
5860     Replaces underscores or spaces with dashes.
5861     
5862         'innerHTML'.dasherize()         => 'inner-html'
5863         'action_name'.dasherize()       => 'action-name'
5864         'css-class-name'.dasherize()    => 'css-class-name'
5865         'my favorite items'.dasherize() => 'my-favorite-items'
5866
5867     @method dasherize
5868     @param {String} str The string to dasherize.
5869     @return {String} the dasherized string.
5870   */
5871   dasherize: function(str) {
5872     var cache = STRING_DASHERIZE_CACHE,
5873         ret   = cache[str];
5874
5875     if (ret) {
5876       return ret;
5877     } else {
5878       ret = Ember.String.decamelize(str).replace(STRING_DASHERIZE_REGEXP,'-');
5879       cache[str] = ret;
5880     }
5881
5882     return ret;
5883   },
5884
5885   /**
5886     Returns the lowerCaseCamel form of a string.
5887
5888         'innerHTML'.camelize()         => 'innerHTML'
5889         'action_name'.camelize()       => 'actionName'
5890         'css-class-name'.camelize()    => 'cssClassName'
5891         'my favorite items'.camelize() => 'myFavoriteItems'
5892
5893     @method camelize
5894     @param {String} str The string to camelize.
5895     @return {String} the camelized string.
5896   */
5897   camelize: function(str) {
5898     return str.replace(STRING_CAMELIZE_REGEXP, function(match, separator, chr) {
5899       return chr ? chr.toUpperCase() : '';
5900     });
5901   },
5902
5903   /**
5904     Returns the UpperCamelCase form of a string.
5905
5906         'innerHTML'.classify()         => 'InnerHTML'
5907         'action_name'.classify()       => 'ActionName'
5908         'css-class-name'.classify()    => 'CssClassName'
5909         'my favorite items'.classify() => 'MyFavoriteItems'
5910
5911     @method classify
5912     @param {String} str the string to classify
5913     @return {String} the classified string
5914   */
5915   classify: function(str) {
5916     var camelized = Ember.String.camelize(str);
5917     return camelized.charAt(0).toUpperCase() + camelized.substr(1);
5918   },
5919
5920   /**
5921     More general than decamelize. Returns the lower_case_and_underscored
5922     form of a string.
5923
5924         'innerHTML'.underscore()         => 'inner_html'
5925         'action_name'.underscore()       => 'action_name'
5926         'css-class-name'.underscore()    => 'css_class_name'
5927         'my favorite items'.underscore() => 'my_favorite_items'
5928
5929     @property underscore
5930     @param {String} str The string to underscore.
5931     @return {String} the underscored string.
5932   */
5933   underscore: function(str) {
5934     return str.replace(STRING_UNDERSCORE_REGEXP_1, '$1_$2').
5935       replace(STRING_UNDERSCORE_REGEXP_2, '_').toLowerCase();
5936   }
5937 };
5938
5939 })();
5940
5941
5942
5943 (function() {
5944 /**
5945 @module ember
5946 @submodule ember-runtime
5947 */
5948
5949
5950
5951 var fmt = Ember.String.fmt,
5952     w   = Ember.String.w,
5953     loc = Ember.String.loc,
5954     camelize = Ember.String.camelize,
5955     decamelize = Ember.String.decamelize,
5956     dasherize = Ember.String.dasherize,
5957     underscore = Ember.String.underscore;
5958
5959 if (Ember.EXTEND_PROTOTYPES) {
5960
5961   /**
5962     See {{#crossLink "Ember.String/fmt"}}{{/crossLink}}
5963
5964     @method fmt
5965     @for String
5966   */
5967   String.prototype.fmt = function() {
5968     return fmt(this, arguments);
5969   };
5970
5971   /**
5972     See {{#crossLink "Ember.String/w"}}{{/crossLink}}
5973
5974     @method w
5975     @for String
5976   */
5977   String.prototype.w = function() {
5978     return w(this);
5979   };
5980
5981   /**
5982     See {{#crossLink "Ember.String/loc"}}{{/crossLink}}
5983
5984     @method loc
5985     @for String
5986   */
5987   String.prototype.loc = function() {
5988     return loc(this, arguments);
5989   };
5990
5991   /**
5992     See {{#crossLink "Ember.String/camelize"}}{{/crossLink}}
5993
5994     @method camelize
5995     @for String
5996   */
5997   String.prototype.camelize = function() {
5998     return camelize(this);
5999   };
6000
6001   /**
6002     See {{#crossLink "Ember.String/decamelize"}}{{/crossLink}}
6003
6004     @method decamelize
6005     @for String
6006   */
6007   String.prototype.decamelize = function() {
6008     return decamelize(this);
6009   };
6010
6011   /**
6012     See {{#crossLink "Ember.String/dasherize"}}{{/crossLink}}
6013
6014     @method dasherize
6015     @for String
6016   */
6017   String.prototype.dasherize = function() {
6018     return dasherize(this);
6019   };
6020
6021   /**
6022     See {{#crossLink "Ember.String/underscore"}}{{/crossLink}}
6023
6024     @method underscore
6025     @for String
6026   */
6027   String.prototype.underscore = function() {
6028     return underscore(this);
6029   };
6030
6031 }
6032
6033
6034 })();
6035
6036
6037
6038 (function() {
6039 /**
6040 @module ember
6041 @submodule ember-runtime
6042 */
6043
6044 var a_slice = Array.prototype.slice;
6045
6046 if (Ember.EXTEND_PROTOTYPES) {
6047
6048   /**
6049     The `property` extension of Javascript's Function prototype is available
6050     when Ember.EXTEND_PROTOTYPES is true, which is the default.
6051
6052     Computed properties allow you to treat a function like a property:
6053
6054         MyApp.president = Ember.Object.create({
6055           firstName: "Barack",
6056           lastName: "Obama",
6057
6058           fullName: function() {
6059             return this.get('firstName') + ' ' + this.get('lastName');
6060
6061             // Call this flag to mark the function as a property
6062           }.property()
6063         });
6064
6065         MyApp.president.get('fullName');    => "Barack Obama"
6066
6067     Treating a function like a property is useful because they can work with
6068     bindings, just like any other property.
6069
6070     Many computed properties have dependencies on other properties. For
6071     example, in the above example, the `fullName` property depends on
6072     `firstName` and `lastName` to determine its value. You can tell Ember.js
6073     about these dependencies like this:
6074
6075         MyApp.president = Ember.Object.create({
6076           firstName: "Barack",
6077           lastName: "Obama",
6078
6079           fullName: function() {
6080             return this.get('firstName') + ' ' + this.get('lastName');
6081
6082             // Tell Ember.js that this computed property depends on firstName
6083             // and lastName
6084           }.property('firstName', 'lastName')
6085         });
6086
6087     Make sure you list these dependencies so Ember.js knows when to update
6088     bindings that connect to a computed property. Changing a dependency
6089     will not immediately trigger an update of the computed property, but
6090     will instead clear the cache so that it is updated when the next `get`
6091     is called on the property.
6092
6093     See {{#crossLink "Ember.ComputedProperty"}}{{/crossLink}},
6094       {{#crossLink "Ember/computed"}}{{/crossLink}}
6095
6096     @method property
6097     @for Function
6098   */
6099   Function.prototype.property = function() {
6100     var ret = Ember.computed(this);
6101     return ret.property.apply(ret, arguments);
6102   };
6103
6104   /**
6105     The `observes` extension of Javascript's Function prototype is available
6106     when Ember.EXTEND_PROTOTYPES is true, which is the default.
6107
6108     You can observe property changes simply by adding the `observes`
6109     call to the end of your method declarations in classes that you write.
6110     For example:
6111
6112         Ember.Object.create({
6113           valueObserver: function() {
6114             // Executes whenever the "value" property changes
6115           }.observes('value')
6116         });
6117
6118     See {{#crossLink "Ember.Observable/observes"}}{{/crossLink}}
6119
6120     @method observes
6121     @for Function
6122   */
6123   Function.prototype.observes = function() {
6124     this.__ember_observes__ = a_slice.call(arguments);
6125     return this;
6126   };
6127
6128   /**
6129     The `observesBefore` extension of Javascript's Function prototype is
6130     available when Ember.EXTEND_PROTOTYPES is true, which is the default.
6131
6132     You can get notified when a property changes is about to happen by
6133     by adding the `observesBefore` call to the end of your method
6134     declarations in classes that you write. For example:
6135
6136         Ember.Object.create({
6137           valueObserver: function() {
6138             // Executes whenever the "value" property is about to change
6139           }.observesBefore('value')
6140         });
6141
6142     See {{#crossLink "Ember.Observable/observesBefore"}}{{/crossLink}}
6143
6144     @method observesBefore
6145     @for Function
6146   */
6147   Function.prototype.observesBefore = function() {
6148     this.__ember_observesBefore__ = a_slice.call(arguments);
6149     return this;
6150   };
6151
6152 }
6153
6154
6155 })();
6156
6157
6158
6159 (function() {
6160
6161 })();
6162
6163
6164
6165 (function() {
6166 /**
6167 @module ember
6168 @submodule ember-runtime
6169 */
6170
6171 // ..........................................................
6172 // HELPERS
6173 //
6174
6175 var get = Ember.get, set = Ember.set;
6176 var a_slice = Array.prototype.slice;
6177 var a_indexOf = Ember.EnumerableUtils.indexOf;
6178
6179 var contexts = [];
6180
6181 function popCtx() {
6182   return contexts.length===0 ? {} : contexts.pop();
6183 }
6184
6185 function pushCtx(ctx) {
6186   contexts.push(ctx);
6187   return null;
6188 }
6189
6190 function iter(key, value) {
6191   var valueProvided = arguments.length === 2;
6192
6193   function i(item) {
6194     var cur = get(item, key);
6195     return valueProvided ? value===cur : !!cur;
6196   }
6197   return i ;
6198 }
6199
6200 /**
6201   This mixin defines the common interface implemented by enumerable objects
6202   in Ember.  Most of these methods follow the standard Array iteration
6203   API defined up to JavaScript 1.8 (excluding language-specific features that
6204   cannot be emulated in older versions of JavaScript).
6205
6206   This mixin is applied automatically to the Array class on page load, so you
6207   can use any of these methods on simple arrays.  If Array already implements
6208   one of these methods, the mixin will not override them.
6209
6210   h3. Writing Your Own Enumerable
6211
6212   To make your own custom class enumerable, you need two items:
6213
6214   1. You must have a length property.  This property should change whenever
6215      the number of items in your enumerable object changes.  If you using this
6216      with an Ember.Object subclass, you should be sure to change the length
6217      property using set().
6218
6219   2. If you must implement nextObject().  See documentation.
6220
6221   Once you have these two methods implement, apply the Ember.Enumerable mixin
6222   to your class and you will be able to enumerate the contents of your object
6223   like any other collection.
6224
6225   h3. Using Ember Enumeration with Other Libraries
6226
6227   Many other libraries provide some kind of iterator or enumeration like
6228   facility.  This is often where the most common API conflicts occur.
6229   Ember's API is designed to be as friendly as possible with other
6230   libraries by implementing only methods that mostly correspond to the
6231   JavaScript 1.8 API.
6232
6233   @class Enumerable
6234   @namespace Ember
6235   @extends Ember.Mixin
6236   @since Ember 0.9
6237 */
6238 Ember.Enumerable = Ember.Mixin.create(
6239   /** @scope Ember.Enumerable.prototype */ {
6240
6241   // compatibility
6242   isEnumerable: true,
6243
6244   /**
6245     Implement this method to make your class enumerable.
6246
6247     This method will be call repeatedly during enumeration.  The index value
6248     will always begin with 0 and increment monotonically.  You don't have to
6249     rely on the index value to determine what object to return, but you should
6250     always check the value and start from the beginning when you see the
6251     requested index is 0.
6252
6253     The previousObject is the object that was returned from the last call
6254     to nextObject for the current iteration.  This is a useful way to
6255     manage iteration if you are tracing a linked list, for example.
6256
6257     Finally the context parameter will always contain a hash you can use as
6258     a "scratchpad" to maintain any other state you need in order to iterate
6259     properly.  The context object is reused and is not reset between
6260     iterations so make sure you setup the context with a fresh state whenever
6261     the index parameter is 0.
6262
6263     Generally iterators will continue to call nextObject until the index
6264     reaches the your current length-1.  If you run out of data before this
6265     time for some reason, you should simply return undefined.
6266
6267     The default implementation of this method simply looks up the index.
6268     This works great on any Array-like objects.
6269
6270     @method nextObject
6271     @param {Number} index the current index of the iteration
6272     @param {Object} previousObject the value returned by the last call to nextObject.
6273     @param {Object} context a context object you can use to maintain state.
6274     @return {Object} the next object in the iteration or undefined
6275   */
6276   nextObject: Ember.required(Function),
6277
6278   /**
6279     Helper method returns the first object from a collection.  This is usually
6280     used by bindings and other parts of the framework to extract a single
6281     object if the enumerable contains only one item.
6282
6283     If you override this method, you should implement it so that it will
6284     always return the same value each time it is called.  If your enumerable
6285     contains only one object, this method should always return that object.
6286     If your enumerable is empty, this method should return undefined.
6287
6288         var arr = ["a", "b", "c"];
6289         arr.firstObject(); => "a"
6290
6291         var arr = [];
6292         arr.firstObject(); => undefined
6293
6294     @property firstObject
6295     @return {Object} the object or undefined
6296   */
6297   firstObject: Ember.computed(function() {
6298     if (get(this, 'length')===0) return undefined ;
6299
6300     // handle generic enumerables
6301     var context = popCtx(), ret;
6302     ret = this.nextObject(0, null, context);
6303     pushCtx(context);
6304     return ret ;
6305   }).property('[]').cacheable(),
6306
6307   /**
6308     Helper method returns the last object from a collection. If your enumerable
6309     contains only one object, this method should always return that object.
6310     If your enumerable is empty, this method should return undefined.
6311
6312         var arr = ["a", "b", "c"];
6313         arr.lastObject(); => "c"
6314
6315         var arr = [];
6316         arr.lastObject(); => undefined
6317
6318     @property lastObject
6319     @return {Object} the last object or undefined
6320   */
6321   lastObject: Ember.computed(function() {
6322     var len = get(this, 'length');
6323     if (len===0) return undefined ;
6324     var context = popCtx(), idx=0, cur, last = null;
6325     do {
6326       last = cur;
6327       cur = this.nextObject(idx++, last, context);
6328     } while (cur !== undefined);
6329     pushCtx(context);
6330     return last;
6331   }).property('[]').cacheable(),
6332
6333   /**
6334     Returns true if the passed object can be found in the receiver.  The
6335     default version will iterate through the enumerable until the object
6336     is found.  You may want to override this with a more efficient version.
6337
6338         var arr = ["a", "b", "c"];
6339         arr.contains("a"); => true
6340         arr.contains("z"); => false
6341
6342     @method contains
6343     @param {Object} obj The object to search for.
6344     @return {Boolean} true if object is found in enumerable.
6345   */
6346   contains: function(obj) {
6347     return this.find(function(item) { return item===obj; }) !== undefined;
6348   },
6349
6350   /**
6351     Iterates through the enumerable, calling the passed function on each
6352     item. This method corresponds to the forEach() method defined in
6353     JavaScript 1.6.
6354
6355     The callback method you provide should have the following signature (all
6356     parameters are optional):
6357
6358           function(item, index, enumerable);
6359
6360     - *item* is the current item in the iteration.
6361     - *index* is the current index in the iteration
6362     - *enumerable* is the enumerable object itself.
6363
6364     Note that in addition to a callback, you can also pass an optional target
6365     object that will be set as "this" on the context. This is a good way
6366     to give your iterator function access to the current object.
6367
6368     @method forEach
6369     @param {Function} callback The callback to execute
6370     @param {Object} [target] The target object to use
6371     @return {Object} receiver
6372   */
6373   forEach: function(callback, target) {
6374     if (typeof callback !== "function") throw new TypeError() ;
6375     var len = get(this, 'length'), last = null, context = popCtx();
6376
6377     if (target === undefined) target = null;
6378
6379     for(var idx=0;idx<len;idx++) {
6380       var next = this.nextObject(idx, last, context) ;
6381       callback.call(target, next, idx, this);
6382       last = next ;
6383     }
6384     last = null ;
6385     context = pushCtx(context);
6386     return this ;
6387   },
6388
6389   /**
6390     Alias for mapProperty
6391
6392     @method getEach
6393     @param {String} key name of the property
6394     @return {Array} The mapped array.
6395   */
6396   getEach: function(key) {
6397     return this.mapProperty(key);
6398   },
6399
6400   /**
6401     Sets the value on the named property for each member. This is more
6402     efficient than using other methods defined on this helper. If the object
6403     implements Ember.Observable, the value will be changed to set(), otherwise
6404     it will be set directly. null objects are skipped.
6405
6406     @method setEach
6407     @param {String} key The key to set
6408     @param {Object} value The object to set
6409     @return {Object} receiver
6410   */
6411   setEach: function(key, value) {
6412     return this.forEach(function(item) {
6413       set(item, key, value);
6414     });
6415   },
6416
6417   /**
6418     Maps all of the items in the enumeration to another value, returning
6419     a new array. This method corresponds to map() defined in JavaScript 1.6.
6420
6421     The callback method you provide should have the following signature (all
6422     parameters are optional):
6423
6424         function(item, index, enumerable);
6425
6426     - *item* is the current item in the iteration.
6427     - *index* is the current index in the iteration
6428     - *enumerable* is the enumerable object itself.
6429
6430     It should return the mapped value.
6431
6432     Note that in addition to a callback, you can also pass an optional target
6433     object that will be set as "this" on the context. This is a good way
6434     to give your iterator function access to the current object.
6435
6436     @method map
6437     @param {Function} callback The callback to execute
6438     @param {Object} [target] The target object to use
6439     @return {Array} The mapped array.
6440   */
6441   map: function(callback, target) {
6442     var ret = [];
6443     this.forEach(function(x, idx, i) {
6444       ret[idx] = callback.call(target, x, idx,i);
6445     });
6446     return ret ;
6447   },
6448
6449   /**
6450     Similar to map, this specialized function returns the value of the named
6451     property on all items in the enumeration.
6452
6453     @method mapProperty
6454     @param {String} key name of the property
6455     @return {Array} The mapped array.
6456   */
6457   mapProperty: function(key) {
6458     return this.map(function(next) {
6459       return get(next, key);
6460     });
6461   },
6462
6463   /**
6464     Returns an array with all of the items in the enumeration that the passed
6465     function returns true for. This method corresponds to filter() defined in
6466     JavaScript 1.6.
6467
6468     The callback method you provide should have the following signature (all
6469     parameters are optional):
6470
6471           function(item, index, enumerable);
6472
6473     - *item* is the current item in the iteration.
6474     - *index* is the current index in the iteration
6475     - *enumerable* is the enumerable object itself.
6476
6477     It should return the true to include the item in the results, false otherwise.
6478
6479     Note that in addition to a callback, you can also pass an optional target
6480     object that will be set as "this" on the context. This is a good way
6481     to give your iterator function access to the current object.
6482
6483     @method filter
6484     @param {Function} callback The callback to execute
6485     @param {Object} [target] The target object to use
6486     @return {Array} A filtered array.
6487   */
6488   filter: function(callback, target) {
6489     var ret = [];
6490     this.forEach(function(x, idx, i) {
6491       if (callback.call(target, x, idx, i)) ret.push(x);
6492     });
6493     return ret ;
6494   },
6495
6496   /**
6497     Returns an array with just the items with the matched property.  You
6498     can pass an optional second argument with the target value.  Otherwise
6499     this will match any property that evaluates to true.
6500
6501     @method filterProperty
6502     @param {String} key the property to test
6503     @param {String} [value] optional value to test against.
6504     @return {Array} filtered array
6505   */
6506   filterProperty: function(key, value) {
6507     return this.filter(iter.apply(this, arguments));
6508   },
6509
6510   /**
6511     Returns the first item in the array for which the callback returns true.
6512     This method works similar to the filter() method defined in JavaScript 1.6
6513     except that it will stop working on the array once a match is found.
6514
6515     The callback method you provide should have the following signature (all
6516     parameters are optional):
6517
6518           function(item, index, enumerable);
6519
6520     - *item* is the current item in the iteration.
6521     - *index* is the current index in the iteration
6522     - *enumerable* is the enumerable object itself.
6523
6524     It should return the true to include the item in the results, false otherwise.
6525
6526     Note that in addition to a callback, you can also pass an optional target
6527     object that will be set as "this" on the context. This is a good way
6528     to give your iterator function access to the current object.
6529
6530     @method find
6531     @param {Function} callback The callback to execute
6532     @param {Object} [target] The target object to use
6533     @return {Object} Found item or null.
6534   */
6535   find: function(callback, target) {
6536     var len = get(this, 'length') ;
6537     if (target === undefined) target = null;
6538
6539     var last = null, next, found = false, ret ;
6540     var context = popCtx();
6541     for(var idx=0;idx<len && !found;idx++) {
6542       next = this.nextObject(idx, last, context) ;
6543       if (found = callback.call(target, next, idx, this)) ret = next ;
6544       last = next ;
6545     }
6546     next = last = null ;
6547     context = pushCtx(context);
6548     return ret ;
6549   },
6550
6551   /**
6552     Returns the first item with a property matching the passed value.  You
6553     can pass an optional second argument with the target value.  Otherwise
6554     this will match any property that evaluates to true.
6555
6556     This method works much like the more generic find() method.
6557
6558     @method findProperty
6559     @param {String} key the property to test
6560     @param {String} [value] optional value to test against.
6561     @return {Object} found item or null
6562   */
6563   findProperty: function(key, value) {
6564     return this.find(iter.apply(this, arguments));
6565   },
6566
6567   /**
6568     Returns true if the passed function returns true for every item in the
6569     enumeration. This corresponds with the every() method in JavaScript 1.6.
6570
6571     The callback method you provide should have the following signature (all
6572     parameters are optional):
6573
6574           function(item, index, enumerable);
6575
6576     - *item* is the current item in the iteration.
6577     - *index* is the current index in the iteration
6578     - *enumerable* is the enumerable object itself.
6579
6580     It should return the true or false.
6581
6582     Note that in addition to a callback, you can also pass an optional target
6583     object that will be set as "this" on the context. This is a good way
6584     to give your iterator function access to the current object.
6585
6586     Example Usage:
6587
6588           if (people.every(isEngineer)) { Paychecks.addBigBonus(); }
6589
6590     @method every
6591     @param {Function} callback The callback to execute
6592     @param {Object} [target] The target object to use
6593     @return {Boolean}
6594   */
6595   every: function(callback, target) {
6596     return !this.find(function(x, idx, i) {
6597       return !callback.call(target, x, idx, i);
6598     });
6599   },
6600
6601   /**
6602     Returns true if the passed property resolves to true for all items in the
6603     enumerable.  This method is often simpler/faster than using a callback.
6604
6605     @method everyProperty
6606     @param {String} key the property to test
6607     @param {String} [value] optional value to test against.
6608     @return {Array} filtered array
6609   */
6610   everyProperty: function(key, value) {
6611     return this.every(iter.apply(this, arguments));
6612   },
6613
6614
6615   /**
6616     Returns true if the passed function returns true for any item in the
6617     enumeration. This corresponds with the every() method in JavaScript 1.6.
6618
6619     The callback method you provide should have the following signature (all
6620     parameters are optional):
6621
6622           function(item, index, enumerable);
6623
6624     - *item* is the current item in the iteration.
6625     - *index* is the current index in the iteration
6626     - *enumerable* is the enumerable object itself.
6627
6628     It should return the true to include the item in the results, false otherwise.
6629
6630     Note that in addition to a callback, you can also pass an optional target
6631     object that will be set as "this" on the context. This is a good way
6632     to give your iterator function access to the current object.
6633
6634     Usage Example:
6635
6636           if (people.some(isManager)) { Paychecks.addBiggerBonus(); }
6637
6638     @method some
6639     @param {Function} callback The callback to execute
6640     @param {Object} [target] The target object to use
6641     @return {Array} A filtered array.
6642   */
6643   some: function(callback, target) {
6644     return !!this.find(function(x, idx, i) {
6645       return !!callback.call(target, x, idx, i);
6646     });
6647   },
6648
6649   /**
6650     Returns true if the passed property resolves to true for any item in the
6651     enumerable.  This method is often simpler/faster than using a callback.
6652
6653     @method someProperty
6654     @param {String} key the property to test
6655     @param {String} [value] optional value to test against.
6656     @return {Boolean} true
6657   */
6658   someProperty: function(key, value) {
6659     return this.some(iter.apply(this, arguments));
6660   },
6661
6662   /**
6663     This will combine the values of the enumerator into a single value. It
6664     is a useful way to collect a summary value from an enumeration. This
6665     corresponds to the reduce() method defined in JavaScript 1.8.
6666
6667     The callback method you provide should have the following signature (all
6668     parameters are optional):
6669
6670           function(previousValue, item, index, enumerable);
6671
6672     - *previousValue* is the value returned by the last call to the iterator.
6673     - *item* is the current item in the iteration.
6674     - *index* is the current index in the iteration
6675     - *enumerable* is the enumerable object itself.
6676
6677     Return the new cumulative value.
6678
6679     In addition to the callback you can also pass an initialValue. An error
6680     will be raised if you do not pass an initial value and the enumerator is
6681     empty.
6682
6683     Note that unlike the other methods, this method does not allow you to
6684     pass a target object to set as this for the callback. It's part of the
6685     spec. Sorry.
6686
6687     @method reduce
6688     @param {Function} callback The callback to execute
6689     @param {Object} initialValue Initial value for the reduce
6690     @param {String} reducerProperty internal use only.
6691     @return {Object} The reduced value.
6692   */
6693   reduce: function(callback, initialValue, reducerProperty) {
6694     if (typeof callback !== "function") { throw new TypeError(); }
6695
6696     var ret = initialValue;
6697
6698     this.forEach(function(item, i) {
6699       ret = callback.call(null, ret, item, i, this, reducerProperty);
6700     }, this);
6701
6702     return ret;
6703   },
6704
6705   /**
6706     Invokes the named method on every object in the receiver that
6707     implements it.  This method corresponds to the implementation in
6708     Prototype 1.6.
6709
6710     @method invoke
6711     @param {String} methodName the name of the method
6712     @param {Object...} args optional arguments to pass as well.
6713     @return {Array} return values from calling invoke.
6714   */
6715   invoke: function(methodName) {
6716     var args, ret = [];
6717     if (arguments.length>1) args = a_slice.call(arguments, 1);
6718
6719     this.forEach(function(x, idx) {
6720       var method = x && x[methodName];
6721       if ('function' === typeof method) {
6722         ret[idx] = args ? method.apply(x, args) : method.call(x);
6723       }
6724     }, this);
6725
6726     return ret;
6727   },
6728
6729   /**
6730     Simply converts the enumerable into a genuine array.  The order is not
6731     guaranteed.  Corresponds to the method implemented by Prototype.
6732
6733     @method toArray
6734     @return {Array} the enumerable as an array.
6735   */
6736   toArray: function() {
6737     var ret = [];
6738     this.forEach(function(o, idx) { ret[idx] = o; });
6739     return ret ;
6740   },
6741
6742   /**
6743     Returns a copy of the array with all null elements removed.
6744
6745         var arr = ["a", null, "c", null];
6746         arr.compact(); => ["a", "c"]
6747
6748     @method compact
6749     @return {Array} the array without null elements.
6750   */
6751   compact: function() { return this.without(null); },
6752
6753   /**
6754     Returns a new enumerable that excludes the passed value.  The default
6755     implementation returns an array regardless of the receiver type unless
6756     the receiver does not contain the value.
6757
6758         var arr = ["a", "b", "a", "c"];
6759         arr.without("a"); => ["b", "c"]
6760
6761     @method without
6762     @param {Object} value
6763     @return {Ember.Enumerable}
6764   */
6765   without: function(value) {
6766     if (!this.contains(value)) return this; // nothing to do
6767     var ret = [] ;
6768     this.forEach(function(k) {
6769       if (k !== value) ret[ret.length] = k;
6770     }) ;
6771     return ret ;
6772   },
6773
6774   /**
6775     Returns a new enumerable that contains only unique values.  The default
6776     implementation returns an array regardless of the receiver type.
6777
6778         var arr = ["a", "a", "b", "b"];
6779         arr.uniq(); => ["a", "b"]
6780
6781     @method uniq
6782     @return {Ember.Enumerable}
6783   */
6784   uniq: function() {
6785     var ret = [];
6786     this.forEach(function(k){
6787       if (a_indexOf(ret, k)<0) ret.push(k);
6788     });
6789     return ret;
6790   },
6791
6792   /**
6793     This property will trigger anytime the enumerable's content changes.
6794     You can observe this property to be notified of changes to the enumerables
6795     content.
6796
6797     For plain enumerables, this property is read only.  Ember.Array overrides
6798     this method.
6799
6800     @property []
6801     @type Ember.Array
6802   */
6803   '[]': Ember.computed(function(key, value) {
6804     return this;
6805   }).property().cacheable(),
6806
6807   // ..........................................................
6808   // ENUMERABLE OBSERVERS
6809   //
6810
6811   /**
6812     Registers an enumerable observer.   Must implement Ember.EnumerableObserver
6813     mixin.
6814
6815     @method addEnumerableObserver
6816     @param target {Object}
6817     @param opts {Hash}
6818   */
6819   addEnumerableObserver: function(target, opts) {
6820     var willChange = (opts && opts.willChange) || 'enumerableWillChange',
6821         didChange  = (opts && opts.didChange) || 'enumerableDidChange';
6822
6823     var hasObservers = get(this, 'hasEnumerableObservers');
6824     if (!hasObservers) Ember.propertyWillChange(this, 'hasEnumerableObservers');
6825     Ember.addListener(this, '@enumerable:before', target, willChange);
6826     Ember.addListener(this, '@enumerable:change', target, didChange);
6827     if (!hasObservers) Ember.propertyDidChange(this, 'hasEnumerableObservers');
6828     return this;
6829   },
6830
6831   /**
6832     Removes a registered enumerable observer.
6833
6834     @method removeEnumerableObserver
6835     @param target {Object}
6836     @param [opts] {Hash}
6837   */
6838   removeEnumerableObserver: function(target, opts) {
6839     var willChange = (opts && opts.willChange) || 'enumerableWillChange',
6840         didChange  = (opts && opts.didChange) || 'enumerableDidChange';
6841
6842     var hasObservers = get(this, 'hasEnumerableObservers');
6843     if (hasObservers) Ember.propertyWillChange(this, 'hasEnumerableObservers');
6844     Ember.removeListener(this, '@enumerable:before', target, willChange);
6845     Ember.removeListener(this, '@enumerable:change', target, didChange);
6846     if (hasObservers) Ember.propertyDidChange(this, 'hasEnumerableObservers');
6847     return this;
6848   },
6849
6850   /**
6851     Becomes true whenever the array currently has observers watching changes
6852     on the array.
6853
6854     @property hasEnumerableObservers
6855     @type Boolean
6856   */
6857   hasEnumerableObservers: Ember.computed(function() {
6858     return Ember.hasListeners(this, '@enumerable:change') || Ember.hasListeners(this, '@enumerable:before');
6859   }).property().cacheable(),
6860
6861
6862   /**
6863     Invoke this method just before the contents of your enumerable will
6864     change.  You can either omit the parameters completely or pass the objects
6865     to be removed or added if available or just a count.
6866
6867     @method enumerableContentWillChange
6868     @param {Ember.Enumerable|Number} removing An enumerable of the objects to
6869       be removed or the number of items to be removed.
6870     @param {Ember.Enumerable|Number} adding An enumerable of the objects to be
6871       added or the number of items to be added.
6872     @chainable
6873   */
6874   enumerableContentWillChange: function(removing, adding) {
6875
6876     var removeCnt, addCnt, hasDelta;
6877
6878     if ('number' === typeof removing) removeCnt = removing;
6879     else if (removing) removeCnt = get(removing, 'length');
6880     else removeCnt = removing = -1;
6881
6882     if ('number' === typeof adding) addCnt = adding;
6883     else if (adding) addCnt = get(adding,'length');
6884     else addCnt = adding = -1;
6885
6886     hasDelta = addCnt<0 || removeCnt<0 || addCnt-removeCnt!==0;
6887
6888     if (removing === -1) removing = null;
6889     if (adding   === -1) adding   = null;
6890
6891     Ember.propertyWillChange(this, '[]');
6892     if (hasDelta) Ember.propertyWillChange(this, 'length');
6893     Ember.sendEvent(this, '@enumerable:before', [this, removing, adding]);
6894
6895     return this;
6896   },
6897
6898   /**
6899     Invoke this method when the contents of your enumerable has changed.
6900     This will notify any observers watching for content changes.  If your are
6901     implementing an ordered enumerable (such as an array), also pass the
6902     start and end values where the content changed so that it can be used to
6903     notify range observers.
6904
6905     @method enumerableContentDidChange
6906     @param {Number} [start] optional start offset for the content change.
6907       For unordered enumerables, you should always pass -1.
6908     @param {Ember.Enumerable|Number} removing An enumerable of the objects to
6909       be removed or the number of items to be removed.
6910     @param {Ember.Enumerable|Number} adding  An enumerable of the objects to
6911       be added or the number of items to be added.
6912     @chainable
6913   */
6914   enumerableContentDidChange: function(removing, adding) {
6915     var notify = this.propertyDidChange, removeCnt, addCnt, hasDelta;
6916
6917     if ('number' === typeof removing) removeCnt = removing;
6918     else if (removing) removeCnt = get(removing, 'length');
6919     else removeCnt = removing = -1;
6920
6921     if ('number' === typeof adding) addCnt = adding;
6922     else if (adding) addCnt = get(adding, 'length');
6923     else addCnt = adding = -1;
6924
6925     hasDelta = addCnt<0 || removeCnt<0 || addCnt-removeCnt!==0;
6926
6927     if (removing === -1) removing = null;
6928     if (adding   === -1) adding   = null;
6929
6930     Ember.sendEvent(this, '@enumerable:change', [this, removing, adding]);
6931     if (hasDelta) Ember.propertyDidChange(this, 'length');
6932     Ember.propertyDidChange(this, '[]');
6933
6934     return this ;
6935   }
6936
6937 }) ;
6938
6939
6940
6941
6942 })();
6943
6944
6945
6946 (function() {
6947 /**
6948 @module ember
6949 @submodule ember-runtime
6950 */
6951
6952 // ..........................................................
6953 // HELPERS
6954 //
6955
6956 var get = Ember.get, set = Ember.set, meta = Ember.meta, map = Ember.EnumerableUtils.map, cacheFor = Ember.cacheFor;
6957
6958 function none(obj) { return obj===null || obj===undefined; }
6959
6960 // ..........................................................
6961 // ARRAY
6962 //
6963 /**
6964   This module implements Observer-friendly Array-like behavior.  This mixin is
6965   picked up by the Array class as well as other controllers, etc. that want to
6966   appear to be arrays.
6967
6968   Unlike Ember.Enumerable, this mixin defines methods specifically for
6969   collections that provide index-ordered access to their contents.  When you
6970   are designing code that needs to accept any kind of Array-like object, you
6971   should use these methods instead of Array primitives because these will
6972   properly notify observers of changes to the array.
6973
6974   Although these methods are efficient, they do add a layer of indirection to
6975   your application so it is a good idea to use them only when you need the
6976   flexibility of using both true JavaScript arrays and "virtual" arrays such
6977   as controllers and collections.
6978
6979   You can use the methods defined in this module to access and modify array
6980   contents in a KVO-friendly way.  You can also be notified whenever the
6981   membership if an array changes by changing the syntax of the property to
6982   .observes('*myProperty.[]') .
6983
6984   To support Ember.Array in your own class, you must override two
6985   primitives to use it: replace() and objectAt().
6986
6987   Note that the Ember.Array mixin also incorporates the Ember.Enumerable mixin.  All
6988   Ember.Array-like objects are also enumerable.
6989
6990   @class Array
6991   @namespace Ember
6992   @extends Ember.Mixin
6993   @uses Ember.Enumerable
6994   @since Ember 0.9.0
6995 */
6996 Ember.Array = Ember.Mixin.create(Ember.Enumerable, /** @scope Ember.Array.prototype */ {
6997
6998   // compatibility
6999   isSCArray: true,
7000
7001   /**
7002     Your array must support the length property. Your replace methods should
7003     set this property whenever it changes.
7004
7005     @property {Number} length
7006   */
7007   length: Ember.required(),
7008
7009   /**
7010     Returns the object at the given index. If the given index is negative or
7011     is greater or equal than the array length, returns `undefined`.
7012
7013     This is one of the primitives you must implement to support `Ember.Array`.
7014     If your object supports retrieving the value of an array item using `get()`
7015     (i.e. `myArray.get(0)`), then you do not need to implement this method
7016     yourself.
7017
7018         var arr = ['a', 'b', 'c', 'd'];
7019         arr.objectAt(0);  => "a"
7020         arr.objectAt(3);  => "d"
7021         arr.objectAt(-1); => undefined
7022         arr.objectAt(4);  => undefined
7023         arr.objectAt(5);  => undefined
7024
7025     @method objectAt
7026     @param {Number} idx
7027       The index of the item to return.
7028   */
7029   objectAt: function(idx) {
7030     if ((idx < 0) || (idx>=get(this, 'length'))) return undefined ;
7031     return get(this, idx);
7032   },
7033
7034   /**
7035     This returns the objects at the specified indexes, using `objectAt`.
7036
7037         var arr = ['a', 'b', 'c', 'd'];
7038         arr.objectsAt([0, 1, 2]) => ["a", "b", "c"]
7039         arr.objectsAt([2, 3, 4]) => ["c", "d", undefined]
7040
7041     @method objectsAt
7042     @param {Array} indexes
7043       An array of indexes of items to return.
7044    */
7045   objectsAt: function(indexes) {
7046     var self = this;
7047     return map(indexes, function(idx){ return self.objectAt(idx); });
7048   },
7049
7050   // overrides Ember.Enumerable version
7051   nextObject: function(idx) {
7052     return this.objectAt(idx);
7053   },
7054
7055   /**
7056     This is the handler for the special array content property.  If you get
7057     this property, it will return this.  If you set this property it a new
7058     array, it will replace the current content.
7059
7060     This property overrides the default property defined in Ember.Enumerable.
7061
7062     @property []
7063   */
7064   '[]': Ember.computed(function(key, value) {
7065     if (value !== undefined) this.replace(0, get(this, 'length'), value) ;
7066     return this ;
7067   }).property().cacheable(),
7068
7069   firstObject: Ember.computed(function() {
7070     return this.objectAt(0);
7071   }).property().cacheable(),
7072
7073   lastObject: Ember.computed(function() {
7074     return this.objectAt(get(this, 'length')-1);
7075   }).property().cacheable(),
7076
7077   // optimized version from Enumerable
7078   contains: function(obj){
7079     return this.indexOf(obj) >= 0;
7080   },
7081
7082   // Add any extra methods to Ember.Array that are native to the built-in Array.
7083   /**
7084     Returns a new array that is a slice of the receiver. This implementation
7085     uses the observable array methods to retrieve the objects for the new
7086     slice.
7087
7088         var arr = ['red', 'green', 'blue'];
7089         arr.slice(0);      => ['red', 'green', 'blue']
7090         arr.slice(0, 2);   => ['red', 'green']
7091         arr.slice(1, 100); => ['green', 'blue']
7092
7093     @method slice
7094     @param beginIndex {Integer} (Optional) index to begin slicing from.
7095     @param endIndex {Integer} (Optional) index to end the slice at.
7096     @return {Array} New array with specified slice
7097   */
7098   slice: function(beginIndex, endIndex) {
7099     var ret = [];
7100     var length = get(this, 'length') ;
7101     if (none(beginIndex)) beginIndex = 0 ;
7102     if (none(endIndex) || (endIndex > length)) endIndex = length ;
7103     while(beginIndex < endIndex) {
7104       ret[ret.length] = this.objectAt(beginIndex++) ;
7105     }
7106     return ret ;
7107   },
7108
7109   /**
7110     Returns the index of the given object's first occurrence.
7111     If no startAt argument is given, the starting location to
7112     search is 0. If it's negative, will count backward from
7113     the end of the array. Returns -1 if no match is found.
7114
7115         var arr = ["a", "b", "c", "d", "a"];
7116         arr.indexOf("a");      =>  0
7117         arr.indexOf("z");      => -1
7118         arr.indexOf("a", 2);   =>  4
7119         arr.indexOf("a", -1);  =>  4
7120         arr.indexOf("b", 3);   => -1
7121         arr.indexOf("a", 100); => -1
7122
7123     @method indexOf
7124     @param {Object} object the item to search for
7125     @param {Number} startAt optional starting location to search, default 0
7126     @return {Number} index or -1 if not found
7127   */
7128   indexOf: function(object, startAt) {
7129     var idx, len = get(this, 'length');
7130
7131     if (startAt === undefined) startAt = 0;
7132     if (startAt < 0) startAt += len;
7133
7134     for(idx=startAt;idx<len;idx++) {
7135       if (this.objectAt(idx, true) === object) return idx ;
7136     }
7137     return -1;
7138   },
7139
7140   /**
7141     Returns the index of the given object's last occurrence.
7142     If no startAt argument is given, the search starts from
7143     the last position. If it's negative, will count backward
7144     from the end of the array. Returns -1 if no match is found.
7145
7146         var arr = ["a", "b", "c", "d", "a"];
7147         arr.lastIndexOf("a");      =>  4
7148         arr.lastIndexOf("z");      => -1
7149         arr.lastIndexOf("a", 2);   =>  0
7150         arr.lastIndexOf("a", -1);  =>  4
7151         arr.lastIndexOf("b", 3);   =>  1
7152         arr.lastIndexOf("a", 100); =>  4
7153
7154     @method lastIndexOf
7155     @param {Object} object the item to search for
7156     @param {Number} startAt optional starting location to search, default 0
7157     @return {Number} index or -1 if not found
7158   */
7159   lastIndexOf: function(object, startAt) {
7160     var idx, len = get(this, 'length');
7161
7162     if (startAt === undefined || startAt >= len) startAt = len-1;
7163     if (startAt < 0) startAt += len;
7164
7165     for(idx=startAt;idx>=0;idx--) {
7166       if (this.objectAt(idx) === object) return idx ;
7167     }
7168     return -1;
7169   },
7170
7171   // ..........................................................
7172   // ARRAY OBSERVERS
7173   //
7174
7175   /**
7176     Adds an array observer to the receiving array.  The array observer object
7177     normally must implement two methods:
7178
7179     * `arrayWillChange(start, removeCount, addCount)` - This method will be
7180       called just before the array is modified.
7181     * `arrayDidChange(start, removeCount, addCount)` - This method will be
7182       called just after the array is modified.
7183
7184     Both callbacks will be passed the starting index of the change as well a
7185     a count of the items to be removed and added.  You can use these callbacks
7186     to optionally inspect the array during the change, clear caches, or do
7187     any other bookkeeping necessary.
7188
7189     In addition to passing a target, you can also include an options hash
7190     which you can use to override the method names that will be invoked on the
7191     target.
7192
7193     @method addArrayObserver
7194     @param {Object} target The observer object.
7195     @param {Hash} opts Optional hash of configuration options including
7196       willChange, didChange, and a context option.
7197     @return {Ember.Array} receiver
7198   */
7199   addArrayObserver: function(target, opts) {
7200     var willChange = (opts && opts.willChange) || 'arrayWillChange',
7201         didChange  = (opts && opts.didChange) || 'arrayDidChange';
7202
7203     var hasObservers = get(this, 'hasArrayObservers');
7204     if (!hasObservers) Ember.propertyWillChange(this, 'hasArrayObservers');
7205     Ember.addListener(this, '@array:before', target, willChange);
7206     Ember.addListener(this, '@array:change', target, didChange);
7207     if (!hasObservers) Ember.propertyDidChange(this, 'hasArrayObservers');
7208     return this;
7209   },
7210
7211   /**
7212     Removes an array observer from the object if the observer is current
7213     registered.  Calling this method multiple times with the same object will
7214     have no effect.
7215
7216     @method removeArrayObserver
7217     @param {Object} target The object observing the array.
7218     @return {Ember.Array} receiver
7219   */
7220   removeArrayObserver: function(target, opts) {
7221     var willChange = (opts && opts.willChange) || 'arrayWillChange',
7222         didChange  = (opts && opts.didChange) || 'arrayDidChange';
7223
7224     var hasObservers = get(this, 'hasArrayObservers');
7225     if (hasObservers) Ember.propertyWillChange(this, 'hasArrayObservers');
7226     Ember.removeListener(this, '@array:before', target, willChange);
7227     Ember.removeListener(this, '@array:change', target, didChange);
7228     if (hasObservers) Ember.propertyDidChange(this, 'hasArrayObservers');
7229     return this;
7230   },
7231
7232   /**
7233     Becomes true whenever the array currently has observers watching changes
7234     on the array.
7235
7236     @property Boolean
7237   */
7238   hasArrayObservers: Ember.computed(function() {
7239     return Ember.hasListeners(this, '@array:change') || Ember.hasListeners(this, '@array:before');
7240   }).property().cacheable(),
7241
7242   /**
7243     If you are implementing an object that supports Ember.Array, call this
7244     method just before the array content changes to notify any observers and
7245     invalidate any related properties.  Pass the starting index of the change
7246     as well as a delta of the amounts to change.
7247
7248     @method arrayContentWillChange
7249     @param {Number} startIdx The starting index in the array that will change.
7250     @param {Number} removeAmt The number of items that will be removed.  If you pass null assumes 0
7251     @param {Number} addAmt The number of items that will be added.  If you pass null assumes 0.
7252     @return {Ember.Array} receiver
7253   */
7254   arrayContentWillChange: function(startIdx, removeAmt, addAmt) {
7255
7256     // if no args are passed assume everything changes
7257     if (startIdx===undefined) {
7258       startIdx = 0;
7259       removeAmt = addAmt = -1;
7260     } else {
7261       if (removeAmt === undefined) removeAmt=-1;
7262       if (addAmt    === undefined) addAmt=-1;
7263     }
7264
7265     // Make sure the @each proxy is set up if anyone is observing @each
7266     if (Ember.isWatching(this, '@each')) { get(this, '@each'); }
7267
7268     Ember.sendEvent(this, '@array:before', [this, startIdx, removeAmt, addAmt]);
7269
7270     var removing, lim;
7271     if (startIdx>=0 && removeAmt>=0 && get(this, 'hasEnumerableObservers')) {
7272       removing = [];
7273       lim = startIdx+removeAmt;
7274       for(var idx=startIdx;idx<lim;idx++) removing.push(this.objectAt(idx));
7275     } else {
7276       removing = removeAmt;
7277     }
7278
7279     this.enumerableContentWillChange(removing, addAmt);
7280
7281     return this;
7282   },
7283
7284   arrayContentDidChange: function(startIdx, removeAmt, addAmt) {
7285
7286     // if no args are passed assume everything changes
7287     if (startIdx===undefined) {
7288       startIdx = 0;
7289       removeAmt = addAmt = -1;
7290     } else {
7291       if (removeAmt === undefined) removeAmt=-1;
7292       if (addAmt    === undefined) addAmt=-1;
7293     }
7294
7295     var adding, lim;
7296     if (startIdx>=0 && addAmt>=0 && get(this, 'hasEnumerableObservers')) {
7297       adding = [];
7298       lim = startIdx+addAmt;
7299       for(var idx=startIdx;idx<lim;idx++) adding.push(this.objectAt(idx));
7300     } else {
7301       adding = addAmt;
7302     }
7303
7304     this.enumerableContentDidChange(removeAmt, adding);
7305     Ember.sendEvent(this, '@array:change', [this, startIdx, removeAmt, addAmt]);
7306
7307     var length      = get(this, 'length'),
7308         cachedFirst = cacheFor(this, 'firstObject'),
7309         cachedLast  = cacheFor(this, 'lastObject');
7310     if (this.objectAt(0) !== cachedFirst) {
7311       Ember.propertyWillChange(this, 'firstObject');
7312       Ember.propertyDidChange(this, 'firstObject');
7313     }
7314     if (this.objectAt(length-1) !== cachedLast) {
7315       Ember.propertyWillChange(this, 'lastObject');
7316       Ember.propertyDidChange(this, 'lastObject');
7317     }
7318
7319     return this;
7320   },
7321
7322   // ..........................................................
7323   // ENUMERATED PROPERTIES
7324   //
7325
7326   /**
7327     Returns a special object that can be used to observe individual properties
7328     on the array.  Just get an equivalent property on this object and it will
7329     return an enumerable that maps automatically to the named key on the
7330     member objects.
7331
7332     @property @each
7333   */
7334   '@each': Ember.computed(function() {
7335     if (!this.__each) this.__each = new Ember.EachProxy(this);
7336     return this.__each;
7337   }).property().cacheable()
7338
7339 }) ;
7340
7341 })();
7342
7343
7344
7345 (function() {
7346 /**
7347 @module ember
7348 @submodule ember-runtime
7349 */
7350
7351
7352 /**
7353   Implements some standard methods for comparing objects. Add this mixin to
7354   any class you create that can compare its instances.
7355
7356   You should implement the compare() method.
7357
7358   @class Comparable
7359   @namespace Ember
7360   @extends Ember.Mixin
7361   @since Ember 0.9
7362 */
7363 Ember.Comparable = Ember.Mixin.create( /** @scope Ember.Comparable.prototype */{
7364
7365   /**
7366     walk like a duck. Indicates that the object can be compared.
7367
7368     @property isComparable
7369     @type Boolean
7370     @default true
7371   */
7372   isComparable: true,
7373
7374   /**
7375     Override to return the result of the comparison of the two parameters. The
7376     compare method should return:
7377
7378       - `-1` if `a < b`
7379       - `0` if `a == b`
7380       - `1` if `a > b`
7381
7382     Default implementation raises an exception.
7383
7384     @method compare
7385     @param a {Object} the first object to compare
7386     @param b {Object} the second object to compare
7387     @return {Integer} the result of the comparison
7388   */
7389   compare: Ember.required(Function)
7390
7391 });
7392
7393
7394 })();
7395
7396
7397
7398 (function() {
7399 /**
7400 @module ember
7401 @submodule ember-runtime
7402 */
7403
7404
7405
7406 var get = Ember.get, set = Ember.set;
7407
7408 /**
7409   Implements some standard methods for copying an object.  Add this mixin to
7410   any object you create that can create a copy of itself.  This mixin is
7411   added automatically to the built-in array.
7412
7413   You should generally implement the copy() method to return a copy of the
7414   receiver.
7415
7416   Note that frozenCopy() will only work if you also implement Ember.Freezable.
7417
7418   @class Copyable
7419   @namespace Ember
7420   @extends Ember.Mixin
7421   @since Ember 0.9
7422 */
7423 Ember.Copyable = Ember.Mixin.create(
7424 /** @scope Ember.Copyable.prototype */ {
7425
7426   /**
7427     Override to return a copy of the receiver.  Default implementation raises
7428     an exception.
7429
7430     @method copy
7431     @param deep {Boolean} if true, a deep copy of the object should be made
7432     @return {Object} copy of receiver
7433   */
7434   copy: Ember.required(Function),
7435
7436   /**
7437     If the object implements Ember.Freezable, then this will return a new copy
7438     if the object is not frozen and the receiver if the object is frozen.
7439
7440     Raises an exception if you try to call this method on a object that does
7441     not support freezing.
7442
7443     You should use this method whenever you want a copy of a freezable object
7444     since a freezable object can simply return itself without actually
7445     consuming more memory.
7446
7447     @method frozenCopy
7448     @return {Object} copy of receiver or receiver
7449   */
7450   frozenCopy: function() {
7451     if (Ember.Freezable && Ember.Freezable.detect(this)) {
7452       return get(this, 'isFrozen') ? this : this.copy().freeze();
7453     } else {
7454       throw new Error(Ember.String.fmt("%@ does not support freezing", [this]));
7455     }
7456   }
7457 });
7458
7459
7460
7461
7462 })();
7463
7464
7465
7466 (function() {
7467 /**
7468 @module ember
7469 @submodule ember-runtime
7470 */
7471
7472
7473 var get = Ember.get, set = Ember.set;
7474
7475 /**
7476   The Ember.Freezable mixin implements some basic methods for marking an object
7477   as frozen. Once an object is frozen it should be read only. No changes
7478   may be made the internal state of the object.
7479
7480   ## Enforcement
7481
7482   To fully support freezing in your subclass, you must include this mixin and
7483   override any method that might alter any property on the object to instead
7484   raise an exception. You can check the state of an object by checking the
7485   isFrozen property.
7486
7487   Although future versions of JavaScript may support language-level freezing
7488   object objects, that is not the case today. Even if an object is freezable,
7489   it is still technically possible to modify the object, even though it could
7490   break other parts of your application that do not expect a frozen object to
7491   change. It is, therefore, very important that you always respect the
7492   isFrozen property on all freezable objects.
7493
7494   ## Example Usage
7495
7496   The example below shows a simple object that implement the Ember.Freezable
7497   protocol.
7498
7499         Contact = Ember.Object.extend(Ember.Freezable, {
7500
7501           firstName: null,
7502
7503           lastName: null,
7504
7505           // swaps the names
7506           swapNames: function() {
7507             if (this.get('isFrozen')) throw Ember.FROZEN_ERROR;
7508             var tmp = this.get('firstName');
7509             this.set('firstName', this.get('lastName'));
7510             this.set('lastName', tmp);
7511             return this;
7512           }
7513
7514         });
7515
7516         c = Context.create({ firstName: "John", lastName: "Doe" });
7517         c.swapNames();  => returns c
7518         c.freeze();
7519         c.swapNames();  => EXCEPTION
7520
7521   ## Copying
7522
7523   Usually the Ember.Freezable protocol is implemented in cooperation with the
7524   Ember.Copyable protocol, which defines a frozenCopy() method that will return
7525   a frozen object, if the object implements this method as well.
7526
7527   @class Freezable
7528   @namespace Ember
7529   @extends Ember.Mixin
7530   @since Ember 0.9
7531 */
7532 Ember.Freezable = Ember.Mixin.create(
7533 /** @scope Ember.Freezable.prototype */ {
7534
7535   /**
7536     Set to true when the object is frozen.  Use this property to detect whether
7537     your object is frozen or not.
7538
7539     @property isFrozen
7540     @type Boolean
7541   */
7542   isFrozen: false,
7543
7544   /**
7545     Freezes the object.  Once this method has been called the object should
7546     no longer allow any properties to be edited.
7547
7548     @method freeze
7549     @return {Object} receiver
7550   */
7551   freeze: function() {
7552     if (get(this, 'isFrozen')) return this;
7553     set(this, 'isFrozen', true);
7554     return this;
7555   }
7556
7557 });
7558
7559 Ember.FROZEN_ERROR = "Frozen object cannot be modified.";
7560
7561 })();
7562
7563
7564
7565 (function() {
7566 /**
7567 @module ember
7568 @submodule ember-runtime
7569 */
7570
7571 var forEach = Ember.EnumerableUtils.forEach;
7572
7573 /**
7574   This mixin defines the API for modifying generic enumerables.  These methods
7575   can be applied to an object regardless of whether it is ordered or
7576   unordered.
7577
7578   Note that an Enumerable can change even if it does not implement this mixin.
7579   For example, a MappedEnumerable cannot be directly modified but if its
7580   underlying enumerable changes, it will change also.
7581
7582   ## Adding Objects
7583
7584   To add an object to an enumerable, use the addObject() method.  This
7585   method will only add the object to the enumerable if the object is not
7586   already present and the object if of a type supported by the enumerable.
7587
7588       set.addObject(contact);
7589
7590   ## Removing Objects
7591
7592   To remove an object form an enumerable, use the removeObject() method.  This
7593   will only remove the object if it is already in the enumerable, otherwise
7594   this method has no effect.
7595
7596       set.removeObject(contact);
7597
7598   ## Implementing In Your Own Code
7599
7600   If you are implementing an object and want to support this API, just include
7601   this mixin in your class and implement the required methods.  In your unit
7602   tests, be sure to apply the Ember.MutableEnumerableTests to your object.
7603
7604   @class MutableEnumerable
7605   @namespace Ember
7606   @extends Ember.Mixin
7607   @uses Ember.Enumerable
7608 */
7609 Ember.MutableEnumerable = Ember.Mixin.create(Ember.Enumerable,
7610   /** @scope Ember.MutableEnumerable.prototype */ {
7611
7612   /**
7613     __Required.__ You must implement this method to apply this mixin.
7614
7615     Attempts to add the passed object to the receiver if the object is not
7616     already present in the collection. If the object is present, this method
7617     has no effect.
7618
7619     If the passed object is of a type not supported by the receiver
7620     then this method should raise an exception.
7621
7622     @method addObject
7623     @param {Object} object The object to add to the enumerable.
7624     @return {Object} the passed object
7625   */
7626   addObject: Ember.required(Function),
7627
7628   /**
7629     Adds each object in the passed enumerable to the receiver.
7630
7631     @method addObjects
7632     @param {Ember.Enumerable} objects the objects to add.
7633     @return {Object} receiver
7634   */
7635   addObjects: function(objects) {
7636     Ember.beginPropertyChanges(this);
7637     forEach(objects, function(obj) { this.addObject(obj); }, this);
7638     Ember.endPropertyChanges(this);
7639     return this;
7640   },
7641
7642   /**
7643     __Required.__ You must implement this method to apply this mixin.
7644
7645     Attempts to remove the passed object from the receiver collection if the
7646     object is in present in the collection.  If the object is not present,
7647     this method has no effect.
7648
7649     If the passed object is of a type not supported by the receiver
7650     then this method should raise an exception.
7651
7652     @method removeObject
7653     @param {Object} object The object to remove from the enumerable.
7654     @return {Object} the passed object
7655   */
7656   removeObject: Ember.required(Function),
7657
7658
7659   /**
7660     Removes each objects in the passed enumerable from the receiver.
7661
7662     @method removeObjects
7663     @param {Ember.Enumerable} objects the objects to remove
7664     @return {Object} receiver
7665   */
7666   removeObjects: function(objects) {
7667     Ember.beginPropertyChanges(this);
7668     forEach(objects, function(obj) { this.removeObject(obj); }, this);
7669     Ember.endPropertyChanges(this);
7670     return this;
7671   }
7672
7673 });
7674
7675 })();
7676
7677
7678
7679 (function() {
7680 /**
7681 @module ember
7682 @submodule ember-runtime
7683 */
7684 // ..........................................................
7685 // CONSTANTS
7686 //
7687
7688 var OUT_OF_RANGE_EXCEPTION = "Index out of range" ;
7689 var EMPTY = [];
7690
7691 // ..........................................................
7692 // HELPERS
7693 //
7694
7695 var get = Ember.get, set = Ember.set, forEach = Ember.EnumerableUtils.forEach;
7696
7697 /**
7698   This mixin defines the API for modifying array-like objects.  These methods
7699   can be applied only to a collection that keeps its items in an ordered set.
7700
7701   Note that an Array can change even if it does not implement this mixin.
7702   For example, one might implement a SparseArray that cannot be directly
7703   modified, but if its underlying enumerable changes, it will change also.
7704
7705   @class MutableArray
7706   @namespace Ember
7707   @extends Ember.Mixin
7708   @uses Ember.Array
7709   @uses Ember.MutableEnumerable
7710 */
7711 Ember.MutableArray = Ember.Mixin.create(Ember.Array, Ember.MutableEnumerable,
7712   /** @scope Ember.MutableArray.prototype */ {
7713
7714   /**
7715     __Required.__ You must implement this method to apply this mixin.
7716
7717     This is one of the primitives you must implement to support Ember.Array.  You
7718     should replace amt objects started at idx with the objects in the passed
7719     array.  You should also call this.enumerableContentDidChange() ;
7720
7721     @method replace
7722     @param {Number} idx Starting index in the array to replace.  If idx >= length,
7723       then append to the end of the array.
7724     @param {Number} amt Number of elements that should be removed from the array,
7725       starting at *idx*.
7726     @param {Array} objects An array of zero or more objects that should be inserted
7727       into the array at *idx*
7728   */
7729   replace: Ember.required(),
7730
7731   /**
7732     Remove all elements from self. This is useful if you
7733     want to reuse an existing array without having to recreate it.
7734
7735         var colors = ["red", "green", "blue"];
7736         color.length();  => 3
7737         colors.clear();  => []
7738         colors.length(); => 0
7739
7740     @method clear
7741     @return {Ember.Array} An empty Array. 
7742   */
7743   clear: function () {
7744     var len = get(this, 'length');
7745     if (len === 0) return this;
7746     this.replace(0, len, EMPTY);
7747     return this;
7748   },
7749
7750   /**
7751     This will use the primitive replace() method to insert an object at the
7752     specified index.
7753
7754         var colors = ["red", "green", "blue"];
7755         colors.insertAt(2, "yellow"); => ["red", "green", "yellow", "blue"]
7756         colors.insertAt(5, "orange"); => Error: Index out of range
7757
7758     @method insertAt
7759     @param {Number} idx index of insert the object at.
7760     @param {Object} object object to insert
7761   */
7762   insertAt: function(idx, object) {
7763     if (idx > get(this, 'length')) throw new Error(OUT_OF_RANGE_EXCEPTION) ;
7764     this.replace(idx, 0, [object]) ;
7765     return this ;
7766   },
7767
7768   /**
7769     Remove an object at the specified index using the replace() primitive
7770     method.  You can pass either a single index, or a start and a length.
7771
7772     If you pass a start and length that is beyond the
7773     length this method will throw an Ember.OUT_OF_RANGE_EXCEPTION
7774
7775         var colors = ["red", "green", "blue", "yellow", "orange"];
7776         colors.removeAt(0); => ["green", "blue", "yellow", "orange"]
7777         colors.removeAt(2, 2); => ["green", "blue"]
7778         colors.removeAt(4, 2); => Error: Index out of range
7779
7780     @method removeAt
7781     @param {Number} start index, start of range
7782     @param {Number} len length of passing range
7783     @return {Object} receiver
7784   */
7785   removeAt: function(start, len) {
7786     if ('number' === typeof start) {
7787
7788       if ((start < 0) || (start >= get(this, 'length'))) {
7789         throw new Error(OUT_OF_RANGE_EXCEPTION);
7790       }
7791
7792       // fast case
7793       if (len === undefined) len = 1;
7794       this.replace(start, len, EMPTY);
7795     }
7796
7797     return this ;
7798   },
7799
7800   /**
7801     Push the object onto the end of the array.  Works just like push() but it
7802     is KVO-compliant.
7803
7804         var colors = ["red", "green", "blue"];
7805         colors.pushObject("black"); => ["red", "green", "blue", "black"]
7806         colors.pushObject(["yellow", "orange"]); => ["red", "green", "blue", "black", ["yellow", "orange"]]
7807
7808     @method pushObject
7809     @param {anything} obj object to push
7810   */
7811   pushObject: function(obj) {
7812     this.insertAt(get(this, 'length'), obj) ;
7813     return obj ;
7814   },
7815
7816   /**
7817     Add the objects in the passed numerable to the end of the array.  Defers
7818     notifying observers of the change until all objects are added.
7819
7820         var colors = ["red", "green", "blue"];
7821         colors.pushObjects("black"); => ["red", "green", "blue", "black"]
7822         colors.pushObjects(["yellow", "orange"]); => ["red", "green", "blue", "black", "yellow", "orange"]
7823
7824     @method pushObjects
7825     @param {Ember.Enumerable} objects the objects to add
7826     @return {Ember.Array} receiver
7827   */
7828   pushObjects: function(objects) {
7829     this.replace(get(this, 'length'), 0, objects);
7830     return this;
7831   },
7832
7833   /**
7834     Pop object from array or nil if none are left.  Works just like pop() but
7835     it is KVO-compliant.
7836
7837         var colors = ["red", "green", "blue"];
7838         colors.popObject(); => "blue"
7839         console.log(colors); => ["red", "green"]
7840
7841     @method popObject
7842     @return object
7843   */
7844   popObject: function() {
7845     var len = get(this, 'length') ;
7846     if (len === 0) return null ;
7847
7848     var ret = this.objectAt(len-1) ;
7849     this.removeAt(len-1, 1) ;
7850     return ret ;
7851   },
7852
7853   /**
7854     Shift an object from start of array or nil if none are left.  Works just
7855     like shift() but it is KVO-compliant.
7856
7857         var colors = ["red", "green", "blue"];
7858         colors.shiftObject(); => "red"
7859         console.log(colors); => ["green", "blue"]
7860
7861     @method shiftObject
7862     @return object
7863   */
7864   shiftObject: function() {
7865     if (get(this, 'length') === 0) return null ;
7866     var ret = this.objectAt(0) ;
7867     this.removeAt(0) ;
7868     return ret ;
7869   },
7870
7871   /**
7872     Unshift an object to start of array.  Works just like unshift() but it is
7873     KVO-compliant.
7874
7875         var colors = ["red", "green", "blue"];
7876         colors.unshiftObject("yellow"); => ["yellow", "red", "green", "blue"]
7877         colors.unshiftObject(["black", "white"]); => [["black", "white"], "yellow", "red", "green", "blue"]
7878
7879     @method unshiftObject
7880     @param {anything} obj object to unshift
7881   */
7882   unshiftObject: function(obj) {
7883     this.insertAt(0, obj) ;
7884     return obj ;
7885   },
7886
7887   /**
7888     Adds the named objects to the beginning of the array.  Defers notifying
7889     observers until all objects have been added.
7890
7891         var colors = ["red", "green", "blue"];
7892         colors.unshiftObjects(["black", "white"]); => ["black", "white", "red", "green", "blue"]
7893         colors.unshiftObjects("yellow"); => Type Error: 'undefined' is not a function
7894
7895     @method unshiftObjects
7896     @param {Ember.Enumerable} objects the objects to add
7897     @return {Ember.Array} receiver
7898   */
7899   unshiftObjects: function(objects) {
7900     this.replace(0, 0, objects);
7901     return this;
7902   },
7903
7904   /**
7905     Reverse objects in the array.  Works just like reverse() but it is
7906     KVO-compliant.
7907
7908     @method reverseObjects
7909     @return {Ember.Array} receiver
7910    */
7911   reverseObjects: function() {
7912     var len = get(this, 'length');
7913     if (len === 0) return this;
7914     var objects = this.toArray().reverse();
7915     this.replace(0, len, objects);
7916     return this;
7917   },
7918
7919   /**
7920     Replace all the the receiver's content with content of the argument.
7921     If argument is an empty array receiver will be cleared.
7922
7923         var colors = ["red", "green", "blue"];
7924         colors.setObjects(["black", "white"]); => ["black", "white"]
7925         colors.setObjects([]); => []
7926
7927     @method setObjects
7928     @param {Ember.Array} objects array whose content will be used for replacing
7929         the content of the receiver
7930     @return {Ember.Array} receiver with the new content
7931    */
7932   setObjects: function(objects) {
7933     if (objects.length === 0) return this.clear();
7934
7935     var len = get(this, 'length');
7936     this.replace(0, len, objects);
7937     return this;
7938   },
7939
7940   // ..........................................................
7941   // IMPLEMENT Ember.MutableEnumerable
7942   //
7943
7944   removeObject: function(obj) {
7945     var loc = get(this, 'length') || 0;
7946     while(--loc >= 0) {
7947       var curObject = this.objectAt(loc) ;
7948       if (curObject === obj) this.removeAt(loc) ;
7949     }
7950     return this ;
7951   },
7952
7953   addObject: function(obj) {
7954     if (!this.contains(obj)) this.pushObject(obj);
7955     return this ;
7956   }
7957
7958 });
7959
7960
7961 })();
7962
7963
7964
7965 (function() {
7966 /**
7967 @module ember
7968 @submodule ember-runtime
7969 */
7970
7971 var get = Ember.get, set = Ember.set, defineProperty = Ember.defineProperty;
7972
7973 /**
7974   ## Overview
7975
7976   This mixin provides properties and property observing functionality, core
7977   features of the Ember object model.
7978
7979   Properties and observers allow one object to observe changes to a
7980   property on another object. This is one of the fundamental ways that
7981   models, controllers and views communicate with each other in an Ember
7982   application.
7983
7984   Any object that has this mixin applied can be used in observer
7985   operations. That includes Ember.Object and most objects you will
7986   interact with as you write your Ember application.
7987
7988   Note that you will not generally apply this mixin to classes yourself,
7989   but you will use the features provided by this module frequently, so it
7990   is important to understand how to use it.
7991
7992   ## Using get() and set()
7993
7994   Because of Ember's support for bindings and observers, you will always
7995   access properties using the get method, and set properties using the
7996   set method. This allows the observing objects to be notified and
7997   computed properties to be handled properly.
7998
7999   More documentation about `get` and `set` are below.
8000
8001   ## Observing Property Changes
8002
8003   You typically observe property changes simply by adding the `observes`
8004   call to the end of your method declarations in classes that you write.
8005   For example:
8006
8007       Ember.Object.create({
8008         valueObserver: function() {
8009           // Executes whenever the "value" property changes
8010         }.observes('value')
8011       });
8012
8013   Although this is the most common way to add an observer, this capability
8014   is actually built into the Ember.Object class on top of two methods
8015   defined in this mixin: `addObserver` and `removeObserver`. You can use
8016   these two methods to add and remove observers yourself if you need to
8017   do so at runtime.
8018
8019   To add an observer for a property, call:
8020
8021       object.addObserver('propertyKey', targetObject, targetAction)
8022
8023   This will call the `targetAction` method on the `targetObject` to be called
8024   whenever the value of the `propertyKey` changes.
8025
8026   Note that if `propertyKey` is a computed property, the observer will be
8027   called when any of the property dependencies are changed, even if the
8028   resulting value of the computed property is unchanged. This is necessary
8029   because computed properties are not computed until `get` is called.
8030
8031   @class Observable
8032   @namespace Ember
8033   @extends Ember.Mixin
8034 */
8035 Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ {
8036
8037   // compatibility
8038   isObserverable: true,
8039
8040   /**
8041     Retrieves the value of a property from the object.
8042
8043     This method is usually similar to using object[keyName] or object.keyName,
8044     however it supports both computed properties and the unknownProperty
8045     handler.
8046
8047     Because `get` unifies the syntax for accessing all these kinds
8048     of properties, it can make many refactorings easier, such as replacing a
8049     simple property with a computed property, or vice versa.
8050
8051     ### Computed Properties
8052
8053     Computed properties are methods defined with the `property` modifier
8054     declared at the end, such as:
8055
8056           fullName: function() {
8057             return this.getEach('firstName', 'lastName').compact().join(' ');
8058           }.property('firstName', 'lastName')
8059
8060     When you call `get` on a computed property, the function will be
8061     called and the return value will be returned instead of the function
8062     itself.
8063
8064     ### Unknown Properties
8065
8066     Likewise, if you try to call `get` on a property whose value is
8067     undefined, the unknownProperty() method will be called on the object.
8068     If this method returns any value other than undefined, it will be returned
8069     instead. This allows you to implement "virtual" properties that are
8070     not defined upfront.
8071
8072     @method get
8073     @param {String} key The property to retrieve
8074     @return {Object} The property value or undefined.
8075   */
8076   get: function(keyName) {
8077     return get(this, keyName);
8078   },
8079
8080   /**
8081     To get multiple properties at once, call getProperties
8082     with a list of strings or an array:
8083
8084           record.getProperties('firstName', 'lastName', 'zipCode'); // => { firstName: 'John', lastName: 'Doe', zipCode: '10011' }
8085
8086    is equivalent to:
8087
8088           record.getProperties(['firstName', 'lastName', 'zipCode']); // => { firstName: 'John', lastName: 'Doe', zipCode: '10011' }
8089
8090     @method getProperties
8091     @param {String...|Array} list of keys to get
8092     @return {Hash}
8093   */
8094   getProperties: function() {
8095     var ret = {};
8096     var propertyNames = arguments;
8097     if (arguments.length === 1 && Ember.typeOf(arguments[0]) === 'array') {
8098       propertyNames = arguments[0];
8099     }
8100     for(var i = 0; i < propertyNames.length; i++) {
8101       ret[propertyNames[i]] = get(this, propertyNames[i]);
8102     }
8103     return ret;
8104   },
8105
8106   /**
8107     Sets the provided key or path to the value.
8108
8109     This method is generally very similar to calling object[key] = value or
8110     object.key = value, except that it provides support for computed
8111     properties, the unknownProperty() method and property observers.
8112
8113     ### Computed Properties
8114
8115     If you try to set a value on a key that has a computed property handler
8116     defined (see the get() method for an example), then set() will call
8117     that method, passing both the value and key instead of simply changing
8118     the value itself. This is useful for those times when you need to
8119     implement a property that is composed of one or more member
8120     properties.
8121
8122     ### Unknown Properties
8123
8124     If you try to set a value on a key that is undefined in the target
8125     object, then the unknownProperty() handler will be called instead. This
8126     gives you an opportunity to implement complex "virtual" properties that
8127     are not predefined on the object. If unknownProperty() returns
8128     undefined, then set() will simply set the value on the object.
8129
8130     ### Property Observers
8131
8132     In addition to changing the property, set() will also register a
8133     property change with the object. Unless you have placed this call
8134     inside of a beginPropertyChanges() and endPropertyChanges(), any "local"
8135     observers (i.e. observer methods declared on the same object), will be
8136     called immediately. Any "remote" observers (i.e. observer methods
8137     declared on another object) will be placed in a queue and called at a
8138     later time in a coalesced manner.
8139
8140     ### Chaining
8141
8142     In addition to property changes, set() returns the value of the object
8143     itself so you can do chaining like this:
8144
8145           record.set('firstName', 'Charles').set('lastName', 'Jolley');
8146
8147     @method set
8148     @param {String} key The property to set
8149     @param {Object} value The value to set or null.
8150     @return {Ember.Observable}
8151   */
8152   set: function(keyName, value) {
8153     set(this, keyName, value);
8154     return this;
8155   },
8156
8157   /**
8158     To set multiple properties at once, call setProperties
8159     with a Hash:
8160
8161           record.setProperties({ firstName: 'Charles', lastName: 'Jolley' });
8162
8163     @method setProperties
8164     @param {Hash} hash the hash of keys and values to set
8165     @return {Ember.Observable}
8166   */
8167   setProperties: function(hash) {
8168     return Ember.setProperties(this, hash);
8169   },
8170
8171   /**
8172     Begins a grouping of property changes.
8173
8174     You can use this method to group property changes so that notifications
8175     will not be sent until the changes are finished. If you plan to make a
8176     large number of changes to an object at one time, you should call this
8177     method at the beginning of the changes to begin deferring change
8178     notifications. When you are done making changes, call endPropertyChanges()
8179     to deliver the deferred change notifications and end deferring.
8180
8181     @method beginPropertyChanges
8182     @return {Ember.Observable}
8183   */
8184   beginPropertyChanges: function() {
8185     Ember.beginPropertyChanges();
8186     return this;
8187   },
8188
8189   /**
8190     Ends a grouping of property changes.
8191
8192     You can use this method to group property changes so that notifications
8193     will not be sent until the changes are finished. If you plan to make a
8194     large number of changes to an object at one time, you should call
8195     beginPropertyChanges() at the beginning of the changes to defer change
8196     notifications. When you are done making changes, call this method to
8197     deliver the deferred change notifications and end deferring.
8198
8199     @method endPropertyChanges
8200     @return {Ember.Observable}
8201   */
8202   endPropertyChanges: function() {
8203     Ember.endPropertyChanges();
8204     return this;
8205   },
8206
8207   /**
8208     Notify the observer system that a property is about to change.
8209
8210     Sometimes you need to change a value directly or indirectly without
8211     actually calling get() or set() on it. In this case, you can use this
8212     method and propertyDidChange() instead. Calling these two methods
8213     together will notify all observers that the property has potentially
8214     changed value.
8215
8216     Note that you must always call propertyWillChange and propertyDidChange as
8217     a pair. If you do not, it may get the property change groups out of order
8218     and cause notifications to be delivered more often than you would like.
8219
8220     @method propertyWillChange
8221     @param {String} key The property key that is about to change.
8222     @return {Ember.Observable}
8223   */
8224   propertyWillChange: function(keyName){
8225     Ember.propertyWillChange(this, keyName);
8226     return this;
8227   },
8228
8229   /**
8230     Notify the observer system that a property has just changed.
8231
8232     Sometimes you need to change a value directly or indirectly without
8233     actually calling get() or set() on it. In this case, you can use this
8234     method and propertyWillChange() instead. Calling these two methods
8235     together will notify all observers that the property has potentially
8236     changed value.
8237
8238     Note that you must always call propertyWillChange and propertyDidChange as
8239     a pair. If you do not, it may get the property change groups out of order
8240     and cause notifications to be delivered more often than you would like.
8241
8242     @method propertyDidChange
8243     @param {String} keyName The property key that has just changed.
8244     @return {Ember.Observable}
8245   */
8246   propertyDidChange: function(keyName) {
8247     Ember.propertyDidChange(this, keyName);
8248     return this;
8249   },
8250
8251   /**
8252     Convenience method to call `propertyWillChange` and `propertyDidChange` in
8253     succession.
8254
8255     @method notifyPropertyChange
8256     @param {String} keyName The property key to be notified about.
8257     @return {Ember.Observable}
8258   */
8259   notifyPropertyChange: function(keyName) {
8260     this.propertyWillChange(keyName);
8261     this.propertyDidChange(keyName);
8262     return this;
8263   },
8264
8265   addBeforeObserver: function(key, target, method) {
8266     Ember.addBeforeObserver(this, key, target, method);
8267   },
8268
8269   /**
8270     Adds an observer on a property.
8271
8272     This is the core method used to register an observer for a property.
8273
8274     Once you call this method, anytime the key's value is set, your observer
8275     will be notified. Note that the observers are triggered anytime the
8276     value is set, regardless of whether it has actually changed. Your
8277     observer should be prepared to handle that.
8278
8279     You can also pass an optional context parameter to this method. The
8280     context will be passed to your observer method whenever it is triggered.
8281     Note that if you add the same target/method pair on a key multiple times
8282     with different context parameters, your observer will only be called once
8283     with the last context you passed.
8284
8285     ### Observer Methods
8286
8287     Observer methods you pass should generally have the following signature if
8288     you do not pass a "context" parameter:
8289
8290           fooDidChange: function(sender, key, value, rev);
8291
8292     The sender is the object that changed. The key is the property that
8293     changes. The value property is currently reserved and unused. The rev
8294     is the last property revision of the object when it changed, which you can
8295     use to detect if the key value has really changed or not.
8296
8297     If you pass a "context" parameter, the context will be passed before the
8298     revision like so:
8299
8300           fooDidChange: function(sender, key, value, context, rev);
8301
8302     Usually you will not need the value, context or revision parameters at
8303     the end. In this case, it is common to write observer methods that take
8304     only a sender and key value as parameters or, if you aren't interested in
8305     any of these values, to write an observer that has no parameters at all.
8306
8307     @method addObserver
8308     @param {String} key The key to observer
8309     @param {Object} target The target object to invoke
8310     @param {String|Function} method The method to invoke.
8311     @return {Ember.Object} self
8312   */
8313   addObserver: function(key, target, method) {
8314     Ember.addObserver(this, key, target, method);
8315   },
8316
8317   /**
8318     Remove an observer you have previously registered on this object. Pass
8319     the same key, target, and method you passed to addObserver() and your
8320     target will no longer receive notifications.
8321
8322     @method removeObserver
8323     @param {String} key The key to observer
8324     @param {Object} target The target object to invoke
8325     @param {String|Function} method The method to invoke.
8326     @return {Ember.Observable} receiver
8327   */
8328   removeObserver: function(key, target, method) {
8329     Ember.removeObserver(this, key, target, method);
8330   },
8331
8332   /**
8333     Returns true if the object currently has observers registered for a
8334     particular key. You can use this method to potentially defer performing
8335     an expensive action until someone begins observing a particular property
8336     on the object.
8337
8338     @method hasObserverFor
8339     @param {String} key Key to check
8340     @return {Boolean}
8341   */
8342   hasObserverFor: function(key) {
8343     return Ember.hasListeners(this, key+':change');
8344   },
8345
8346   /**
8347     This method will be called when a client attempts to get the value of a
8348     property that has not been defined in one of the typical ways. Override
8349     this method to create "virtual" properties.
8350
8351     @method unknownProperty
8352     @param {String} key The name of the unknown property that was requested.
8353     @return {Object} The property value or undefined. Default is undefined.
8354   */
8355   unknownProperty: function(key) {
8356     return undefined;
8357   },
8358
8359   /**
8360     This method will be called when a client attempts to set the value of a
8361     property that has not been defined in one of the typical ways. Override
8362     this method to create "virtual" properties.
8363
8364     @method setUnknownProperty
8365     @param {String} key The name of the unknown property to be set.
8366     @param {Object} value The value the unknown property is to be set to.
8367   */
8368   setUnknownProperty: function(key, value) {
8369     defineProperty(this, key);
8370     set(this, key, value);
8371   },
8372
8373   /**
8374     @deprecated
8375     @method getPath
8376     @param {String} path The property path to retrieve
8377     @return {Object} The property value or undefined.
8378   */
8379   getPath: function(path) {
8380     Ember.deprecate("getPath is deprecated since get now supports paths");
8381     return this.get(path);
8382   },
8383
8384   /**
8385     @deprecated
8386     @method setPath
8387     @param {String} path The path to the property that will be set
8388     @param {Object} value The value to set or null.
8389     @return {Ember.Observable}
8390   */
8391   setPath: function(path, value) {
8392     Ember.deprecate("setPath is deprecated since set now supports paths");
8393     return this.set(path, value);
8394   },
8395
8396   /**
8397     Retrieves the value of a property, or a default value in the case that the property
8398     returns undefined.
8399
8400         person.getWithDefault('lastName', 'Doe');
8401
8402     @method getWithDefault
8403     @param {String} keyName The name of the property to retrieve
8404     @param {Object} defaultValue The value to return if the property value is undefined
8405     @return {Object} The property value or the defaultValue.
8406   */
8407   getWithDefault: function(keyName, defaultValue) {
8408     return Ember.getWithDefault(this, keyName, defaultValue);
8409   },
8410
8411   /**
8412     Set the value of a property to the current value plus some amount.
8413
8414         person.incrementProperty('age');
8415         team.incrementProperty('score', 2);
8416
8417     @method incrementProperty
8418     @param {String} keyName The name of the property to increment
8419     @param {Object} increment The amount to increment by. Defaults to 1
8420     @return {Object} The new property value
8421   */
8422   incrementProperty: function(keyName, increment) {
8423     if (!increment) { increment = 1; }
8424     set(this, keyName, (get(this, keyName) || 0)+increment);
8425     return get(this, keyName);
8426   },
8427
8428   /**
8429     Set the value of a property to the current value minus some amount.
8430
8431         player.decrementProperty('lives');
8432         orc.decrementProperty('health', 5);
8433
8434     @method decrementProperty
8435     @param {String} keyName The name of the property to decrement
8436     @param {Object} increment The amount to decrement by. Defaults to 1
8437     @return {Object} The new property value
8438   */
8439   decrementProperty: function(keyName, increment) {
8440     if (!increment) { increment = 1; }
8441     set(this, keyName, (get(this, keyName) || 0)-increment);
8442     return get(this, keyName);
8443   },
8444
8445   /**
8446     Set the value of a boolean property to the opposite of it's
8447     current value.
8448
8449         starship.toggleProperty('warpDriveEnaged');
8450
8451     @method toggleProperty
8452     @param {String} keyName The name of the property to toggle
8453     @return {Object} The new property value
8454   */
8455   toggleProperty: function(keyName) {
8456     set(this, keyName, !get(this, keyName));
8457     return get(this, keyName);
8458   },
8459
8460   /**
8461     Returns the cached value of a computed property, if it exists.
8462     This allows you to inspect the value of a computed property
8463     without accidentally invoking it if it is intended to be
8464     generated lazily.
8465
8466     @method cacheFor
8467     @param {String} keyName
8468     @return {Object} The cached value of the computed property, if any
8469   */
8470   cacheFor: function(keyName) {
8471     return Ember.cacheFor(this, keyName);
8472   },
8473
8474   // intended for debugging purposes
8475   observersForKey: function(keyName) {
8476     return Ember.observersFor(this, keyName);
8477   }
8478 });
8479
8480
8481 })();
8482
8483
8484
8485 (function() {
8486 /**
8487 @module ember
8488 @submodule ember-runtime
8489 */
8490
8491 var get = Ember.get, set = Ember.set;
8492
8493 /**
8494 @class TargetActionSupport
8495 @namespace Ember
8496 @extends Ember.Mixin
8497 */
8498 Ember.TargetActionSupport = Ember.Mixin.create({
8499   target: null,
8500   action: null,
8501
8502   targetObject: Ember.computed(function() {
8503     var target = get(this, 'target');
8504
8505     if (Ember.typeOf(target) === "string") {
8506       var value = get(this, target);
8507       if (value === undefined) { value = get(window, target); }
8508       return value;
8509     } else {
8510       return target;
8511     }
8512   }).property('target').cacheable(),
8513
8514   triggerAction: function() {
8515     var action = get(this, 'action'),
8516         target = get(this, 'targetObject');
8517
8518     if (target && action) {
8519       var ret;
8520
8521       if (typeof target.send === 'function') {
8522         ret = target.send(action, this);
8523       } else {
8524         if (typeof action === 'string') {
8525           action = target[action];
8526         }
8527         ret = action.call(target, this);
8528       }
8529       if (ret !== false) ret = true;
8530
8531       return ret;
8532     } else {
8533       return false;
8534     }
8535   }
8536 });
8537
8538 })();
8539
8540
8541
8542 (function() {
8543 /**
8544 @module ember
8545 @submodule ember-runtime
8546 */
8547
8548 /**
8549   @class Evented
8550   @namespace Ember
8551   @extends Ember.Mixin
8552  */
8553 Ember.Evented = Ember.Mixin.create({
8554   on: function(name, target, method) {
8555     Ember.addListener(this, name, target, method);
8556   },
8557
8558   one: function(name, target, method) {
8559     if (!method) {
8560       method = target;
8561       target = null;
8562     }
8563
8564     var self = this;
8565     var wrapped = function() {
8566       Ember.removeListener(self, name, target, wrapped);
8567
8568       if ('string' === typeof method) { method = this[method]; }
8569
8570       // Internally, a `null` target means that the target is
8571       // the first parameter to addListener. That means that
8572       // the `this` passed into this function is the target
8573       // determined by the event system.
8574       method.apply(this, arguments);
8575     };
8576
8577     this.on(name, target, wrapped);
8578   },
8579
8580   trigger: function(name) {
8581     var args = [], i, l;
8582     for (i = 1, l = arguments.length; i < l; i++) {
8583       args.push(arguments[i]);
8584     }
8585     Ember.sendEvent(this, name, args);
8586   },
8587
8588   fire: function(name) {
8589     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.");
8590     this.trigger.apply(this, arguments);
8591   },
8592
8593   off: function(name, target, method) {
8594     Ember.removeListener(this, name, target, method);
8595   },
8596
8597   has: function(name) {
8598     return Ember.hasListeners(this, name);
8599   }
8600 });
8601
8602 })();
8603
8604
8605
8606 (function() {
8607
8608 })();
8609
8610
8611
8612 (function() {
8613 /**
8614 @module ember
8615 @submodule ember-runtime
8616 */
8617
8618
8619 // NOTE: this object should never be included directly.  Instead use Ember.
8620 // Ember.Object.  We only define this separately so that Ember.Set can depend on it
8621
8622
8623 var set = Ember.set, get = Ember.get,
8624     o_create = Ember.create,
8625     o_defineProperty = Ember.platform.defineProperty,
8626     a_slice = Array.prototype.slice,
8627     GUID_KEY = Ember.GUID_KEY,
8628     guidFor = Ember.guidFor,
8629     generateGuid = Ember.generateGuid,
8630     meta = Ember.meta,
8631     rewatch = Ember.rewatch,
8632     finishChains = Ember.finishChains,
8633     destroy = Ember.destroy,
8634     schedule = Ember.run.schedule,
8635     Mixin = Ember.Mixin,
8636     applyMixin = Mixin._apply,
8637     finishPartial = Mixin.finishPartial,
8638     reopen = Mixin.prototype.reopen,
8639     classToString = Mixin.prototype.toString;
8640
8641 var undefinedDescriptor = {
8642   configurable: true,
8643   writable: true,
8644   enumerable: false,
8645   value: undefined
8646 };
8647
8648 function makeCtor() {
8649
8650   // Note: avoid accessing any properties on the object since it makes the
8651   // method a lot faster.  This is glue code so we want it to be as fast as
8652   // possible.
8653
8654   var wasApplied = false, initMixins;
8655
8656   var Class = function() {
8657     if (!wasApplied) {
8658       Class.proto(); // prepare prototype...
8659     }
8660     o_defineProperty(this, GUID_KEY, undefinedDescriptor);
8661     o_defineProperty(this, '_super', undefinedDescriptor);
8662     var m = meta(this);
8663     m.proto = this;
8664     if (initMixins) {
8665       this.reopen.apply(this, initMixins);
8666       initMixins = null;
8667     }
8668     finishPartial(this, m);
8669     delete m.proto;
8670     finishChains(this);
8671     this.init.apply(this, arguments);
8672   };
8673
8674   Class.toString = classToString;
8675   Class.willReopen = function() {
8676     if (wasApplied) {
8677       Class.PrototypeMixin = Mixin.create(Class.PrototypeMixin);
8678     }
8679
8680     wasApplied = false;
8681   };
8682   Class._initMixins = function(args) { initMixins = args; };
8683
8684   Class.proto = function() {
8685     var superclass = Class.superclass;
8686     if (superclass) { superclass.proto(); }
8687
8688     if (!wasApplied) {
8689       wasApplied = true;
8690       Class.PrototypeMixin.applyPartial(Class.prototype);
8691       rewatch(Class.prototype);
8692     }
8693
8694     return this.prototype;
8695   };
8696
8697   return Class;
8698
8699 }
8700
8701 var CoreObject = makeCtor();
8702
8703 CoreObject.PrototypeMixin = Mixin.create({
8704
8705   reopen: function() {
8706     applyMixin(this, arguments, true);
8707     return this;
8708   },
8709
8710   isInstance: true,
8711
8712   init: function() {},
8713
8714   /**
8715     @property isDestroyed
8716     @default false
8717   */
8718   isDestroyed: false,
8719
8720   /**
8721     @property isDestroying
8722     @default false
8723   */
8724   isDestroying: false,
8725
8726   /**
8727     Destroys an object by setting the isDestroyed flag and removing its
8728     metadata, which effectively destroys observers and bindings.
8729
8730     If you try to set a property on a destroyed object, an exception will be
8731     raised.
8732
8733     Note that destruction is scheduled for the end of the run loop and does not
8734     happen immediately.
8735
8736     @method destroy
8737     @return {Ember.Object} receiver
8738   */
8739   destroy: function() {
8740     if (this.isDestroying) { return; }
8741
8742     this.isDestroying = true;
8743
8744     if (this.willDestroy) { this.willDestroy(); }
8745
8746     set(this, 'isDestroyed', true);
8747     schedule('destroy', this, this._scheduledDestroy);
8748     return this;
8749   },
8750
8751   /**
8752     @private
8753
8754     Invoked by the run loop to actually destroy the object. This is
8755     scheduled for execution by the `destroy` method.
8756
8757     @method _scheduledDestroy
8758   */
8759   _scheduledDestroy: function() {
8760     destroy(this);
8761     if (this.didDestroy) { this.didDestroy(); }
8762   },
8763
8764   bind: function(to, from) {
8765     if (!(from instanceof Ember.Binding)) { from = Ember.Binding.from(from); }
8766     from.to(to).connect(this);
8767     return from;
8768   },
8769
8770   toString: function() {
8771     return '<'+this.constructor.toString()+':'+guidFor(this)+'>';
8772   }
8773 });
8774
8775 if (Ember.config.overridePrototypeMixin) {
8776   Ember.config.overridePrototypeMixin(CoreObject.PrototypeMixin);
8777 }
8778
8779 CoreObject.__super__ = null;
8780
8781 var ClassMixin = Mixin.create({
8782
8783   ClassMixin: Ember.required(),
8784
8785   PrototypeMixin: Ember.required(),
8786
8787   isClass: true,
8788
8789   isMethod: false,
8790
8791   extend: function() {
8792     var Class = makeCtor(), proto;
8793     Class.ClassMixin = Mixin.create(this.ClassMixin);
8794     Class.PrototypeMixin = Mixin.create(this.PrototypeMixin);
8795
8796     Class.ClassMixin.ownerConstructor = Class;
8797     Class.PrototypeMixin.ownerConstructor = Class;
8798
8799     reopen.apply(Class.PrototypeMixin, arguments);
8800
8801     Class.superclass = this;
8802     Class.__super__  = this.prototype;
8803
8804     proto = Class.prototype = o_create(this.prototype);
8805     proto.constructor = Class;
8806     generateGuid(proto, 'ember');
8807     meta(proto).proto = proto; // this will disable observers on prototype
8808
8809     Class.ClassMixin.apply(Class);
8810     return Class;
8811   },
8812
8813   create: function() {
8814     var C = this;
8815     if (arguments.length>0) { this._initMixins(arguments); }
8816     return new C();
8817   },
8818
8819   reopen: function() {
8820     this.willReopen();
8821     reopen.apply(this.PrototypeMixin, arguments);
8822     return this;
8823   },
8824
8825   reopenClass: function() {
8826     reopen.apply(this.ClassMixin, arguments);
8827     applyMixin(this, arguments, false);
8828     return this;
8829   },
8830
8831   detect: function(obj) {
8832     if ('function' !== typeof obj) { return false; }
8833     while(obj) {
8834       if (obj===this) { return true; }
8835       obj = obj.superclass;
8836     }
8837     return false;
8838   },
8839
8840   detectInstance: function(obj) {
8841     return obj instanceof this;
8842   },
8843
8844   /**
8845     In some cases, you may want to annotate computed properties with additional
8846     metadata about how they function or what values they operate on. For example,
8847     computed property functions may close over variables that are then no longer
8848     available for introspection.
8849
8850     You can pass a hash of these values to a computed property like this:
8851
8852         person: function() {
8853           var personId = this.get('personId');
8854           return App.Person.create({ id: personId });
8855         }.property().meta({ type: App.Person })
8856
8857     Once you've done this, you can retrieve the values saved to the computed
8858     property from your class like this:
8859
8860         MyClass.metaForProperty('person');
8861
8862     This will return the original hash that was passed to `meta()`.
8863
8864     @method metaForProperty
8865     @param key {String} property name
8866   */
8867   metaForProperty: function(key) {
8868     var desc = meta(this.proto(), false).descs[key];
8869
8870     Ember.assert("metaForProperty() could not find a computed property with key '"+key+"'.", !!desc && desc instanceof Ember.ComputedProperty);
8871     return desc._meta || {};
8872   },
8873
8874   /**
8875     Iterate over each computed property for the class, passing its name
8876     and any associated metadata (see `metaForProperty`) to the callback.
8877
8878     @method eachComputedProperty
8879     @param {Function} callback
8880     @param {Object} binding
8881   */
8882   eachComputedProperty: function(callback, binding) {
8883     var proto = this.proto(),
8884         descs = meta(proto).descs,
8885         empty = {},
8886         property;
8887
8888     for (var name in descs) {
8889       property = descs[name];
8890
8891       if (property instanceof Ember.ComputedProperty) {
8892         callback.call(binding || this, name, property._meta || empty);
8893       }
8894     }
8895   }
8896
8897 });
8898
8899 if (Ember.config.overrideClassMixin) {
8900   Ember.config.overrideClassMixin(ClassMixin);
8901 }
8902
8903 CoreObject.ClassMixin = ClassMixin;
8904 ClassMixin.apply(CoreObject);
8905
8906 /**
8907   @class CoreObject
8908   @namespace Ember
8909 */
8910 Ember.CoreObject = CoreObject;
8911
8912
8913
8914
8915 })();
8916
8917
8918
8919 (function() {
8920 /**
8921 @module ember
8922 @submodule ember-runtime
8923 */
8924
8925 var get = Ember.get, set = Ember.set, guidFor = Ember.guidFor, none = Ember.none;
8926
8927 /**
8928   An unordered collection of objects.
8929
8930   A Set works a bit like an array except that its items are not ordered.
8931   You can create a set to efficiently test for membership for an object. You
8932   can also iterate through a set just like an array, even accessing objects
8933   by index, however there is no guarantee as to their order.
8934
8935   All Sets are observable via the Enumerable Observer API - which works
8936   on any enumerable object including both Sets and Arrays.
8937
8938   ## Creating a Set
8939
8940   You can create a set like you would most objects using
8941   `new Ember.Set()`.  Most new sets you create will be empty, but you can
8942   also initialize the set with some content by passing an array or other
8943   enumerable of objects to the constructor.
8944
8945   Finally, you can pass in an existing set and the set will be copied. You
8946   can also create a copy of a set by calling `Ember.Set#copy()`.
8947
8948       #js
8949       // creates a new empty set
8950       var foundNames = new Ember.Set();
8951
8952       // creates a set with four names in it.
8953       var names = new Ember.Set(["Charles", "Tom", "Juan", "Alex"]); // :P
8954
8955       // creates a copy of the names set.
8956       var namesCopy = new Ember.Set(names);
8957
8958       // same as above.
8959       var anotherNamesCopy = names.copy();
8960
8961   ## Adding/Removing Objects
8962
8963   You generally add or remove objects from a set using `add()` or
8964   `remove()`. You can add any type of object including primitives such as
8965   numbers, strings, and booleans.
8966
8967   Unlike arrays, objects can only exist one time in a set. If you call `add()`
8968   on a set with the same object multiple times, the object will only be added
8969   once. Likewise, calling `remove()` with the same object multiple times will
8970   remove the object the first time and have no effect on future calls until
8971   you add the object to the set again.
8972
8973   NOTE: You cannot add/remove null or undefined to a set. Any attempt to do so
8974   will be ignored.
8975
8976   In addition to add/remove you can also call `push()`/`pop()`. Push behaves
8977   just like `add()` but `pop()`, unlike `remove()` will pick an arbitrary
8978   object, remove it and return it. This is a good way to use a set as a job
8979   queue when you don't care which order the jobs are executed in.
8980
8981   ## Testing for an Object
8982
8983   To test for an object's presence in a set you simply call
8984   `Ember.Set#contains()`.
8985
8986   ## Observing changes
8987
8988   When using `Ember.Set`, you can observe the `"[]"` property to be
8989   alerted whenever the content changes.  You can also add an enumerable
8990   observer to the set to be notified of specific objects that are added and
8991   removed from the set.  See `Ember.Enumerable` for more information on
8992   enumerables.
8993
8994   This is often unhelpful. If you are filtering sets of objects, for instance,
8995   it is very inefficient to re-filter all of the items each time the set
8996   changes. It would be better if you could just adjust the filtered set based
8997   on what was changed on the original set. The same issue applies to merging
8998   sets, as well.
8999
9000   ## Other Methods
9001
9002   `Ember.Set` primary implements other mixin APIs.  For a complete reference
9003   on the methods you will use with `Ember.Set`, please consult these mixins.
9004   The most useful ones will be `Ember.Enumerable` and
9005   `Ember.MutableEnumerable` which implement most of the common iterator
9006   methods you are used to on Array.
9007
9008   Note that you can also use the `Ember.Copyable` and `Ember.Freezable`
9009   APIs on `Ember.Set` as well.  Once a set is frozen it can no longer be
9010   modified.  The benefit of this is that when you call frozenCopy() on it,
9011   Ember will avoid making copies of the set.  This allows you to write
9012   code that can know with certainty when the underlying set data will or
9013   will not be modified.
9014
9015   @class Set
9016   @namespace Ember
9017   @extends Ember.CoreObject
9018   @uses Ember.MutableEnumerable
9019   @uses Ember.Copyable
9020   @uses Ember.Freezable
9021   @since Ember 0.9
9022 */
9023 Ember.Set = Ember.CoreObject.extend(Ember.MutableEnumerable, Ember.Copyable, Ember.Freezable,
9024   /** @scope Ember.Set.prototype */ {
9025
9026   // ..........................................................
9027   // IMPLEMENT ENUMERABLE APIS
9028   //
9029
9030   /**
9031     This property will change as the number of objects in the set changes.
9032
9033     @property length
9034     @type number
9035     @default 0
9036   */
9037   length: 0,
9038
9039   /**
9040     Clears the set. This is useful if you want to reuse an existing set
9041     without having to recreate it.
9042
9043         var colors = new Ember.Set(["red", "green", "blue"]);
9044         colors.length;  => 3
9045         colors.clear();
9046         colors.length;  => 0
9047
9048     @method clear
9049     @return {Ember.Set} An empty Set
9050   */
9051   clear: function() {
9052     if (this.isFrozen) { throw new Error(Ember.FROZEN_ERROR); }
9053
9054     var len = get(this, 'length');
9055     if (len === 0) { return this; }
9056
9057     var guid;
9058
9059     this.enumerableContentWillChange(len, 0);
9060     Ember.propertyWillChange(this, 'firstObject');
9061     Ember.propertyWillChange(this, 'lastObject');
9062
9063     for (var i=0; i < len; i++){
9064       guid = guidFor(this[i]);
9065       delete this[guid];
9066       delete this[i];
9067     }
9068
9069     set(this, 'length', 0);
9070
9071     Ember.propertyDidChange(this, 'firstObject');
9072     Ember.propertyDidChange(this, 'lastObject');
9073     this.enumerableContentDidChange(len, 0);
9074
9075     return this;
9076   },
9077
9078   /**
9079     Returns true if the passed object is also an enumerable that contains the
9080     same objects as the receiver.
9081
9082         var colors = ["red", "green", "blue"],
9083             same_colors = new Ember.Set(colors);
9084         same_colors.isEqual(colors); => true
9085         same_colors.isEqual(["purple", "brown"]); => false
9086
9087     @method isEqual
9088     @param {Ember.Set} obj the other object.
9089     @return {Boolean}
9090   */
9091   isEqual: function(obj) {
9092     // fail fast
9093     if (!Ember.Enumerable.detect(obj)) return false;
9094
9095     var loc = get(this, 'length');
9096     if (get(obj, 'length') !== loc) return false;
9097
9098     while(--loc >= 0) {
9099       if (!obj.contains(this[loc])) return false;
9100     }
9101
9102     return true;
9103   },
9104
9105   /**
9106     Adds an object to the set. Only non-null objects can be added to a set
9107     and those can only be added once. If the object is already in the set or
9108     the passed value is null this method will have no effect.
9109
9110     This is an alias for `Ember.MutableEnumerable.addObject()`.
9111
9112         var colors = new Ember.Set();
9113         colors.add("blue");    => ["blue"]
9114         colors.add("blue");    => ["blue"]
9115         colors.add("red");     => ["blue", "red"]
9116         colors.add(null);      => ["blue", "red"]
9117         colors.add(undefined); => ["blue", "red"]
9118
9119     @method add
9120     @param {Object} obj The object to add.
9121     @return {Ember.Set} The set itself.
9122   */
9123   add: Ember.alias('addObject'),
9124
9125   /**
9126     Removes the object from the set if it is found.  If you pass a null value
9127     or an object that is already not in the set, this method will have no
9128     effect. This is an alias for `Ember.MutableEnumerable.removeObject()`.
9129
9130         var colors = new Ember.Set(["red", "green", "blue"]);
9131         colors.remove("red");    => ["blue", "green"]
9132         colors.remove("purple"); => ["blue", "green"]
9133         colors.remove(null);     => ["blue", "green"]
9134
9135     @method remove
9136     @param {Object} obj The object to remove
9137     @return {Ember.Set} The set itself.
9138   */
9139   remove: Ember.alias('removeObject'),
9140
9141   /**
9142     Removes the last element from the set and returns it, or null if it's empty.
9143
9144         var colors = new Ember.Set(["green", "blue"]);
9145         colors.pop(); => "blue"
9146         colors.pop(); => "green"
9147         colors.pop(); => null
9148
9149     @method pop
9150     @return {Object} The removed object from the set or null.
9151   */
9152   pop: function() {
9153     if (get(this, 'isFrozen')) throw new Error(Ember.FROZEN_ERROR);
9154     var obj = this.length > 0 ? this[this.length-1] : null;
9155     this.remove(obj);
9156     return obj;
9157   },
9158
9159   /**
9160     Inserts the given object on to the end of the set. It returns
9161     the set itself.
9162
9163     This is an alias for `Ember.MutableEnumerable.addObject()`.
9164
9165         var colors = new Ember.Set();
9166         colors.push("red");   => ["red"]
9167         colors.push("green"); => ["red", "green"]
9168         colors.push("blue");  => ["red", "green", "blue"]
9169
9170     @method push
9171     @return {Ember.Set} The set itself.
9172   */
9173   push: Ember.alias('addObject'),
9174
9175   /**
9176     Removes the last element from the set and returns it, or null if it's empty.
9177
9178     This is an alias for `Ember.Set.pop()`.
9179
9180         var colors = new Ember.Set(["green", "blue"]);
9181         colors.shift(); => "blue"
9182         colors.shift(); => "green"
9183         colors.shift(); => null
9184
9185     @method shift
9186     @return {Object} The removed object from the set or null.
9187   */
9188   shift: Ember.alias('pop'),
9189
9190   /**
9191     Inserts the given object on to the end of the set. It returns
9192     the set itself.
9193
9194     This is an alias of `Ember.Set.push()`
9195
9196         var colors = new Ember.Set();
9197         colors.unshift("red");   => ["red"]
9198         colors.unshift("green"); => ["red", "green"]
9199         colors.unshift("blue");  => ["red", "green", "blue"]
9200
9201     @method unshift
9202     @return {Ember.Set} The set itself.
9203   */
9204   unshift: Ember.alias('push'),
9205
9206   /**
9207     Adds each object in the passed enumerable to the set.
9208
9209     This is an alias of `Ember.MutableEnumerable.addObjects()`
9210
9211         var colors = new Ember.Set();
9212         colors.addEach(["red", "green", "blue"]); => ["red", "green", "blue"]
9213
9214     @method addEach
9215     @param {Ember.Enumerable} objects the objects to add.
9216     @return {Ember.Set} The set itself.
9217   */
9218   addEach: Ember.alias('addObjects'),
9219
9220   /**
9221     Removes each object in the passed enumerable to the set.
9222
9223     This is an alias of `Ember.MutableEnumerable.removeObjects()`
9224
9225         var colors = new Ember.Set(["red", "green", "blue"]);
9226         colors.removeEach(["red", "blue"]); => ["green"]
9227
9228     @method removeEach
9229     @param {Ember.Enumerable} objects the objects to remove.
9230     @return {Ember.Set} The set itself.
9231   */
9232   removeEach: Ember.alias('removeObjects'),
9233
9234   // ..........................................................
9235   // PRIVATE ENUMERABLE SUPPORT
9236   //
9237
9238   init: function(items) {
9239     this._super();
9240     if (items) this.addObjects(items);
9241   },
9242
9243   // implement Ember.Enumerable
9244   nextObject: function(idx) {
9245     return this[idx];
9246   },
9247
9248   // more optimized version
9249   firstObject: Ember.computed(function() {
9250     return this.length > 0 ? this[0] : undefined;
9251   }).property().cacheable(),
9252
9253   // more optimized version
9254   lastObject: Ember.computed(function() {
9255     return this.length > 0 ? this[this.length-1] : undefined;
9256   }).property().cacheable(),
9257
9258   // implements Ember.MutableEnumerable
9259   addObject: function(obj) {
9260     if (get(this, 'isFrozen')) throw new Error(Ember.FROZEN_ERROR);
9261     if (none(obj)) return this; // nothing to do
9262
9263     var guid = guidFor(obj),
9264         idx  = this[guid],
9265         len  = get(this, 'length'),
9266         added ;
9267
9268     if (idx>=0 && idx<len && (this[idx] === obj)) return this; // added
9269
9270     added = [obj];
9271
9272     this.enumerableContentWillChange(null, added);
9273     Ember.propertyWillChange(this, 'lastObject');
9274
9275     len = get(this, 'length');
9276     this[guid] = len;
9277     this[len] = obj;
9278     set(this, 'length', len+1);
9279
9280     Ember.propertyDidChange(this, 'lastObject');
9281     this.enumerableContentDidChange(null, added);
9282
9283     return this;
9284   },
9285
9286   // implements Ember.MutableEnumerable
9287   removeObject: function(obj) {
9288     if (get(this, 'isFrozen')) throw new Error(Ember.FROZEN_ERROR);
9289     if (none(obj)) return this; // nothing to do
9290
9291     var guid = guidFor(obj),
9292         idx  = this[guid],
9293         len = get(this, 'length'),
9294         isFirst = idx === 0,
9295         isLast = idx === len-1,
9296         last, removed;
9297
9298
9299     if (idx>=0 && idx<len && (this[idx] === obj)) {
9300       removed = [obj];
9301
9302       this.enumerableContentWillChange(removed, null);
9303       if (isFirst) { Ember.propertyWillChange(this, 'firstObject'); }
9304       if (isLast)  { Ember.propertyWillChange(this, 'lastObject'); }
9305
9306       // swap items - basically move the item to the end so it can be removed
9307       if (idx < len-1) {
9308         last = this[len-1];
9309         this[idx] = last;
9310         this[guidFor(last)] = idx;
9311       }
9312
9313       delete this[guid];
9314       delete this[len-1];
9315       set(this, 'length', len-1);
9316
9317       if (isFirst) { Ember.propertyDidChange(this, 'firstObject'); }
9318       if (isLast)  { Ember.propertyDidChange(this, 'lastObject'); }
9319       this.enumerableContentDidChange(removed, null);
9320     }
9321
9322     return this;
9323   },
9324
9325   // optimized version
9326   contains: function(obj) {
9327     return this[guidFor(obj)]>=0;
9328   },
9329
9330   copy: function() {
9331     var C = this.constructor, ret = new C(), loc = get(this, 'length');
9332     set(ret, 'length', loc);
9333     while(--loc>=0) {
9334       ret[loc] = this[loc];
9335       ret[guidFor(this[loc])] = loc;
9336     }
9337     return ret;
9338   },
9339
9340   toString: function() {
9341     var len = this.length, idx, array = [];
9342     for(idx = 0; idx < len; idx++) {
9343       array[idx] = this[idx];
9344     }
9345     return "Ember.Set<%@>".fmt(array.join(','));
9346   }
9347
9348 });
9349
9350 })();
9351
9352
9353
9354 (function() {
9355 /**
9356 @module ember
9357 @submodule ember-runtime
9358 */
9359
9360 /**
9361   `Ember.Object` is the main base class for all Ember objects. It is a subclass
9362   of `Ember.CoreObject` with the `Ember.Observable` mixin applied. For details,
9363   see the documentation for each of these.
9364
9365   @class Object
9366   @namespace Ember
9367   @extends Ember.CoreObject
9368   @uses Ember.Observable
9369 */
9370 Ember.Object = Ember.CoreObject.extend(Ember.Observable);
9371
9372 })();
9373
9374
9375
9376 (function() {
9377 /**
9378 @module ember
9379 @submodule ember-runtime
9380 */
9381
9382 var indexOf = Ember.ArrayPolyfills.indexOf;
9383
9384 /**
9385   A Namespace is an object usually used to contain other objects or methods
9386   such as an application or framework.  Create a namespace anytime you want
9387   to define one of these new containers.
9388
9389   # Example Usage
9390
9391       MyFramework = Ember.Namespace.create({
9392         VERSION: '1.0.0'
9393       });
9394
9395   @class Namespace
9396   @namespace Ember
9397   @extends Ember.Object
9398 */
9399 Ember.Namespace = Ember.Object.extend({
9400   isNamespace: true,
9401
9402   init: function() {
9403     Ember.Namespace.NAMESPACES.push(this);
9404     Ember.Namespace.PROCESSED = false;
9405   },
9406
9407   toString: function() {
9408     Ember.identifyNamespaces();
9409     return this[Ember.GUID_KEY+'_name'];
9410   },
9411
9412   destroy: function() {
9413     var namespaces = Ember.Namespace.NAMESPACES;
9414     window[this.toString()] = undefined;
9415     namespaces.splice(indexOf.call(namespaces, this), 1);
9416     this._super();
9417   }
9418 });
9419
9420 Ember.Namespace.NAMESPACES = [Ember];
9421 Ember.Namespace.PROCESSED = false;
9422
9423 })();
9424
9425
9426
9427 (function() {
9428 /**
9429 @module ember
9430 @submodule ember-runtime
9431 */
9432
9433 /**
9434   Defines a namespace that will contain an executable application.  This is
9435   very similar to a normal namespace except that it is expected to include at
9436   least a 'ready' function which can be run to initialize the application.
9437
9438   Currently Ember.Application is very similar to Ember.Namespace.  However, this
9439   class may be augmented by additional frameworks so it is important to use
9440   this instance when building new applications.
9441
9442   # Example Usage
9443
9444       MyApp = Ember.Application.create({
9445         VERSION: '1.0.0',
9446         store: Ember.Store.create().from(Ember.fixtures)
9447       });
9448
9449       MyApp.ready = function() {
9450         //..init code goes here...
9451       }
9452
9453   @class Application
9454   @namespace Ember
9455   @extends Ember.Namespace
9456 */
9457 Ember.Application = Ember.Namespace.extend();
9458
9459
9460 })();
9461
9462
9463
9464 (function() {
9465 /**
9466 @module ember
9467 @submodule ember-runtime
9468 */
9469
9470
9471 var get = Ember.get, set = Ember.set;
9472
9473 /**
9474   An ArrayProxy wraps any other object that implements Ember.Array and/or
9475   Ember.MutableArray, forwarding all requests. This makes it very useful for
9476   a number of binding use cases or other cases where being able to swap
9477   out the underlying array is useful.
9478
9479   A simple example of usage:
9480
9481       var pets = ['dog', 'cat', 'fish'];
9482       var ap = Ember.ArrayProxy.create({ content: Ember.A(pets) });
9483       ap.get('firstObject'); // => 'dog'
9484       ap.set('content', ['amoeba', 'paramecium']);
9485       ap.get('firstObject'); // => 'amoeba'
9486
9487   This class can also be useful as a layer to transform the contents of
9488   an array, as they are accessed. This can be done by overriding
9489   `objectAtContent`:
9490
9491       var pets = ['dog', 'cat', 'fish'];
9492       var ap = Ember.ArrayProxy.create({
9493           content: Ember.A(pets),
9494           objectAtContent: function(idx) {
9495               return this.get('content').objectAt(idx).toUpperCase();
9496           }
9497       });
9498       ap.get('firstObject'); // => 'DOG'
9499
9500
9501   @class ArrayProxy
9502   @namespace Ember
9503   @extends Ember.Object
9504   @uses Ember.MutableArray
9505 */
9506 Ember.ArrayProxy = Ember.Object.extend(Ember.MutableArray,
9507 /** @scope Ember.ArrayProxy.prototype */ {
9508
9509   /**
9510     The content array.  Must be an object that implements Ember.Array and/or
9511     Ember.MutableArray.
9512
9513     @property content
9514     @type Ember.Array
9515   */
9516   content: null,
9517
9518   /**
9519    The array that the proxy pretends to be. In the default `ArrayProxy`
9520    implementation, this and `content` are the same. Subclasses of `ArrayProxy`
9521    can override this property to provide things like sorting and filtering.
9522    
9523    @property arrangedContent
9524   */
9525   arrangedContent: Ember.computed('content', function() {
9526     return get(this, 'content');
9527   }).cacheable(),
9528
9529   /**
9530     Should actually retrieve the object at the specified index from the
9531     content. You can override this method in subclasses to transform the
9532     content item to something new.
9533
9534     This method will only be called if content is non-null.
9535
9536     @method objectAtContent
9537     @param {Number} idx The index to retrieve.
9538     @return {Object} the value or undefined if none found
9539   */
9540   objectAtContent: function(idx) {
9541     return get(this, 'arrangedContent').objectAt(idx);
9542   },
9543
9544   /**
9545     Should actually replace the specified objects on the content array.
9546     You can override this method in subclasses to transform the content item
9547     into something new.
9548
9549     This method will only be called if content is non-null.
9550
9551     @method replaceContent
9552     @param {Number} idx The starting index
9553     @param {Number} amt The number of items to remove from the content.
9554     @param {Array} objects Optional array of objects to insert or null if no objects.
9555     @return {void}
9556   */
9557   replaceContent: function(idx, amt, objects) {
9558     get(this, 'arrangedContent').replace(idx, amt, objects);
9559   },
9560
9561   /**
9562     @private
9563
9564     Invoked when the content property is about to change. Notifies observers that the
9565     entire array content will change.
9566
9567     @method _contentWillChange
9568   */
9569   _contentWillChange: Ember.beforeObserver(function() {
9570     this._teardownContent();
9571   }, 'content'),
9572
9573   _teardownContent: function() {
9574     var content = get(this, 'content');
9575
9576     if (content) {
9577       content.removeArrayObserver(this, {
9578         willChange: 'contentArrayWillChange',
9579         didChange: 'contentArrayDidChange'
9580       });
9581     }
9582   },
9583
9584   contentArrayWillChange: Ember.K,
9585   contentArrayDidChange: Ember.K,
9586
9587   /**
9588     @private
9589
9590     Invoked when the content property changes.  Notifies observers that the
9591     entire array content has changed.
9592
9593     @method _contentDidChange
9594   */
9595   _contentDidChange: Ember.observer(function() {
9596     var content = get(this, 'content');
9597
9598     Ember.assert("Can't set ArrayProxy's content to itself", content !== this);
9599
9600     this._setupContent();
9601   }, 'content'),
9602
9603   _setupContent: function() {
9604     var content = get(this, 'content');
9605
9606     if (content) {
9607       content.addArrayObserver(this, {
9608         willChange: 'contentArrayWillChange',
9609         didChange: 'contentArrayDidChange'
9610       });
9611     }
9612   },
9613
9614   _arrangedContentWillChange: Ember.beforeObserver(function() {
9615     var arrangedContent = get(this, 'arrangedContent'),
9616         len = arrangedContent ? get(arrangedContent, 'length') : 0;
9617
9618     this.arrangedContentArrayWillChange(this, 0, len, undefined);
9619     this.arrangedContentWillChange(this);
9620
9621     this._teardownArrangedContent(arrangedContent);
9622   }, 'arrangedContent'),
9623
9624   _arrangedContentDidChange: Ember.observer(function() {
9625     var arrangedContent = get(this, 'arrangedContent'),
9626         len = arrangedContent ? get(arrangedContent, 'length') : 0;
9627
9628     Ember.assert("Can't set ArrayProxy's content to itself", arrangedContent !== this);
9629
9630     this._setupArrangedContent();
9631
9632     this.arrangedContentDidChange(this);
9633     this.arrangedContentArrayDidChange(this, 0, undefined, len);
9634   }, 'arrangedContent'),
9635
9636   _setupArrangedContent: function() {
9637     var arrangedContent = get(this, 'arrangedContent');
9638
9639     if (arrangedContent) {
9640       arrangedContent.addArrayObserver(this, {
9641         willChange: 'arrangedContentArrayWillChange',
9642         didChange: 'arrangedContentArrayDidChange'
9643       });
9644     }
9645   },
9646
9647   _teardownArrangedContent: function() {
9648     var arrangedContent = get(this, 'arrangedContent');
9649
9650     if (arrangedContent) {
9651       arrangedContent.removeArrayObserver(this, {
9652         willChange: 'arrangedContentArrayWillChange',
9653         didChange: 'arrangedContentArrayDidChange'
9654       });
9655     }
9656   },
9657
9658   arrangedContentWillChange: Ember.K,
9659   arrangedContentDidChange: Ember.K,
9660
9661   objectAt: function(idx) {
9662     return get(this, 'content') && this.objectAtContent(idx);
9663   },
9664
9665   length: Ember.computed(function() {
9666     var arrangedContent = get(this, 'arrangedContent');
9667     return arrangedContent ? get(arrangedContent, 'length') : 0;
9668     // No dependencies since Enumerable notifies length of change
9669   }).property().cacheable(),
9670
9671   replace: function(idx, amt, objects) {
9672     if (get(this, 'content')) this.replaceContent(idx, amt, objects);
9673     return this;
9674   },
9675
9676   arrangedContentArrayWillChange: function(item, idx, removedCnt, addedCnt) {
9677     this.arrayContentWillChange(idx, removedCnt, addedCnt);
9678   },
9679
9680   arrangedContentArrayDidChange: function(item, idx, removedCnt, addedCnt) {
9681     this.arrayContentDidChange(idx, removedCnt, addedCnt);
9682   },
9683
9684   init: function() {
9685     this._super();
9686     this._setupContent();
9687     this._setupArrangedContent();
9688   },
9689
9690   willDestroy: function() {
9691     this._teardownArrangedContent();
9692     this._teardownContent();
9693   }
9694 });
9695
9696
9697 })();
9698
9699
9700
9701 (function() {
9702 /**
9703 @module ember
9704 @submodule ember-runtime
9705 */
9706
9707 var get = Ember.get,
9708     set = Ember.set,
9709     fmt = Ember.String.fmt,
9710     addBeforeObserver = Ember.addBeforeObserver,
9711     addObserver = Ember.addObserver,
9712     removeBeforeObserver = Ember.removeBeforeObserver,
9713     removeObserver = Ember.removeObserver,
9714     propertyWillChange = Ember.propertyWillChange,
9715     propertyDidChange = Ember.propertyDidChange;
9716
9717 function contentPropertyWillChange(content, contentKey) {
9718   var key = contentKey.slice(8); // remove "content."
9719   if (key in this) { return; }  // if shadowed in proxy
9720   propertyWillChange(this, key);
9721 }
9722
9723 function contentPropertyDidChange(content, contentKey) {
9724   var key = contentKey.slice(8); // remove "content."
9725   if (key in this) { return; } // if shadowed in proxy
9726   propertyDidChange(this, key);
9727 }
9728
9729 /**
9730   `Ember.ObjectProxy` forwards all properties not defined by the proxy itself
9731   to a proxied `content` object.
9732
9733       object = Ember.Object.create({
9734         name: 'Foo'
9735       });
9736       proxy = Ember.ObjectProxy.create({
9737         content: object
9738       });
9739
9740       // Access and change existing properties
9741       proxy.get('name') // => 'Foo'
9742       proxy.set('name', 'Bar');
9743       object.get('name') // => 'Bar'
9744
9745       // Create new 'description' property on `object`
9746       proxy.set('description', 'Foo is a whizboo baz');
9747       object.get('description') // => 'Foo is a whizboo baz'
9748
9749   While `content` is unset, setting a property to be delegated will throw an Error.
9750
9751       proxy = Ember.ObjectProxy.create({
9752         content: null,
9753         flag: null
9754       });
9755       proxy.set('flag', true);
9756       proxy.get('flag'); // => true
9757       proxy.get('foo'); // => undefined
9758       proxy.set('foo', 'data'); // throws Error
9759
9760   Delegated properties can be bound to and will change when content is updated.
9761
9762   Computed properties on the proxy itself can depend on delegated properties.
9763
9764       ProxyWithComputedProperty = Ember.ObjectProxy.extend({
9765         fullName: function () {
9766           var firstName = this.get('firstName'),
9767               lastName = this.get('lastName');
9768           if (firstName && lastName) {
9769             return firstName + ' ' + lastName;
9770           }
9771           return firstName || lastName;
9772         }.property('firstName', 'lastName')
9773       });
9774       proxy = ProxyWithComputedProperty.create();
9775       proxy.get('fullName'); => undefined
9776       proxy.set('content', {
9777         firstName: 'Tom', lastName: 'Dale'
9778       }); // triggers property change for fullName on proxy
9779       proxy.get('fullName'); => 'Tom Dale'
9780
9781   @class ObjectProxy
9782   @namespace Ember
9783   @extends Ember.Object
9784 */
9785 Ember.ObjectProxy = Ember.Object.extend(
9786 /** @scope Ember.ObjectProxy.prototype */ {
9787   /**
9788     The object whose properties will be forwarded.
9789
9790     @property content
9791     @type Ember.Object
9792     @default null
9793   */
9794   content: null,
9795   _contentDidChange: Ember.observer(function() {
9796     Ember.assert("Can't set ObjectProxy's content to itself", this.get('content') !== this);
9797   }, 'content'),
9798
9799   willWatchProperty: function (key) {
9800     var contentKey = 'content.' + key;
9801     addBeforeObserver(this, contentKey, null, contentPropertyWillChange);
9802     addObserver(this, contentKey, null, contentPropertyDidChange);
9803   },
9804
9805   didUnwatchProperty: function (key) {
9806     var contentKey = 'content.' + key;
9807     removeBeforeObserver(this, contentKey, null, contentPropertyWillChange);
9808     removeObserver(this, contentKey, null, contentPropertyDidChange);
9809   },
9810
9811   unknownProperty: function (key) {
9812     var content = get(this, 'content');
9813     if (content) {
9814       return get(content, key);
9815     }
9816   },
9817
9818   setUnknownProperty: function (key, value) {
9819     var content = get(this, 'content');
9820     Ember.assert(fmt("Cannot delegate set('%@', %@) to the 'content' property of object proxy %@: its 'content' is undefined.", [key, value, this]), content);
9821     return set(content, key, value);
9822   }
9823 });
9824
9825 })();
9826
9827
9828
9829 (function() {
9830 /**
9831 @module ember
9832 @submodule ember-runtime
9833 */
9834
9835
9836 var set = Ember.set, get = Ember.get, guidFor = Ember.guidFor;
9837 var forEach = Ember.EnumerableUtils.forEach;
9838
9839 var EachArray = Ember.Object.extend(Ember.Array, {
9840
9841   init: function(content, keyName, owner) {
9842     this._super();
9843     this._keyName = keyName;
9844     this._owner   = owner;
9845     this._content = content;
9846   },
9847
9848   objectAt: function(idx) {
9849     var item = this._content.objectAt(idx);
9850     return item && get(item, this._keyName);
9851   },
9852
9853   length: Ember.computed(function() {
9854     var content = this._content;
9855     return content ? get(content, 'length') : 0;
9856   }).property().cacheable()
9857
9858 });
9859
9860 var IS_OBSERVER = /^.+:(before|change)$/;
9861
9862 function addObserverForContentKey(content, keyName, proxy, idx, loc) {
9863   var objects = proxy._objects, guid;
9864   if (!objects) objects = proxy._objects = {};
9865
9866   while(--loc>=idx) {
9867     var item = content.objectAt(loc);
9868     if (item) {
9869       Ember.addBeforeObserver(item, keyName, proxy, 'contentKeyWillChange');
9870       Ember.addObserver(item, keyName, proxy, 'contentKeyDidChange');
9871
9872       // keep track of the indicies each item was found at so we can map
9873       // it back when the obj changes.
9874       guid = guidFor(item);
9875       if (!objects[guid]) objects[guid] = [];
9876       objects[guid].push(loc);
9877     }
9878   }
9879 }
9880
9881 function removeObserverForContentKey(content, keyName, proxy, idx, loc) {
9882   var objects = proxy._objects;
9883   if (!objects) objects = proxy._objects = {};
9884   var indicies, guid;
9885
9886   while(--loc>=idx) {
9887     var item = content.objectAt(loc);
9888     if (item) {
9889       Ember.removeBeforeObserver(item, keyName, proxy, 'contentKeyWillChange');
9890       Ember.removeObserver(item, keyName, proxy, 'contentKeyDidChange');
9891
9892       guid = guidFor(item);
9893       indicies = objects[guid];
9894       indicies[indicies.indexOf(loc)] = null;
9895     }
9896   }
9897 }
9898
9899 /**
9900   This is the object instance returned when you get the @each property on an
9901   array.  It uses the unknownProperty handler to automatically create
9902   EachArray instances for property names.
9903
9904   @private
9905   @class EachProxy
9906   @namespace Ember
9907   @extends Ember.Object
9908 */
9909 Ember.EachProxy = Ember.Object.extend({
9910
9911   init: function(content) {
9912     this._super();
9913     this._content = content;
9914     content.addArrayObserver(this);
9915
9916     // in case someone is already observing some keys make sure they are
9917     // added
9918     forEach(Ember.watchedEvents(this), function(eventName) {
9919       this.didAddListener(eventName);
9920     }, this);
9921   },
9922
9923   /**
9924     You can directly access mapped properties by simply requesting them.
9925     The unknownProperty handler will generate an EachArray of each item.
9926
9927     @method unknownProperty
9928     @param keyName {String}
9929     @param value {anything}
9930   */
9931   unknownProperty: function(keyName, value) {
9932     var ret;
9933     ret = new EachArray(this._content, keyName, this);
9934     Ember.defineProperty(this, keyName, null, ret);
9935     this.beginObservingContentKey(keyName);
9936     return ret;
9937   },
9938
9939   // ..........................................................
9940   // ARRAY CHANGES
9941   // Invokes whenever the content array itself changes.
9942
9943   arrayWillChange: function(content, idx, removedCnt, addedCnt) {
9944     var keys = this._keys, key, array, lim;
9945
9946     lim = removedCnt>0 ? idx+removedCnt : -1;
9947     Ember.beginPropertyChanges(this);
9948
9949     for(key in keys) {
9950       if (!keys.hasOwnProperty(key)) { continue; }
9951
9952       if (lim>0) removeObserverForContentKey(content, key, this, idx, lim);
9953
9954       Ember.propertyWillChange(this, key);
9955     }
9956
9957     Ember.propertyWillChange(this._content, '@each');
9958     Ember.endPropertyChanges(this);
9959   },
9960
9961   arrayDidChange: function(content, idx, removedCnt, addedCnt) {
9962     var keys = this._keys, key, array, lim;
9963
9964     lim = addedCnt>0 ? idx+addedCnt : -1;
9965     Ember.beginPropertyChanges(this);
9966
9967     for(key in keys) {
9968       if (!keys.hasOwnProperty(key)) { continue; }
9969
9970       if (lim>0) addObserverForContentKey(content, key, this, idx, lim);
9971
9972       Ember.propertyDidChange(this, key);
9973     }
9974
9975     Ember.propertyDidChange(this._content, '@each');
9976     Ember.endPropertyChanges(this);
9977   },
9978
9979   // ..........................................................
9980   // LISTEN FOR NEW OBSERVERS AND OTHER EVENT LISTENERS
9981   // Start monitoring keys based on who is listening...
9982
9983   didAddListener: function(eventName) {
9984     if (IS_OBSERVER.test(eventName)) {
9985       this.beginObservingContentKey(eventName.slice(0, -7));
9986     }
9987   },
9988
9989   didRemoveListener: function(eventName) {
9990     if (IS_OBSERVER.test(eventName)) {
9991       this.stopObservingContentKey(eventName.slice(0, -7));
9992     }
9993   },
9994
9995   // ..........................................................
9996   // CONTENT KEY OBSERVING
9997   // Actual watch keys on the source content.
9998
9999   beginObservingContentKey: function(keyName) {
10000     var keys = this._keys;
10001     if (!keys) keys = this._keys = {};
10002     if (!keys[keyName]) {
10003       keys[keyName] = 1;
10004       var content = this._content,
10005           len = get(content, 'length');
10006       addObserverForContentKey(content, keyName, this, 0, len);
10007     } else {
10008       keys[keyName]++;
10009     }
10010   },
10011
10012   stopObservingContentKey: function(keyName) {
10013     var keys = this._keys;
10014     if (keys && (keys[keyName]>0) && (--keys[keyName]<=0)) {
10015       var content = this._content,
10016           len     = get(content, 'length');
10017       removeObserverForContentKey(content, keyName, this, 0, len);
10018     }
10019   },
10020
10021   contentKeyWillChange: function(obj, keyName) {
10022     Ember.propertyWillChange(this, keyName);
10023   },
10024
10025   contentKeyDidChange: function(obj, keyName) {
10026     Ember.propertyDidChange(this, keyName);
10027   }
10028
10029 });
10030
10031
10032
10033 })();
10034
10035
10036
10037 (function() {
10038 /**
10039 @module ember
10040 @submodule ember-runtime
10041 */
10042
10043
10044 var get = Ember.get, set = Ember.set;
10045
10046 // Add Ember.Array to Array.prototype.  Remove methods with native
10047 // implementations and supply some more optimized versions of generic methods
10048 // because they are so common.
10049 var NativeArray = Ember.Mixin.create(Ember.MutableArray, Ember.Observable, Ember.Copyable, {
10050
10051   // because length is a built-in property we need to know to just get the
10052   // original property.
10053   get: function(key) {
10054     if (key==='length') return this.length;
10055     else if ('number' === typeof key) return this[key];
10056     else return this._super(key);
10057   },
10058
10059   objectAt: function(idx) {
10060     return this[idx];
10061   },
10062
10063   // primitive for array support.
10064   replace: function(idx, amt, objects) {
10065
10066     if (this.isFrozen) throw Ember.FROZEN_ERROR ;
10067
10068     // if we replaced exactly the same number of items, then pass only the
10069     // replaced range.  Otherwise, pass the full remaining array length
10070     // since everything has shifted
10071     var len = objects ? get(objects, 'length') : 0;
10072     this.arrayContentWillChange(idx, amt, len);
10073
10074     if (!objects || objects.length === 0) {
10075       this.splice(idx, amt) ;
10076     } else {
10077       var args = [idx, amt].concat(objects) ;
10078       this.splice.apply(this,args) ;
10079     }
10080
10081     this.arrayContentDidChange(idx, amt, len);
10082     return this ;
10083   },
10084
10085   // If you ask for an unknown property, then try to collect the value
10086   // from member items.
10087   unknownProperty: function(key, value) {
10088     var ret;// = this.reducedProperty(key, value) ;
10089     if ((value !== undefined) && ret === undefined) {
10090       ret = this[key] = value;
10091     }
10092     return ret ;
10093   },
10094
10095   // If browser did not implement indexOf natively, then override with
10096   // specialized version
10097   indexOf: function(object, startAt) {
10098     var idx, len = this.length;
10099
10100     if (startAt === undefined) startAt = 0;
10101     else startAt = (startAt < 0) ? Math.ceil(startAt) : Math.floor(startAt);
10102     if (startAt < 0) startAt += len;
10103
10104     for(idx=startAt;idx<len;idx++) {
10105       if (this[idx] === object) return idx ;
10106     }
10107     return -1;
10108   },
10109
10110   lastIndexOf: function(object, startAt) {
10111     var idx, len = this.length;
10112
10113     if (startAt === undefined) startAt = len-1;
10114     else startAt = (startAt < 0) ? Math.ceil(startAt) : Math.floor(startAt);
10115     if (startAt < 0) startAt += len;
10116
10117     for(idx=startAt;idx>=0;idx--) {
10118       if (this[idx] === object) return idx ;
10119     }
10120     return -1;
10121   },
10122
10123   copy: function() {
10124     return this.slice();
10125   }
10126 });
10127
10128 // Remove any methods implemented natively so we don't override them
10129 var ignore = ['length'];
10130 Ember.EnumerableUtils.forEach(NativeArray.keys(), function(methodName) {
10131   if (Array.prototype[methodName]) ignore.push(methodName);
10132 });
10133
10134 if (ignore.length>0) {
10135   NativeArray = NativeArray.without.apply(NativeArray, ignore);
10136 }
10137
10138 /**
10139   The NativeArray mixin contains the properties needed to to make the native
10140   Array support Ember.MutableArray and all of its dependent APIs.  Unless you
10141   have Ember.EXTEND_PROTOTYPES set to false, this will be applied automatically.
10142   Otherwise you can apply the mixin at anytime by calling
10143   `Ember.NativeArray.activate`.
10144
10145   @class NativeArray
10146   @namespace Ember
10147   @extends Ember.Mixin
10148   @uses Ember.MutableArray
10149   @uses Ember.MutableEnumerable
10150   @uses Ember.Copyable
10151   @uses Ember.Freezable
10152 */
10153 Ember.NativeArray = NativeArray;
10154
10155 /**
10156   Creates an Ember.NativeArray from an Array like object.
10157   Does not modify the original object.
10158
10159   @method A
10160   @for Ember
10161   @return {Ember.NativeArray}
10162 */
10163 Ember.A = function(arr){
10164   if (arr === undefined) { arr = []; }
10165   return Ember.NativeArray.apply(arr);
10166 };
10167
10168 /**
10169   Activates the mixin on the Array.prototype if not already applied.  Calling
10170   this method more than once is safe.
10171
10172   @method activate
10173   @for Ember.NativeArray
10174   @static
10175   @return {void}
10176 */
10177 Ember.NativeArray.activate = function() {
10178   NativeArray.apply(Array.prototype);
10179
10180   Ember.A = function(arr) { return arr || []; };
10181 };
10182
10183 if (Ember.EXTEND_PROTOTYPES) Ember.NativeArray.activate();
10184
10185
10186
10187 })();
10188
10189
10190
10191 (function() {
10192 /**
10193 @module ember
10194 @submodule ember-runtime
10195 */
10196
10197 var get = Ember.get, set = Ember.set;
10198
10199 Ember._PromiseChain = Ember.Object.extend({
10200   promises: null,
10201   failureCallback: Ember.K,
10202   successCallback: Ember.K,
10203   abortCallback: Ember.K,
10204   promiseSuccessCallback: Ember.K,
10205
10206   runNextPromise: function() {
10207     if (get(this, 'isDestroyed')) { return; }
10208
10209     var item = get(this, 'promises').shiftObject();
10210     if (item) {
10211       var promise = get(item, 'promise') || item;
10212       Ember.assert("Cannot find promise to invoke", Ember.canInvoke(promise, 'then'));
10213
10214       var self = this;
10215
10216       var successCallback = function() {
10217         self.promiseSuccessCallback.call(this, item, arguments);
10218         self.runNextPromise();
10219       };
10220
10221       var failureCallback = get(self, 'failureCallback');
10222
10223       promise.then(successCallback, failureCallback);
10224      } else {
10225       this.successCallback();
10226     }
10227   },
10228
10229   start: function() {
10230     this.runNextPromise();
10231     return this;
10232   },
10233
10234   abort: function() {
10235     this.abortCallback();
10236     this.destroy();
10237   },
10238
10239   init: function() {
10240     set(this, 'promises', Ember.A(get(this, 'promises')));
10241     this._super();
10242   }
10243 });
10244
10245
10246 })();
10247
10248
10249
10250 (function() {
10251 /**
10252 @module ember
10253 @submodule ember-runtime
10254 */
10255
10256 var loadHooks = {};
10257 var loaded = {};
10258
10259 /**
10260 @method onLoad
10261 @for Ember
10262 @param name {String} name of hook
10263 @param callback {Function} callback to be called
10264 */
10265 Ember.onLoad = function(name, callback) {
10266   var object;
10267
10268   loadHooks[name] = loadHooks[name] || Ember.A();
10269   loadHooks[name].pushObject(callback);
10270
10271   if (object = loaded[name]) {
10272     callback(object);
10273   }
10274 };
10275
10276 /**
10277 @method runLoadHooks
10278 @for Ember
10279 @param name {String} name of hook
10280 @param object {Object} object to pass to callbacks
10281 */
10282 Ember.runLoadHooks = function(name, object) {
10283   var hooks;
10284
10285   loaded[name] = object;
10286
10287   if (hooks = loadHooks[name]) {
10288     loadHooks[name].forEach(function(callback) {
10289       callback(object);
10290     });
10291   }
10292 };
10293
10294 })();
10295
10296
10297
10298 (function() {
10299
10300 })();
10301
10302
10303
10304 (function() {
10305 /**
10306 @module ember
10307 @submodule ember-runtime
10308 */
10309
10310 /**
10311   Ember.ControllerMixin provides a standard interface for all classes
10312   that compose Ember's controller layer: Ember.Controller, Ember.ArrayController,
10313   and Ember.ObjectController.
10314
10315   Within an Ember.Router-managed application single shared instaces of every
10316   Controller object in your application's namespace will be added to the
10317   application's Ember.Router instance. See `Ember.Application#initialize`
10318   for additional information.
10319
10320   ## Views
10321   By default a controller instance will be the rendering context
10322   for its associated Ember.View. This connection is made during calls to
10323   `Ember.ControllerMixin#connectOutlet`.
10324
10325   Within the view's template, the Ember.View instance can be accessed
10326   through the controller with `{{view}}`.
10327
10328   ## Target Forwarding
10329   By default a controller will target your application's Ember.Router instance.
10330   Calls to `{{action}}` within the template of a controller's view are forwarded
10331   to the router. See `Ember.Handlebars.helpers.action` for additional information.
10332
10333   @class ControllerMixin
10334   @namespace Ember
10335   @extends Ember.Mixin
10336 */
10337 Ember.ControllerMixin = Ember.Mixin.create({
10338   /**
10339     The object to which events from the view should be sent.
10340
10341     For example, when a Handlebars template uses the `{{action}}` helper,
10342     it will attempt to send the event to the view's controller's `target`.
10343
10344     By default, a controller's `target` is set to the router after it is
10345     instantiated by `Ember.Application#initialize`.
10346
10347     @property target
10348     @default null
10349   */
10350   target: null,
10351
10352   store: null
10353 });
10354
10355 /**
10356   @class Controller
10357   @namespace Ember
10358   @extends Ember.Object
10359   @uses Ember.ControllerMixin
10360 */
10361 Ember.Controller = Ember.Object.extend(Ember.ControllerMixin);
10362
10363 })();
10364
10365
10366
10367 (function() {
10368 /**
10369 @module ember
10370 @submodule ember-runtime
10371 */
10372
10373 var get = Ember.get, set = Ember.set, forEach = Ember.EnumerableUtils.forEach;
10374
10375 /**
10376   Ember.SortableMixin provides a standard interface for array proxies
10377   to specify a sort order and maintain this sorting when objects are added,
10378   removed, or updated without changing the implicit order of their underlying
10379   content array:
10380
10381       songs = [
10382         {trackNumber: 4, title: 'Ob-La-Di, Ob-La-Da'},
10383         {trackNumber: 2, title: 'Back in the U.S.S.R.'},
10384         {trackNumber: 3, title: 'Glass Onion'},
10385       ];
10386
10387       songsController = Ember.ArrayController.create({
10388         content: songs,
10389         sortProperties: ['trackNumber']
10390       });
10391
10392       songsController.get('firstObject'); // {trackNumber: 2, title: 'Back in the U.S.S.R.'}
10393
10394       songsController.addObject({trackNumber: 1, title: 'Dear Prudence'});
10395       songsController.get('firstObject'); // {trackNumber: 1, title: 'Dear Prudence'}
10396
10397
10398   @class SortableMixin
10399   @namespace Ember
10400   @extends Ember.Mixin
10401   @uses Ember.MutableEnumerable
10402 */
10403 Ember.SortableMixin = Ember.Mixin.create(Ember.MutableEnumerable, {
10404   sortProperties: null,
10405   sortAscending: true,
10406
10407   addObject: function(obj) {
10408     var content = get(this, 'content');
10409     content.pushObject(obj);
10410   },
10411
10412   removeObject: function(obj) {
10413     var content = get(this, 'content');
10414     content.removeObject(obj);
10415   },
10416
10417   orderBy: function(item1, item2) {
10418     var result = 0,
10419         sortProperties = get(this, 'sortProperties'),
10420         sortAscending = get(this, 'sortAscending');
10421
10422     Ember.assert("you need to define `sortProperties`", !!sortProperties);
10423
10424     forEach(sortProperties, function(propertyName) {
10425       if (result === 0) {
10426         result = Ember.compare(get(item1, propertyName), get(item2, propertyName));
10427         if ((result !== 0) && !sortAscending) {
10428           result = (-1) * result;
10429         }
10430       }
10431     });
10432
10433     return result;
10434   },
10435
10436   destroy: function() {
10437     var content = get(this, 'content'),
10438         sortProperties = get(this, 'sortProperties');
10439
10440     if (content && sortProperties) {
10441       forEach(content, function(item) {
10442         forEach(sortProperties, function(sortProperty) {
10443           Ember.removeObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
10444         }, this);
10445       }, this);
10446     }
10447
10448     return this._super();
10449   },
10450
10451   isSorted: Ember.computed('sortProperties', function() {
10452     return !!get(this, 'sortProperties');
10453   }),
10454
10455   arrangedContent: Ember.computed('content', 'sortProperties.@each', function(key, value) {
10456     var content = get(this, 'content'),
10457         isSorted = get(this, 'isSorted'),
10458         sortProperties = get(this, 'sortProperties'),
10459         self = this;
10460
10461     if (content && isSorted) {
10462       content = content.slice();
10463       content.sort(function(item1, item2) {
10464         return self.orderBy(item1, item2);
10465       });
10466       forEach(content, function(item) {
10467         forEach(sortProperties, function(sortProperty) {
10468           Ember.addObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
10469         }, this);
10470       }, this);
10471       return Ember.A(content);
10472     }
10473
10474     return content;
10475   }).cacheable(),
10476
10477   _contentWillChange: Ember.beforeObserver(function() {
10478     var content = get(this, 'content'),
10479         sortProperties = get(this, 'sortProperties');
10480
10481     if (content && sortProperties) {
10482       forEach(content, function(item) {
10483         forEach(sortProperties, function(sortProperty) {
10484           Ember.removeObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
10485         }, this);
10486       }, this);
10487     }
10488
10489     this._super();
10490   }, 'content'),
10491
10492   sortAscendingWillChange: Ember.beforeObserver(function() {
10493     this._lastSortAscending = get(this, 'sortAscending');
10494   }, 'sortAscending'),
10495
10496   sortAscendingDidChange: Ember.observer(function() {
10497     if (get(this, 'sortAscending') !== this._lastSortAscending) {
10498       var arrangedContent = get(this, 'arrangedContent');
10499       arrangedContent.reverseObjects();
10500     }
10501   }, 'sortAscending'),
10502
10503   contentArrayWillChange: function(array, idx, removedCount, addedCount) {
10504     var isSorted = get(this, 'isSorted');
10505
10506     if (isSorted) {
10507       var arrangedContent = get(this, 'arrangedContent');
10508       var removedObjects = array.slice(idx, idx+removedCount);
10509       var sortProperties = get(this, 'sortProperties');
10510
10511       forEach(removedObjects, function(item) {
10512         arrangedContent.removeObject(item);
10513
10514         forEach(sortProperties, function(sortProperty) {
10515           Ember.removeObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
10516         }, this);
10517       });
10518     }
10519
10520     return this._super(array, idx, removedCount, addedCount);
10521   },
10522
10523   contentArrayDidChange: function(array, idx, removedCount, addedCount) {
10524     var isSorted = get(this, 'isSorted'),
10525         sortProperties = get(this, 'sortProperties');
10526
10527     if (isSorted) {
10528       var addedObjects = array.slice(idx, idx+addedCount);
10529       var arrangedContent = get(this, 'arrangedContent');
10530
10531       forEach(addedObjects, function(item) {
10532         this.insertItemSorted(item);
10533
10534         forEach(sortProperties, function(sortProperty) {
10535           Ember.addObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
10536         }, this);
10537       }, this);
10538     }
10539
10540     return this._super(array, idx, removedCount, addedCount);
10541   },
10542
10543   insertItemSorted: function(item) {
10544     var arrangedContent = get(this, 'arrangedContent');
10545     var length = get(arrangedContent, 'length');
10546
10547     var idx = this._binarySearch(item, 0, length);
10548     arrangedContent.insertAt(idx, item);
10549   },
10550
10551   contentItemSortPropertyDidChange: function(item) {
10552     var arrangedContent = get(this, 'arrangedContent'),
10553         oldIndex = arrangedContent.indexOf(item),
10554         newIndex = this._binarySearch(item, 0, get(arrangedContent, 'length'));
10555
10556     if (newIndex !== oldIndex) {
10557       arrangedContent.removeObject(item);
10558       this.insertItemSorted(item);
10559     }
10560   },
10561
10562   _binarySearch: function(item, low, high) {
10563     var mid, midItem, res, arrangedContent;
10564
10565     if (low === high) {
10566       return low;
10567     }
10568
10569     arrangedContent = get(this, 'arrangedContent');
10570
10571     mid = low + Math.floor((high - low) / 2);
10572     midItem = arrangedContent.objectAt(mid);
10573
10574     res = this.orderBy(midItem, item);
10575
10576     if (res < 0) {
10577       return this._binarySearch(item, mid+1, high);
10578     } else if (res > 0) {
10579       return this._binarySearch(item, low, mid);
10580     }
10581
10582     return mid;
10583   }
10584 });
10585
10586 })();
10587
10588
10589
10590 (function() {
10591 /**
10592 @module ember
10593 @submodule ember-runtime
10594 */
10595
10596 var get = Ember.get, set = Ember.set;
10597
10598 /**
10599   Ember.ArrayController provides a way for you to publish a collection of objects
10600   so that you can easily bind to the collection from a Handlebars #each helper,
10601   an Ember.CollectionView, or other controllers.
10602
10603   The advantage of using an ArrayController is that you only have to set up
10604   your view bindings once; to change what's displayed, simply swap out the
10605   `content` property on the controller.
10606
10607   For example, imagine you wanted to display a list of items fetched via an XHR
10608   request. Create an Ember.ArrayController and set its `content` property:
10609
10610   ``` javascript
10611   MyApp.listController = Ember.ArrayController.create();
10612
10613   $.get('people.json', function(data) {
10614     MyApp.listController.set('content', data);
10615   });
10616   ```
10617
10618   Then, create a view that binds to your new controller:
10619
10620   ``` handlebars
10621   {{#each MyApp.listController}}
10622     {{firstName}} {{lastName}}
10623   {{/each}}
10624   ```
10625
10626   Although you are binding to the controller, the behavior of this controller
10627   is to pass through any methods or properties to the underlying array. This
10628   capability comes from `Ember.ArrayProxy`, which this class inherits from.
10629
10630   Note: As of this writing, `ArrayController` does not add any functionality
10631   to its superclass, `ArrayProxy`. The Ember team plans to add additional
10632   controller-specific functionality in the future, e.g. single or multiple
10633   selection support. If you are creating something that is conceptually a
10634   controller, use this class.
10635
10636   @class ArrayController
10637   @namespace Ember
10638   @extends Ember.ArrayProxy
10639   @uses Ember.SortableMixin
10640   @uses Ember.ControllerMixin
10641 */
10642
10643 Ember.ArrayController = Ember.ArrayProxy.extend(Ember.ControllerMixin,
10644   Ember.SortableMixin);
10645
10646 })();
10647
10648
10649
10650 (function() {
10651 /**
10652 @module ember
10653 @submodule ember-runtime
10654 */
10655
10656 /**
10657   Ember.ObjectController is part of Ember's Controller layer. A single
10658   shared instance of each Ember.ObjectController subclass in your application's
10659   namespace will be created at application initialization and be stored on your
10660   application's Ember.Router instance.
10661
10662   Ember.ObjectController derives its functionality from its superclass
10663   Ember.ObjectProxy and the Ember.ControllerMixin mixin.
10664
10665   @class ObjectController
10666   @namespace Ember
10667   @extends Ember.ObjectProxy
10668   @uses Ember.ControllerMixin
10669 **/
10670 Ember.ObjectController = Ember.ObjectProxy.extend(Ember.ControllerMixin);
10671
10672 })();
10673
10674
10675
10676 (function() {
10677
10678 })();
10679
10680
10681
10682 (function() {
10683 /**
10684 Ember Runtime
10685
10686 @module ember
10687 @submodule ember-runtime
10688 @requires ember-metal
10689 */
10690
10691 })();
10692
10693 (function() {
10694 function visit(vertex, fn, visited, path) {
10695   var name = vertex.name,
10696     vertices = vertex.incoming,
10697     names = vertex.incomingNames,
10698     len = names.length,
10699     i;
10700   if (!visited) {
10701     visited = {};
10702   }
10703   if (!path) {
10704     path = [];
10705   }
10706   if (visited.hasOwnProperty(name)) {
10707     return;
10708   }
10709   path.push(name);
10710   visited[name] = true;
10711   for (i = 0; i < len; i++) {
10712     visit(vertices[names[i]], fn, visited, path);
10713   }
10714   fn(vertex, path);
10715   path.pop();
10716 }
10717
10718 function DAG() {
10719   this.names = [];
10720   this.vertices = {};
10721 }
10722
10723 DAG.prototype.add = function(name) {
10724   if (!name) { return; }
10725   if (this.vertices.hasOwnProperty(name)) {
10726     return this.vertices[name];
10727   }
10728   var vertex = {
10729     name: name, incoming: {}, incomingNames: [], hasOutgoing: false, value: null
10730   };
10731   this.vertices[name] = vertex;
10732   this.names.push(name);
10733   return vertex;
10734 };
10735
10736 DAG.prototype.map = function(name, value) {
10737   this.add(name).value = value;
10738 };
10739
10740 DAG.prototype.addEdge = function(fromName, toName) {
10741   if (!fromName || !toName || fromName === toName) {
10742     return;
10743   }
10744   var from = this.add(fromName), to = this.add(toName);
10745   if (to.incoming.hasOwnProperty(fromName)) {
10746     return;
10747   }
10748   function checkCycle(vertex, path) {
10749     if (vertex.name === toName) {
10750       throw new Error("cycle detected: " + toName + " <- " + path.join(" <- "));
10751     }
10752   }
10753   visit(from, checkCycle);
10754   from.hasOutgoing = true;
10755   to.incoming[fromName] = from;
10756   to.incomingNames.push(fromName);
10757 };
10758
10759 DAG.prototype.topsort = function(fn) {
10760   var visited = {},
10761     vertices = this.vertices,
10762     names = this.names,
10763     len = names.length,
10764     i, vertex;
10765   for (i = 0; i < len; i++) {
10766     vertex = vertices[names[i]];
10767     if (!vertex.hasOutgoing) {
10768       visit(vertex, fn, visited);
10769     }
10770   }
10771 };
10772
10773 DAG.prototype.addEdges = function(name, value, before, after) {
10774   var i;
10775   this.map(name, value);
10776   if (before) {
10777     if (typeof before === 'string') {
10778       this.addEdge(name, before);
10779     } else {
10780       for (i = 0; i < before.length; i++) {
10781         this.addEdge(name, before[i]);
10782       }
10783     }
10784   }
10785   if (after) {
10786     if (typeof after === 'string') {
10787       this.addEdge(after, name);
10788     } else {
10789       for (i = 0; i < after.length; i++) {
10790         this.addEdge(after[i], name);
10791       }
10792     }
10793   }
10794 };
10795
10796 Ember.DAG = DAG;
10797
10798 })();
10799
10800
10801
10802 (function() {
10803 /**
10804 @module ember
10805 @submodule ember-application
10806 */
10807
10808 var get = Ember.get, set = Ember.set;
10809
10810 /**
10811   An instance of `Ember.Application` is the starting point for every Ember.js
10812   application. It helps to instantiate, initialize and coordinate the many
10813   objects that make up your app.
10814
10815   Each Ember.js app has one and only one `Ember.Application` object. In fact, the very
10816   first thing you should do in your application is create the instance:
10817
10818   ```javascript
10819   window.App = Ember.Application.create();
10820   ```
10821
10822   Typically, the application object is the only global variable. All other
10823   classes in your app should be properties on the `Ember.Application` instance,
10824   which highlights its first role: a global namespace.
10825
10826   For example, if you define a view class, it might look like this:
10827
10828   ```javascript
10829   App.MyView = Ember.View.extend();
10830   ```
10831
10832   After all of your classes are defined, call `App.initialize()` to start the
10833   application.
10834
10835   Because `Ember.Application` inherits from `Ember.Namespace`, any classes
10836   you create will have useful string representations when calling `toString()`;
10837   see the `Ember.Namespace` documentation for more information.
10838
10839   While you can think of your `Ember.Application` as a container that holds the
10840   other classes in your application, there are several other responsibilities
10841   going on under-the-hood that you may want to understand.
10842
10843   ### Event Delegation
10844
10845   Ember.js uses a technique called _event delegation_. This allows the framework
10846   to set up a global, shared event listener instead of requiring each view to do
10847   it manually. For example, instead of each view registering its own `mousedown`
10848   listener on its associated element, Ember.js sets up a `mousedown` listener on
10849   the `body`.
10850
10851   If a `mousedown` event occurs, Ember.js will look at the target of the event and
10852   start walking up the DOM node tree, finding corresponding views and invoking their
10853   `mouseDown` method as it goes.
10854
10855   `Ember.Application` has a number of default events that it listens for, as well
10856   as a mapping from lowercase events to camel-cased view method names. For
10857   example, the `keypress` event causes the `keyPress` method on the view to be
10858   called, the `dblclick` event causes `doubleClick` to be called, and so on.
10859
10860   If there is a browser event that Ember.js does not listen for by default, you
10861   can specify custom events and their corresponding view method names by setting
10862   the application's `customEvents` property:
10863
10864   ```javascript
10865   App = Ember.Application.create({
10866     customEvents: {
10867       // add support for the loadedmetadata media
10868       // player event
10869       'loadedmetadata': "loadedMetadata"
10870     }
10871   });
10872   ```
10873
10874   By default, the application sets up these event listeners on the document body.
10875   However, in cases where you are embedding an Ember.js application inside an
10876   existing page, you may want it to set up the listeners on an element inside
10877   the body.
10878
10879   For example, if only events inside a DOM element with the ID of `ember-app` should
10880   be delegated, set your application's `rootElement` property:
10881
10882   ```javascript
10883   window.App = Ember.Application.create({
10884     rootElement: '#ember-app'
10885   });
10886   ```
10887
10888   The `rootElement` can be either a DOM element or a jQuery-compatible selector
10889   string. Note that *views appended to the DOM outside the root element will not
10890   receive events.* If you specify a custom root element, make sure you only append
10891   views inside it!
10892
10893   To learn more about the advantages of event delegation and the Ember.js view layer,
10894   and a list of the event listeners that are setup by default, visit the
10895   [Ember.js View Layer guide](http://emberjs.com/guides/view_layer#toc_event-delegation).
10896
10897   ### Dependency Injection
10898
10899   One thing you may have noticed while using Ember.js is that you define *classes*, not
10900   *instances*. When your application loads, all of the instances are created for you.
10901   Creating these instances is the responsibility of `Ember.Application`.
10902
10903   When the `Ember.Application` initializes, it will look for an `Ember.Router` class
10904   defined on the applications's `Router` property, like this:
10905
10906   ```javascript
10907   App.Router = Ember.Router.extend({
10908   // ...
10909   });
10910   ```
10911
10912   If found, the router is instantiated and saved on the application's `router`
10913   property (note the lowercase 'r'). While you should *not* reference this router
10914   instance directly from your application code, having access to `App.router`
10915   from the console can be useful during debugging.
10916
10917   After the router is created, the application loops through all of the
10918   registered _injections_ and invokes them once for each property on the
10919   `Ember.Application` object.
10920
10921   An injection is a function that is responsible for instantiating objects from
10922   classes defined on the application. By default, the only injection registered
10923   instantiates controllers and makes them available on the router.
10924
10925   For example, if you define a controller class:
10926
10927   ```javascript
10928   App.MyController = Ember.Controller.extend({
10929     // ...
10930   });
10931   ```
10932
10933   Your router will receive an instance of `App.MyController` saved on its
10934   `myController` property.
10935
10936   Libraries on top of Ember.js can register additional injections. For example,
10937   if your application is using Ember Data, it registers an injection that
10938   instantiates `DS.Store`:
10939
10940   ```javascript
10941   Ember.Application.registerInjection({
10942     name: 'store',
10943     before: 'controllers',
10944
10945     injection: function(app, router, property) {
10946       if (property === 'Store') {
10947         set(router, 'store', app[property].create());
10948       }
10949     }
10950   });
10951   ```
10952
10953   ### Routing
10954
10955   In addition to creating your application's router, `Ember.Application` is also
10956   responsible for telling the router when to start routing.
10957
10958   By default, the router will begin trying to translate the current URL into
10959   application state once the browser emits the `DOMContentReady` event. If you
10960   need to defer routing, you can call the application's `deferReadiness()` method.
10961   Once routing can begin, call the `advanceReadiness()` method.
10962
10963   If there is any setup required before routing begins, you can implement a `ready()`
10964   method on your app that will be invoked immediately before routing begins:
10965
10966   ```javascript
10967   window.App = Ember.Application.create({
10968     ready: function() {
10969       this.set('router.enableLogging', true);
10970     }
10971   });
10972
10973   To begin routing, you must have at a minimum a top-level controller and view.
10974   You define these as `App.ApplicationController` and `App.ApplicationView`,
10975   respectively. Your application will not work if you do not define these two
10976   mandatory classes. For example:
10977
10978   ```javascript
10979   App.ApplicationView = Ember.View.extend({
10980     templateName: 'application'
10981   });
10982   App.ApplicationController = Ember.Controller.extend();
10983   ```
10984
10985   @class Application
10986   @namespace Ember
10987   @extends Ember.Namespace
10988 */
10989 Ember.Application = Ember.Namespace.extend(
10990 /** @scope Ember.Application.prototype */{
10991
10992   /**
10993     The root DOM element of the Application. This can be specified as an
10994     element or a
10995     [jQuery-compatible selector string](http://api.jquery.com/category/selectors/).
10996
10997     This is the element that will be passed to the Application's,
10998     `eventDispatcher`, which sets up the listeners for event delegation. Every
10999     view in your application should be a child of the element you specify here.
11000
11001     @property rootElement
11002     @type DOMElement
11003     @default 'body'
11004   */
11005   rootElement: 'body',
11006
11007   /**
11008     The `Ember.EventDispatcher` responsible for delegating events to this
11009     application's views.
11010
11011     The event dispatcher is created by the application at initialization time
11012     and sets up event listeners on the DOM element described by the
11013     application's `rootElement` property.
11014
11015     See the documentation for `Ember.EventDispatcher` for more information.
11016
11017     @property eventDispatcher
11018     @type Ember.EventDispatcher
11019     @default null
11020   */
11021   eventDispatcher: null,
11022
11023   /**
11024     The DOM events for which the event dispatcher should listen.
11025
11026     By default, the application's `Ember.EventDispatcher` listens
11027     for a set of standard DOM events, such as `mousedown` and
11028     `keyup`, and delegates them to your application's `Ember.View`
11029     instances.
11030
11031     If you would like additional events to be delegated to your
11032     views, set your `Ember.Application`'s `customEvents` property
11033     to a hash containing the DOM event name as the key and the
11034     corresponding view method name as the value. For example:
11035
11036         App = Ember.Application.create({
11037           customEvents: {
11038             // add support for the loadedmetadata media
11039             // player event
11040             'loadedmetadata': "loadedMetadata"
11041           }
11042         });
11043
11044     @property customEvents
11045     @type Object
11046     @default null
11047   */
11048   customEvents: null,
11049
11050   autoinit: !Ember.testing,
11051
11052   isInitialized: false,
11053
11054   init: function() {
11055     if (!this.$) { this.$ = Ember.$; }
11056
11057     this._super();
11058
11059     this.createEventDispatcher();
11060
11061     // Start off the number of deferrals at 1. This will be
11062     // decremented by the Application's own `initialize` method.
11063     this._readinessDeferrals = 1;
11064
11065     this.waitForDOMContentLoaded();
11066
11067     if (this.autoinit) {
11068       var self = this;
11069       this.$().ready(function() {
11070         if (self.isDestroyed || self.isInitialized) return;
11071         self.initialize();
11072       });
11073     }
11074   },
11075
11076   /** @private */
11077   createEventDispatcher: function() {
11078     var rootElement = get(this, 'rootElement'),
11079         eventDispatcher = Ember.EventDispatcher.create({
11080           rootElement: rootElement
11081         });
11082
11083     set(this, 'eventDispatcher', eventDispatcher);
11084   },
11085
11086   waitForDOMContentLoaded: function() {
11087     this.deferReadiness();
11088
11089     var self = this;
11090     this.$().ready(function() {
11091       self.advanceReadiness();
11092     });
11093   },
11094
11095   deferReadiness: function() {
11096     Ember.assert("You cannot defer readiness since the `ready()` hook has already been called.", this._readinessDeferrals > 0);
11097     this._readinessDeferrals++;
11098   },
11099
11100   advanceReadiness: function() {
11101     this._readinessDeferrals--;
11102
11103     if (this._readinessDeferrals === 0) {
11104       Ember.run.once(this, this.didBecomeReady);
11105     }
11106   },
11107
11108   /**
11109     Instantiate all controllers currently available on the namespace
11110     and inject them onto a router.
11111
11112     Example:
11113
11114         App.PostsController = Ember.ArrayController.extend();
11115         App.CommentsController = Ember.ArrayController.extend();
11116
11117         var router = Ember.Router.create({
11118           ...
11119         });
11120
11121         App.initialize(router);
11122
11123         router.get('postsController')     // <App.PostsController:ember1234>
11124         router.get('commentsController')  // <App.CommentsController:ember1235>
11125
11126         router.get('postsController.router') // router
11127
11128     @method initialize
11129     @param router {Ember.Router}
11130   */
11131   initialize: function(router) {
11132     Ember.assert("Application initialize may only be call once", !this.isInitialized);
11133     Ember.assert("Application not destroyed", !this.isDestroyed);
11134
11135     router = this.setupRouter(router);
11136
11137     this.runInjections(router);
11138
11139     Ember.runLoadHooks('application', this);
11140
11141     this.isInitialized = true;
11142
11143     // At this point, any injections or load hooks that would have wanted
11144     // to defer readiness have fired.
11145     this.advanceReadiness();
11146
11147     return this;
11148   },
11149
11150   /** @private */
11151   runInjections: function(router) {
11152     var injections = get(this.constructor, 'injections'),
11153         graph = new Ember.DAG(),
11154         namespace = this,
11155         properties, i, injection;
11156
11157     for (i=0; i<injections.length; i++) {
11158       injection = injections[i];
11159       graph.addEdges(injection.name, injection.injection, injection.before, injection.after);
11160     }
11161
11162     graph.topsort(function (vertex) {
11163       var injection = vertex.value,
11164           properties = Ember.A(Ember.keys(namespace));
11165       properties.forEach(function(property) {
11166         injection(namespace, router, property);
11167       });
11168     });
11169   },
11170
11171   /** @private */
11172   setupRouter: function(router) {
11173     if (!router && Ember.Router.detect(this.Router)) {
11174       router = this.Router.create();
11175       this._createdRouter = router;
11176     }
11177
11178     if (router) {
11179       set(this, 'router', router);
11180
11181       // By default, the router's namespace is the current application.
11182       //
11183       // This allows it to find model classes when a state has a
11184       // route like `/posts/:post_id`. In that case, it would first
11185       // convert `post_id` into `Post`, and then look it up on its
11186       // namespace.
11187       set(router, 'namespace', this);
11188     }
11189
11190     return router;
11191   },
11192
11193   /** @private */
11194   didBecomeReady: function() {
11195     var eventDispatcher = get(this, 'eventDispatcher'),
11196         customEvents    = get(this, 'customEvents'),
11197         router;
11198
11199     eventDispatcher.setup(customEvents);
11200
11201     this.ready();
11202
11203
11204     router = get(this, 'router');
11205
11206     this.createApplicationView(router);
11207
11208     if (router && router instanceof Ember.Router) {
11209       this.startRouting(router);
11210     }
11211   },
11212
11213   createApplicationView: function (router) {
11214     var rootElement = get(this, 'rootElement'),
11215         applicationViewOptions = {},
11216         applicationViewClass = this.ApplicationView,
11217         applicationTemplate = Ember.TEMPLATES.application,
11218         applicationController, applicationView;
11219
11220     // don't do anything unless there is an ApplicationView or application template
11221     if (!applicationViewClass && !applicationTemplate) return;
11222
11223     if (router) {
11224       applicationController = get(router, 'applicationController');
11225       if (applicationController) {
11226         applicationViewOptions.controller = applicationController;
11227       }
11228     }
11229
11230     if (applicationTemplate) {
11231       applicationViewOptions.template = applicationTemplate;
11232     }
11233
11234     if (!applicationViewClass) {
11235       applicationViewClass = Ember.View;
11236     }
11237
11238     applicationView = applicationViewClass.create(applicationViewOptions);
11239
11240     this._createdApplicationView = applicationView;
11241
11242     if (router) {
11243       set(router, 'applicationView', applicationView);
11244     }
11245
11246     applicationView.appendTo(rootElement);
11247   },
11248
11249   /**
11250     @private
11251
11252     If the application has a router, use it to route to the current URL, and
11253     trigger a new call to `route` whenever the URL changes.
11254
11255     @method startRouting
11256     @property router {Ember.Router}
11257   */
11258   startRouting: function(router) {
11259     var location = get(router, 'location');
11260
11261     Ember.assert("You must have an application template or ApplicationView defined on your application", get(router, 'applicationView') );
11262     Ember.assert("You must have an ApplicationController defined on your application", get(router, 'applicationController') );
11263
11264     router.route(location.getURL());
11265     location.onUpdateURL(function(url) {
11266       router.route(url);
11267     });
11268   },
11269
11270   /**
11271     Called when the Application has become ready.
11272     The call will be delayed until the DOM has become ready.
11273
11274     @event ready
11275   */
11276   ready: Ember.K,
11277
11278   willDestroy: function() {
11279     get(this, 'eventDispatcher').destroy();
11280     if (this._createdRouter)          { this._createdRouter.destroy(); }
11281     if (this._createdApplicationView) { this._createdApplicationView.destroy(); }
11282   },
11283
11284   registerInjection: function(options) {
11285     this.constructor.registerInjection(options);
11286   }
11287 });
11288
11289 Ember.Application.reopenClass({
11290   concatenatedProperties: ['injections'],
11291   injections: Ember.A(),
11292   registerInjection: function(injection) {
11293     var injections = get(this, 'injections');
11294
11295     Ember.assert("The injection '" + injection.name + "' has already been registered", !injections.findProperty('name', injection.name));
11296     Ember.assert("An injection cannot be registered with both a before and an after", !(injection.before && injection.after));
11297     Ember.assert("An injection cannot be registered without an injection function", Ember.canInvoke(injection, 'injection'));
11298
11299     injections.push(injection);
11300   }
11301 });
11302
11303 Ember.Application.registerInjection({
11304   name: 'controllers',
11305   injection: function(app, router, property) {
11306     if (!/^[A-Z].*Controller$/.test(property)) { return; }
11307
11308     var name = property.charAt(0).toLowerCase() + property.substr(1),
11309         controllerClass = app[property], controller;
11310
11311     if(!Ember.Object.detect(controllerClass)){ return; }
11312     controller = app[property].create();
11313
11314     router.set(name, controller);
11315
11316     controller.setProperties({
11317       target: router,
11318       controllers: router,
11319       namespace: app
11320     });
11321   }
11322 });
11323
11324 Ember.runLoadHooks('Ember.Application', Ember.Application);
11325
11326
11327 })();
11328
11329
11330
11331 (function() {
11332
11333 })();
11334
11335
11336
11337 (function() {
11338 /**
11339 Ember Application
11340
11341 @module ember
11342 @submodule ember-application
11343 @requires ember-views, ember-states, ember-routing
11344 */
11345
11346 })();
11347
11348 (function() {
11349 /**
11350 @module ember
11351 @submodule ember-views
11352 */
11353
11354 Ember.assert("Ember Views require jQuery 1.7 or 1.8", window.jQuery && (window.jQuery().jquery.match(/^1\.[78](\.\d+)?(pre|rc\d?)?/) || Ember.ENV.FORCE_JQUERY));
11355
11356 /**
11357   Alias for jQuery
11358
11359   @method $
11360   @for Ember
11361 */
11362 Ember.$ = window.jQuery;
11363
11364 })();
11365
11366
11367
11368 (function() {
11369 /**
11370 @module ember
11371 @submodule ember-views
11372 */
11373
11374 // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#dndevents
11375 var dragEvents = Ember.String.w('dragstart drag dragenter dragleave dragover drop dragend');
11376
11377 // Copies the `dataTransfer` property from a browser event object onto the
11378 // jQuery event object for the specified events
11379 Ember.EnumerableUtils.forEach(dragEvents, function(eventName) {
11380   Ember.$.event.fixHooks[eventName] = { props: ['dataTransfer'] };
11381 });
11382
11383 })();
11384
11385
11386
11387 (function() {
11388 /**
11389 @module ember
11390 @submodule ember-views
11391 */
11392
11393 var get = Ember.get, set = Ember.set;
11394 var indexOf = Ember.ArrayPolyfills.indexOf;
11395
11396 var ClassSet = function() {
11397   this.seen = {};
11398   this.list = [];
11399 };
11400
11401 ClassSet.prototype = {
11402   add: function(string) {
11403     if (string in this.seen) { return; }
11404     this.seen[string] = true;
11405
11406     this.list.push(string);
11407   },
11408
11409   toDOM: function() {
11410     return this.list.join(" ");
11411   }
11412 };
11413
11414 /**
11415   Ember.RenderBuffer gathers information regarding the a view and generates the
11416   final representation. Ember.RenderBuffer will generate HTML which can be pushed
11417   to the DOM.
11418
11419   @class RenderBuffer
11420   @namespace Ember
11421   @constructor
11422 */
11423 Ember.RenderBuffer = function(tagName) {
11424   return new Ember._RenderBuffer(tagName);
11425 };
11426
11427 Ember._RenderBuffer = function(tagName) {
11428   this.elementTag = tagName;
11429   this.childBuffers = [];
11430 };
11431
11432 Ember._RenderBuffer.prototype =
11433 /** @scope Ember.RenderBuffer.prototype */ {
11434
11435   /**
11436     Array of class-names which will be applied in the class="" attribute
11437
11438     You should not maintain this array yourself, rather, you should use
11439     the addClass() method of Ember.RenderBuffer.
11440
11441     @property elementClasses
11442     @type Array
11443     @default []
11444   */
11445   elementClasses: null,
11446
11447   /**
11448     The id in of the element, to be applied in the id="" attribute
11449
11450     You should not set this property yourself, rather, you should use
11451     the id() method of Ember.RenderBuffer.
11452
11453     @property elementId
11454     @type String
11455     @default null
11456   */
11457   elementId: null,
11458
11459   /**
11460     A hash keyed on the name of the attribute and whose value will be
11461     applied to that attribute. For example, if you wanted to apply a
11462     data-view="Foo.bar" property to an element, you would set the
11463     elementAttributes hash to {'data-view':'Foo.bar'}
11464
11465     You should not maintain this hash yourself, rather, you should use
11466     the attr() method of Ember.RenderBuffer.
11467
11468     @property elementAttributes
11469     @type Hash
11470     @default {}
11471   */
11472   elementAttributes: null,
11473
11474   /**
11475     The tagname of the element an instance of Ember.RenderBuffer represents.
11476
11477     Usually, this gets set as the first parameter to Ember.RenderBuffer. For
11478     example, if you wanted to create a `p` tag, then you would call
11479
11480       Ember.RenderBuffer('p')
11481
11482     @property elementTag
11483     @type String
11484     @default null
11485   */
11486   elementTag: null,
11487
11488   /**
11489     A hash keyed on the name of the style attribute and whose value will
11490     be applied to that attribute. For example, if you wanted to apply a
11491     background-color:black;" style to an element, you would set the
11492     elementStyle hash to {'background-color':'black'}
11493
11494     You should not maintain this hash yourself, rather, you should use
11495     the style() method of Ember.RenderBuffer.
11496
11497     @property elementStyle
11498     @type Hash
11499     @default {}
11500   */
11501   elementStyle: null,
11502
11503   /**
11504     Nested RenderBuffers will set this to their parent RenderBuffer
11505     instance.
11506
11507     @property parentBuffer
11508     @type Ember._RenderBuffer
11509   */
11510   parentBuffer: null,
11511
11512   /**
11513     Adds a string of HTML to the RenderBuffer.
11514
11515     @method push
11516     @param {String} string HTML to push into the buffer
11517     @chainable
11518   */
11519   push: function(string) {
11520     this.childBuffers.push(String(string));
11521     return this;
11522   },
11523
11524   /**
11525     Adds a class to the buffer, which will be rendered to the class attribute.
11526
11527     @method addClass
11528     @param {String} className Class name to add to the buffer
11529     @chainable
11530   */
11531   addClass: function(className) {
11532     // lazily create elementClasses
11533     var elementClasses = this.elementClasses = (this.elementClasses || new ClassSet());
11534     this.elementClasses.add(className);
11535
11536     return this;
11537   },
11538
11539   /**
11540     Sets the elementID to be used for the element.
11541
11542     @method id
11543     @param {String} id
11544     @chainable
11545   */
11546   id: function(id) {
11547     this.elementId = id;
11548     return this;
11549   },
11550
11551   // duck type attribute functionality like jQuery so a render buffer
11552   // can be used like a jQuery object in attribute binding scenarios.
11553
11554   /**
11555     Adds an attribute which will be rendered to the element.
11556
11557     @method attr
11558     @param {String} name The name of the attribute
11559     @param {String} value The value to add to the attribute
11560     @chainable
11561     @return {Ember.RenderBuffer|String} this or the current attribute value
11562   */
11563   attr: function(name, value) {
11564     var attributes = this.elementAttributes = (this.elementAttributes || {});
11565
11566     if (arguments.length === 1) {
11567       return attributes[name];
11568     } else {
11569       attributes[name] = value;
11570     }
11571
11572     return this;
11573   },
11574
11575   /**
11576     Remove an attribute from the list of attributes to render.
11577
11578     @method removeAttr
11579     @param {String} name The name of the attribute
11580     @chainable
11581   */
11582   removeAttr: function(name) {
11583     var attributes = this.elementAttributes;
11584     if (attributes) { delete attributes[name]; }
11585
11586     return this;
11587   },
11588
11589   /**
11590     Adds a style to the style attribute which will be rendered to the element.
11591
11592     @method style
11593     @param {String} name Name of the style
11594     @param {String} value
11595     @chainable
11596   */
11597   style: function(name, value) {
11598     var style = this.elementStyle = (this.elementStyle || {});
11599
11600     this.elementStyle[name] = value;
11601     return this;
11602   },
11603
11604   /**
11605     @private
11606
11607     Create a new child render buffer from a parent buffer. Optionally set
11608     additional properties on the buffer. Optionally invoke a callback
11609     with the newly created buffer.
11610
11611     This is a primitive method used by other public methods: `begin`,
11612     `prepend`, `replaceWith`, `insertAfter`.
11613
11614     @method newBuffer
11615     @param {String} tagName Tag name to use for the child buffer's element
11616     @param {Ember._RenderBuffer} parent The parent render buffer that this
11617       buffer should be appended to.
11618     @param {Function} fn A callback to invoke with the newly created buffer.
11619     @param {Object} other Additional properties to add to the newly created
11620       buffer.
11621   */
11622   newBuffer: function(tagName, parent, fn, other) {
11623     var buffer = new Ember._RenderBuffer(tagName);
11624     buffer.parentBuffer = parent;
11625
11626     if (other) { Ember.$.extend(buffer, other); }
11627     if (fn) { fn.call(this, buffer); }
11628
11629     return buffer;
11630   },
11631
11632   /**
11633     @private
11634
11635     Replace the current buffer with a new buffer. This is a primitive
11636     used by `remove`, which passes `null` for `newBuffer`, and `replaceWith`,
11637     which passes the new buffer it created.
11638
11639     @method replaceWithBuffer
11640     @param {Ember._RenderBuffer} buffer The buffer to insert in place of
11641       the existing buffer.
11642   */
11643   replaceWithBuffer: function(newBuffer) {
11644     var parent = this.parentBuffer;
11645     if (!parent) { return; }
11646
11647     var childBuffers = parent.childBuffers;
11648
11649     var index = indexOf.call(childBuffers, this);
11650
11651     if (newBuffer) {
11652       childBuffers.splice(index, 1, newBuffer);
11653     } else {
11654       childBuffers.splice(index, 1);
11655     }
11656   },
11657
11658   /**
11659     Creates a new Ember.RenderBuffer object with the provided tagName as
11660     the element tag and with its parentBuffer property set to the current
11661     Ember.RenderBuffer.
11662
11663     @method begin
11664     @param {String} tagName Tag name to use for the child buffer's element
11665     @return {Ember.RenderBuffer} A new RenderBuffer object
11666   */
11667   begin: function(tagName) {
11668     return this.newBuffer(tagName, this, function(buffer) {
11669       this.childBuffers.push(buffer);
11670     });
11671   },
11672
11673   /**
11674     Prepend a new child buffer to the current render buffer.
11675
11676     @method prepend
11677     @param {String} tagName Tag name to use for the child buffer's element
11678   */
11679   prepend: function(tagName) {
11680     return this.newBuffer(tagName, this, function(buffer) {
11681       this.childBuffers.splice(0, 0, buffer);
11682     });
11683   },
11684
11685   /**
11686     Replace the current buffer with a new render buffer.
11687
11688     @method replaceWith
11689     @param {String} tagName Tag name to use for the new buffer's element
11690   */
11691   replaceWith: function(tagName) {
11692     var parentBuffer = this.parentBuffer;
11693
11694     return this.newBuffer(tagName, parentBuffer, function(buffer) {
11695       this.replaceWithBuffer(buffer);
11696     });
11697   },
11698
11699   /**
11700     Insert a new render buffer after the current render buffer.
11701
11702     @method insertAfter
11703     @param {String} tagName Tag name to use for the new buffer's element
11704   */
11705   insertAfter: function(tagName) {
11706     var parentBuffer = get(this, 'parentBuffer');
11707
11708     return this.newBuffer(tagName, parentBuffer, function(buffer) {
11709       var siblings = parentBuffer.childBuffers;
11710       var index = indexOf.call(siblings, this);
11711       siblings.splice(index + 1, 0, buffer);
11712     });
11713   },
11714
11715   /**
11716     Closes the current buffer and adds its content to the parentBuffer.
11717
11718     @method end
11719     @return {Ember.RenderBuffer} The parentBuffer, if one exists. Otherwise, this
11720   */
11721   end: function() {
11722     var parent = this.parentBuffer;
11723     return parent || this;
11724   },
11725
11726   remove: function() {
11727     this.replaceWithBuffer(null);
11728   },
11729
11730   /**
11731     @method element
11732     @return {DOMElement} The element corresponding to the generated HTML
11733       of this buffer
11734   */
11735   element: function() {
11736     return Ember.$(this.string())[0];
11737   },
11738
11739   /**
11740     Generates the HTML content for this buffer.
11741
11742     @method string
11743     @return {String} The generated HTMl
11744   */
11745   string: function() {
11746     var content = '', tag = this.elementTag, openTag;
11747
11748     if (tag) {
11749       var id = this.elementId,
11750           classes = this.elementClasses,
11751           attrs = this.elementAttributes,
11752           style = this.elementStyle,
11753           styleBuffer = '', prop;
11754
11755       openTag = ["<" + tag];
11756
11757       if (id) { openTag.push('id="' + this._escapeAttribute(id) + '"'); }
11758       if (classes) { openTag.push('class="' + this._escapeAttribute(classes.toDOM()) + '"'); }
11759
11760       if (style) {
11761         for (prop in style) {
11762           if (style.hasOwnProperty(prop)) {
11763             styleBuffer += (prop + ':' + this._escapeAttribute(style[prop]) + ';');
11764           }
11765         }
11766
11767         openTag.push('style="' + styleBuffer + '"');
11768       }
11769
11770       if (attrs) {
11771         for (prop in attrs) {
11772           if (attrs.hasOwnProperty(prop)) {
11773             openTag.push(prop + '="' + this._escapeAttribute(attrs[prop]) + '"');
11774           }
11775         }
11776       }
11777
11778       openTag = openTag.join(" ") + '>';
11779     }
11780
11781     var childBuffers = this.childBuffers;
11782
11783     Ember.ArrayPolyfills.forEach.call(childBuffers, function(buffer) {
11784       var stringy = typeof buffer === 'string';
11785       content += (stringy ? buffer : buffer.string());
11786     });
11787
11788     if (tag) {
11789       return openTag + content + "</" + tag + ">";
11790     } else {
11791       return content;
11792     }
11793   },
11794
11795   _escapeAttribute: function(value) {
11796     // Stolen shamelessly from Handlebars
11797
11798     var escape = {
11799       "<": "&lt;",
11800       ">": "&gt;",
11801       '"': "&quot;",
11802       "'": "&#x27;",
11803       "`": "&#x60;"
11804     };
11805
11806     var badChars = /&(?!\w+;)|[<>"'`]/g;
11807     var possible = /[&<>"'`]/;
11808
11809     var escapeChar = function(chr) {
11810       return escape[chr] || "&amp;";
11811     };
11812
11813     var string = value.toString();
11814
11815     if(!possible.test(string)) { return string; }
11816     return string.replace(badChars, escapeChar);
11817   }
11818
11819 };
11820
11821 })();
11822
11823
11824
11825 (function() {
11826 /**
11827 @module ember
11828 @submodule ember-views
11829 */
11830
11831 var get = Ember.get, set = Ember.set, fmt = Ember.String.fmt;
11832
11833 /**
11834   Ember.EventDispatcher handles delegating browser events to their corresponding
11835   Ember.Views. For example, when you click on a view, Ember.EventDispatcher ensures
11836   that that view's `mouseDown` method gets called.
11837
11838   @class EventDispatcher
11839   @namespace Ember
11840   @private
11841   @extends Ember.Object
11842 */
11843 Ember.EventDispatcher = Ember.Object.extend(
11844 /** @scope Ember.EventDispatcher.prototype */{
11845
11846   /**
11847     @private
11848
11849     The root DOM element to which event listeners should be attached. Event
11850     listeners will be attached to the document unless this is overridden.
11851
11852     Can be specified as a DOMElement or a selector string.
11853
11854     The default body is a string since this may be evaluated before document.body
11855     exists in the DOM.
11856
11857     @property rootElement
11858     @type DOMElement
11859     @default 'body'
11860   */
11861   rootElement: 'body',
11862
11863   /**
11864     @private
11865
11866     Sets up event listeners for standard browser events.
11867
11868     This will be called after the browser sends a DOMContentReady event. By
11869     default, it will set up all of the listeners on the document body. If you
11870     would like to register the listeners on a different element, set the event
11871     dispatcher's `root` property.
11872
11873     @method setup
11874     @param addedEvents {Hash}
11875   */
11876   setup: function(addedEvents) {
11877     var event, events = {
11878       touchstart  : 'touchStart',
11879       touchmove   : 'touchMove',
11880       touchend    : 'touchEnd',
11881       touchcancel : 'touchCancel',
11882       keydown     : 'keyDown',
11883       keyup       : 'keyUp',
11884       keypress    : 'keyPress',
11885       mousedown   : 'mouseDown',
11886       mouseup     : 'mouseUp',
11887       contextmenu : 'contextMenu',
11888       click       : 'click',
11889       dblclick    : 'doubleClick',
11890       mousemove   : 'mouseMove',
11891       focusin     : 'focusIn',
11892       focusout    : 'focusOut',
11893       mouseenter  : 'mouseEnter',
11894       mouseleave  : 'mouseLeave',
11895       submit      : 'submit',
11896       input       : 'input',
11897       change      : 'change',
11898       dragstart   : 'dragStart',
11899       drag        : 'drag',
11900       dragenter   : 'dragEnter',
11901       dragleave   : 'dragLeave',
11902       dragover    : 'dragOver',
11903       drop        : 'drop',
11904       dragend     : 'dragEnd'
11905     };
11906
11907     Ember.$.extend(events, addedEvents || {});
11908
11909     var rootElement = Ember.$(get(this, 'rootElement'));
11910
11911     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'));
11912     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);
11913     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);
11914
11915     rootElement.addClass('ember-application');
11916
11917     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'));
11918
11919     for (event in events) {
11920       if (events.hasOwnProperty(event)) {
11921         this.setupHandler(rootElement, event, events[event]);
11922       }
11923     }
11924   },
11925
11926   /**
11927     @private
11928
11929     Registers an event listener on the document. If the given event is
11930     triggered, the provided event handler will be triggered on the target
11931     view.
11932
11933     If the target view does not implement the event handler, or if the handler
11934     returns false, the parent view will be called. The event will continue to
11935     bubble to each successive parent view until it reaches the top.
11936
11937     For example, to have the `mouseDown` method called on the target view when
11938     a `mousedown` event is received from the browser, do the following:
11939
11940         setupHandler('mousedown', 'mouseDown');
11941
11942     @method setupHandler
11943     @param {Element} rootElement
11944     @param {String} event the browser-originated event to listen to
11945     @param {String} eventName the name of the method to call on the view
11946   */
11947   setupHandler: function(rootElement, event, eventName) {
11948     var self = this;
11949
11950     rootElement.delegate('.ember-view', event + '.ember', function(evt, triggeringManager) {
11951       return Ember.handleErrors(function() {
11952         var view = Ember.View.views[this.id],
11953             result = true, manager = null;
11954
11955         manager = self._findNearestEventManager(view,eventName);
11956
11957         if (manager && manager !== triggeringManager) {
11958           result = self._dispatchEvent(manager, evt, eventName, view);
11959         } else if (view) {
11960           result = self._bubbleEvent(view,evt,eventName);
11961         } else {
11962           evt.stopPropagation();
11963         }
11964
11965         return result;
11966       }, this);
11967     });
11968
11969     rootElement.delegate('[data-ember-action]', event + '.ember', function(evt) {
11970       return Ember.handleErrors(function() {
11971         var actionId = Ember.$(evt.currentTarget).attr('data-ember-action'),
11972             action   = Ember.Handlebars.ActionHelper.registeredActions[actionId],
11973             handler  = action.handler;
11974
11975         if (action.eventName === eventName) {
11976           return handler(evt);
11977         }
11978       }, this);
11979     });
11980   },
11981
11982   _findNearestEventManager: function(view, eventName) {
11983     var manager = null;
11984
11985     while (view) {
11986       manager = get(view, 'eventManager');
11987       if (manager && manager[eventName]) { break; }
11988
11989       view = get(view, 'parentView');
11990     }
11991
11992     return manager;
11993   },
11994
11995   _dispatchEvent: function(object, evt, eventName, view) {
11996     var result = true;
11997
11998     var handler = object[eventName];
11999     if (Ember.typeOf(handler) === 'function') {
12000       result = handler.call(object, evt, view);
12001       // Do not preventDefault in eventManagers.
12002       evt.stopPropagation();
12003     }
12004     else {
12005       result = this._bubbleEvent(view, evt, eventName);
12006     }
12007
12008     return result;
12009   },
12010
12011   _bubbleEvent: function(view, evt, eventName) {
12012     return Ember.run(function() {
12013       return view.handleEvent(eventName, evt);
12014     });
12015   },
12016
12017   destroy: function() {
12018     var rootElement = get(this, 'rootElement');
12019     Ember.$(rootElement).undelegate('.ember').removeClass('ember-application');
12020     return this._super();
12021   }
12022 });
12023
12024 })();
12025
12026
12027
12028 (function() {
12029 /**
12030 @module ember
12031 @submodule ember-views
12032 */
12033
12034 // Add a new named queue for rendering views that happens
12035 // after bindings have synced.
12036 var queues = Ember.run.queues;
12037 queues.splice(Ember.$.inArray('actions', queues)+1, 0, 'render');
12038
12039 })();
12040
12041
12042
12043 (function() {
12044 /**
12045 @module ember
12046 @submodule ember-views
12047 */
12048
12049 var get = Ember.get, set = Ember.set;
12050
12051 // Original class declaration and documentation in runtime/lib/controllers/controller.js
12052 // NOTE: It may be possible with YUIDoc to combine docs in two locations
12053
12054 /**
12055 Additional methods for the ControllerMixin
12056
12057 @class ControllerMixin
12058 @namespace Ember
12059 */
12060 Ember.ControllerMixin.reopen({
12061
12062   target: null,
12063   controllers: null,
12064   namespace: null,
12065   view: null,
12066
12067   /**
12068     `connectOutlet` creates a new instance of a provided view
12069     class, wires it up to its associated controller, and
12070     assigns the new view to a property on the current controller.
12071
12072     The purpose of this method is to enable views that use
12073     outlets to quickly assign new views for a given outlet.
12074
12075     For example, an application view's template may look like
12076     this:
12077
12078     ``` handlebars
12079     <h1>My Blog</h1>
12080     {{outlet}}
12081     ```
12082
12083     The view for this outlet is specified by assigning a
12084     `view` property to the application's controller. The
12085     following code will assign a new `App.PostsView` to
12086     that outlet:
12087
12088     ``` javascript
12089     applicationController.connectOutlet('posts');
12090     ```
12091
12092     In general, you will also want to assign a controller
12093     to the newly created view. By convention, a controller
12094     named `postsController` will be assigned as the view's
12095     controller.
12096
12097     In an application initialized using `app.initialize(router)`,
12098     `connectOutlet` will look for `postsController` on the
12099     router. The initialization process will automatically
12100     create an instance of `App.PostsController` called
12101     `postsController`, so you don't need to do anything
12102     beyond `connectOutlet` to assign your view and wire it
12103     up to its associated controller.
12104
12105     You can supply a `content` for the controller by supplying
12106     a final argument after the view class:
12107
12108     ``` javascript
12109     applicationController.connectOutlet('posts', App.Post.find());
12110     ```
12111
12112     You can specify a particular outlet to use. For example, if your main
12113     template looks like:
12114
12115     ``` handlebars
12116     <h1>My Blog</h1>
12117     {{outlet master}}
12118     {{outlet detail}}
12119     ```
12120
12121     You can assign an `App.PostsView` to the master outlet:
12122
12123     ``` javascript
12124     applicationController.connectOutlet({
12125       name: 'posts',
12126       outletName: 'master',
12127       context: App.Post.find()
12128     });
12129     ```
12130
12131     You can write this as:
12132
12133     ``` javascript
12134     applicationController.connectOutlet('master', 'posts', App.Post.find());
12135     ```
12136
12137
12138     @method connectOutlet
12139     @param {String} outletName a name for the outlet to set
12140     @param {String} name a view/controller pair name
12141     @param {Object} context a context object to assign to the
12142       controller's `content` property, if a controller can be
12143       found (optional)
12144   */
12145   connectOutlet: function(name, context) {
12146     // Normalize arguments. Supported arguments:
12147     //
12148     // name
12149     // name, context
12150     // outletName, name
12151     // outletName, name, context
12152     // options
12153     //
12154     // The options hash has the following keys:
12155     //
12156     //   name: the name of the controller and view
12157     //     to use. If this is passed, the name
12158     //     determines the view and controller.
12159     //   outletName: the name of the outlet to
12160     //     fill in. default: 'view'
12161     //   viewClass: the class of the view to instantiate
12162     //   controller: the controller instance to pass
12163     //     to the view
12164     //   context: an object that should become the
12165     //     controller's `content` and thus the
12166     //     template's context.
12167
12168     var outletName, viewClass, view, controller, options;
12169
12170     if (Ember.typeOf(context) === 'string') {
12171       outletName = name;
12172       name = context;
12173       context = arguments[2];
12174     }
12175
12176     if (arguments.length === 1) {
12177       if (Ember.typeOf(name) === 'object') {
12178         options = name;
12179         outletName = options.outletName;
12180         name = options.name;
12181         viewClass = options.viewClass;
12182         controller = options.controller;
12183         context = options.context;
12184       }
12185     } else {
12186       options = {};
12187     }
12188
12189     outletName = outletName || 'view';
12190     
12191     Ember.assert("The viewClass is either missing or the one provided did not resolve to a view", !!name || (!name && !!viewClass));
12192     
12193     Ember.assert("You must supply a name or a viewClass to connectOutlet, but not both", (!!name && !viewClass && !controller) || (!name && !!viewClass));
12194
12195     if (name) {
12196       var namespace = get(this, 'namespace'),
12197           controllers = get(this, 'controllers');
12198
12199       var viewClassName = name.charAt(0).toUpperCase() + name.substr(1) + "View";
12200       viewClass = get(namespace, viewClassName);
12201       controller = get(controllers, name + 'Controller');
12202
12203       Ember.assert("The name you supplied " + name + " did not resolve to a view " + viewClassName, !!viewClass);
12204       Ember.assert("The name you supplied " + name + " did not resolve to a controller " + name + 'Controller', (!!controller && !!context) || !context);
12205     }
12206
12207     if (controller && context) { set(controller, 'content', context); }
12208
12209     view = this.createOutletView(outletName, viewClass);
12210
12211     if (controller) { set(view, 'controller', controller); }
12212     set(this, outletName, view);
12213
12214     return view;
12215   },
12216
12217   /**
12218     Convenience method to connect controllers. This method makes other controllers
12219     available on the controller the method was invoked on.
12220
12221     For example, to make the `personController` and the `postController` available
12222     on the `overviewController`, you would call:
12223
12224         overviewController.connectControllers('person', 'post');
12225
12226     @method connectControllers
12227     @param {String...} controllerNames the controllers to make available
12228   */
12229   connectControllers: function() {
12230     var controllers = get(this, 'controllers'),
12231         controllerNames = Array.prototype.slice.apply(arguments),
12232         controllerName;
12233
12234     for (var i=0, l=controllerNames.length; i<l; i++) {
12235       controllerName = controllerNames[i] + 'Controller';
12236       set(this, controllerName, get(controllers, controllerName));
12237     }
12238   },
12239
12240   /**
12241     `disconnectOutlet` removes previously attached view from given outlet.
12242
12243     @method disconnectOutlet
12244     @param  {String} outletName the outlet name. (optional)
12245    */
12246   disconnectOutlet: function(outletName) {
12247     outletName = outletName || 'view';
12248
12249     set(this, outletName, null);
12250   },
12251
12252   /**
12253     `createOutletView` is a hook you may want to override if you need to do
12254     something special with the view created for the outlet. For example
12255     you may want to implement views sharing across outlets.
12256
12257     @method createOutletView
12258     @param outletName {String}
12259     @param viewClass {Ember.View}
12260   */
12261   createOutletView: function(outletName, viewClass) {
12262     return viewClass.create();
12263   }
12264 });
12265
12266 })();
12267
12268
12269
12270 (function() {
12271
12272 })();
12273
12274
12275
12276 (function() {
12277 /**
12278 @module ember
12279 @submodule ember-views
12280 */
12281
12282 var get = Ember.get, set = Ember.set, addObserver = Ember.addObserver, removeObserver = Ember.removeObserver;
12283 var meta = Ember.meta, fmt = Ember.String.fmt;
12284 var a_slice = [].slice;
12285 var a_forEach = Ember.EnumerableUtils.forEach;
12286
12287 var childViewsProperty = Ember.computed(function() {
12288   var childViews = this._childViews;
12289
12290   var ret = Ember.A();
12291
12292   a_forEach(childViews, function(view) {
12293     if (view.isVirtual) {
12294       ret.pushObjects(get(view, 'childViews'));
12295     } else {
12296       ret.push(view);
12297     }
12298   });
12299
12300   return ret;
12301 }).property().cacheable();
12302
12303 var VIEW_PRESERVES_CONTEXT = Ember.VIEW_PRESERVES_CONTEXT;
12304 Ember.warn("The way that the {{view}} helper affects templates is about to change. Previously, templates inside child views would use the new view as the context. Soon, views will preserve their parent context when rendering their template. You can opt-in early to the new behavior by setting `ENV.VIEW_PRESERVES_CONTEXT = true`. For more information, see https://gist.github.com/2494968. You should update your templates as soon as possible; this default will change soon, and the option will be eliminated entirely before the 1.0 release.", VIEW_PRESERVES_CONTEXT);
12305
12306 /**
12307   Global hash of shared templates. This will automatically be populated
12308   by the build tools so that you can store your Handlebars templates in
12309   separate files that get loaded into JavaScript at buildtime.
12310
12311   @property TEMPLATES
12312   @for Ember
12313   @type Hash
12314 */
12315 Ember.TEMPLATES = {};
12316
12317 var invokeForState = {
12318   preRender: {},
12319   inBuffer: {},
12320   hasElement: {},
12321   inDOM: {},
12322   destroyed: {}
12323 };
12324
12325 /**
12326   `Ember.View` is the class in Ember responsible for encapsulating templates of HTML
12327   content, combining templates with data to render as sections of a page's DOM, and
12328   registering and responding to user-initiated events.
12329   
12330   ## HTML Tag
12331   The default HTML tag name used for a view's DOM representation is `div`. This can be
12332   customized by setting the `tagName` property. The following view class:
12333
12334   ``` javascript
12335   ParagraphView = Ember.View.extend({
12336     tagName: 'em'
12337   });
12338   ```
12339
12340   Would result in instances with the following HTML:
12341
12342   ``` html
12343   <em id="ember1" class="ember-view"></em>
12344   ```
12345
12346   ## HTML `class` Attribute
12347   The HTML `class` attribute of a view's tag can be set by providing a `classNames` property
12348   that is set to an array of strings:
12349
12350   ``` javascript
12351   MyView = Ember.View.extend({
12352     classNames: ['my-class', 'my-other-class']
12353   });
12354   ```
12355
12356   Will result in view instances with an HTML representation of:
12357
12358   ``` html
12359   <div id="ember1" class="ember-view my-class my-other-class"></div>
12360   ```
12361
12362   `class` attribute values can also be set by providing a `classNameBindings` property
12363   set to an array of properties names for the view. The return value of these properties 
12364   will be added as part of the value for the view's `class` attribute. These properties
12365   can be computed properties:
12366
12367   ``` javascript
12368   MyView = Ember.View.extend({
12369     classNameBindings: ['propertyA', 'propertyB'],
12370     propertyA: 'from-a',
12371     propertyB: function(){
12372       if(someLogic){ return 'from-b'; }
12373     }.property()
12374   });
12375   ```
12376
12377   Will result in view instances with an HTML representation of:
12378
12379   ``` html
12380   <div id="ember1" class="ember-view from-a from-b"></div>
12381   ```
12382
12383   If the value of a class name binding returns a boolean the property name itself
12384   will be used as the class name if the property is true. The class name will
12385   not be added if the value is `false` or `undefined`.
12386
12387   ``` javascript
12388   MyView = Ember.View.extend({
12389     classNameBindings: ['hovered'],
12390     hovered: true
12391   });
12392   ```
12393
12394   Will result in view instances with an HTML representation of:
12395
12396   ``` html
12397   <div id="ember1" class="ember-view hovered"></div>
12398   ```
12399
12400   When using boolean class name bindings you can supply a string value other than the 
12401   property name for use as the `class` HTML attribute by appending the preferred value after
12402   a ":" character when defining the binding:
12403
12404   ``` javascript
12405   MyView = Ember.View.extend({
12406     classNameBindings: ['awesome:so-very-cool'],
12407     awesome: true
12408   });
12409   ```
12410
12411   Will result in view instances with an HTML representation of:
12412
12413   ``` html
12414   <div id="ember1" class="ember-view so-very-cool"></div>
12415   ```
12416
12417
12418   Boolean value class name bindings whose property names are in a camelCase-style
12419   format will be converted to a dasherized format:
12420
12421   ``` javascript
12422   MyView = Ember.View.extend({
12423     classNameBindings: ['isUrgent'],
12424     isUrgent: true
12425   });
12426   ```
12427
12428   Will result in view instances with an HTML representation of:
12429
12430   ``` html
12431   <div id="ember1" class="ember-view is-urgent"></div>
12432   ```
12433
12434
12435   Class name bindings can also refer to object values that are found by
12436   traversing a path relative to the view itself:
12437
12438   ``` javascript
12439   MyView = Ember.View.extend({
12440     classNameBindings: ['messages.empty']
12441     messages: Ember.Object.create({
12442       empty: true
12443     })
12444   });
12445   ```
12446
12447   Will result in view instances with an HTML representation of:
12448
12449   ``` html
12450   <div id="ember1" class="ember-view empty"></div>
12451   ```
12452
12453
12454   If you want to add a class name for a property which evaluates to true and
12455   and a different class name if it evaluates to false, you can pass a binding
12456   like this:
12457
12458   ```
12459   // Applies 'enabled' class when isEnabled is true and 'disabled' when isEnabled is false
12460   Ember.View.create({
12461     classNameBindings: ['isEnabled:enabled:disabled']
12462     isEnabled: true
12463   });
12464   ```
12465
12466   Will result in view instances with an HTML representation of:
12467
12468   ``` html
12469   <div id="ember1" class="ember-view enabled"></div>
12470   ``` 
12471
12472   When isEnabled is `false`, the resulting HTML reprensentation looks like this:
12473
12474   ``` html
12475   <div id="ember1" class="ember-view disabled"></div>
12476   ```
12477
12478   This syntax offers the convenience to add a class if a property is `false`:
12479
12480   ``` javascript
12481   // Applies no class when isEnabled is true and class 'disabled' when isEnabled is false
12482   Ember.View.create({
12483     classNameBindings: ['isEnabled::disabled']
12484     isEnabled: true
12485   });
12486   ```
12487
12488   Will result in view instances with an HTML representation of:
12489
12490   ``` html
12491   <div id="ember1" class="ember-view"></div>
12492   ```
12493
12494   When the `isEnabled` property on the view is set to `false`, it will result
12495   in view instances with an HTML representation of:
12496
12497   ``` html
12498   <div id="ember1" class="ember-view disabled"></div>
12499   ```
12500
12501   Updates to the the value of a class name binding will result in automatic update 
12502   of the  HTML `class` attribute in the view's rendered HTML representation.
12503   If the value becomes  `false` or `undefined` the class name will be removed.
12504
12505   Both `classNames` and `classNameBindings` are concatenated properties. 
12506   See `Ember.Object` documentation for more information about concatenated properties.
12507
12508   ## HTML Attributes
12509
12510   The HTML attribute section of a view's tag can be set by providing an `attributeBindings`
12511   property set to an array of property names on the view. The return value of these properties
12512   will be used as the value of the view's HTML associated attribute:
12513
12514   ``` javascript
12515   AnchorView = Ember.View.extend({
12516     tagName: 'a',
12517     attributeBindings: ['href'],
12518     href: 'http://google.com'
12519   });
12520   ```
12521
12522   Will result in view instances with an HTML representation of:
12523
12524   ``` html
12525   <a id="ember1" class="ember-view" href="http://google.com"></a>
12526   ```
12527
12528   If the return value of an `attributeBindings` monitored property is a boolean
12529   the property will follow HTML's pattern of repeating the attribute's name as
12530   its value:
12531
12532   ``` javascript
12533   MyTextInput = Ember.View.extend({
12534     tagName: 'input',
12535     attributeBindings: ['disabled'],
12536     disabled: true
12537   });
12538   ```
12539
12540   Will result in view instances with an HTML representation of:
12541
12542   ``` html
12543   <input id="ember1" class="ember-view" disabled="disabled" />
12544   ```
12545
12546   `attributeBindings` can refer to computed properties:
12547
12548   ``` javascript
12549   MyTextInput = Ember.View.extend({
12550     tagName: 'input',
12551     attributeBindings: ['disabled'],
12552     disabled: function(){
12553       if (someLogic) {
12554         return true;
12555       } else {
12556         return false;
12557       }
12558     }.property()
12559   });
12560   ```
12561
12562   Updates to the the property of an attribute binding will result in automatic update 
12563   of the  HTML attribute in the view's rendered HTML representation.
12564
12565   `attributeBindings` is a concatenated property. See `Ember.Object` documentation
12566   for more information about concatenated properties.
12567
12568   ## Templates
12569   The HTML contents of a view's rendered representation are determined by its template.
12570   Templates can be any function that accepts an optional context parameter and returns
12571   a string of HTML that will be inserted within the view's tag. Most
12572   typically in Ember this function will be a compiled Ember.Handlebars template.
12573
12574   ``` javascript
12575   AView = Ember.View.extend({
12576     template: Ember.Handlebars.compile('I am the template')
12577   });
12578   ```
12579
12580   Will result in view instances with an HTML representation of:
12581
12582   ``` html
12583   <div id="ember1" class="ember-view">I am the template</div>
12584   ``` 
12585
12586   The default context of the compiled template will be the view instance itself:
12587
12588   ``` javascript
12589   AView = Ember.View.extend({
12590     template: Ember.Handlebars.compile('Hello {{excitedGreeting}}')
12591   });
12592
12593   aView = AView.create({
12594     content: Ember.Object.create({
12595       firstName: 'Barry'
12596     })
12597     excitedGreeting: function(){
12598       return this.get("content.firstName") + "!!!"
12599     }
12600   });
12601   ```
12602
12603   Will result in an HTML representation of:
12604
12605   ``` html
12606   <div id="ember1" class="ember-view">Hello Barry!!!</div>
12607   ```
12608
12609   Within an Ember application is more common to define a Handlebars templates as
12610   part of a page:
12611
12612   ``` handlebars
12613   <script type='text/x-handlebars' data-template-name='some-template'>
12614     Hello
12615   </script>
12616   ```
12617
12618   And associate it by name using a view's `templateName` property:
12619
12620   ``` javascript
12621   AView = Ember.View.extend({
12622     templateName: 'some-template'
12623   });
12624   ```
12625
12626   Using a value for `templateName` that does not have a Handlebars template with a
12627   matching `data-template-name` attribute will throw an error.
12628
12629   Assigning a value to both `template` and `templateName` properties will throw an error.
12630
12631   For views classes that may have a template later defined (e.g. as the block portion of a `{{view}}`
12632   Handlebars helper call in another template or in a subclass), you can provide a `defaultTemplate`
12633   property set to compiled template function. If a template is not later provided for the view
12634   instance the `defaultTemplate` value will be used:
12635
12636   ``` javascript
12637   AView = Ember.View.extend({
12638     defaultTemplate: Ember.Handlebars.compile('I was the default'),
12639     template: null,
12640     templateName: null
12641   });
12642   ```
12643
12644   Will result in instances with an HTML representation of:
12645
12646   ``` html
12647   <div id="ember1" class="ember-view">I was the default</div>
12648   ```
12649
12650   If a `template` or `templateName` is provided it will take precedence over `defaultTemplate`:
12651
12652   ``` javascript
12653   AView = Ember.View.extend({
12654     defaultTemplate: Ember.Handlebars.compile('I was the default')
12655   });
12656
12657   aView = AView.create({
12658     template: Ember.Handlebars.compile('I was the template, not default')
12659   });
12660   ```
12661
12662   Will result in the following HTML representation when rendered:
12663
12664   ``` html
12665   <div id="ember1" class="ember-view">I was the template, not default</div>
12666   ```
12667
12668   ## Layouts
12669
12670   Views can have a secondary template that wraps their main template. Like
12671   primary templates, layouts can be any function that  accepts an optional context
12672   parameter and returns a string of HTML that will be inserted inside view's tag. Views whose HTML
12673   element is self closing (e.g. `<input />`) cannot have a layout and this property will be ignored.
12674   
12675   Most typically in Ember a layout will be a compiled Ember.Handlebars template.
12676
12677   A view's layout can be set directly with the `layout` property or reference an
12678   existing Handlebars template by name with the `layoutName` property.
12679
12680   A template used as a layout must contain a single use of the Handlebars `{{yield}}`
12681   helper. The HTML contents of a view's rendered `template` will be inserted at this location:
12682
12683   ``` javascript
12684   AViewWithLayout = Ember.View.extend({
12685     layout: Ember.Handlebars.compile("<div class='my-decorative-class'>{{yield}}</div>")
12686     template: Ember.Handlebars.compile("I got wrapped"),
12687   });
12688   ```
12689
12690   Will result in view instances with an HTML representation of:
12691
12692   ``` html
12693   <div id="ember1" class="ember-view">
12694     <div class="my-decorative-class">
12695       I got wrapped
12696     </div>
12697   </div>
12698   ```
12699
12700   See `Handlebars.helpers.yield` for more information.
12701
12702   ## Responding to Browser Events
12703
12704   Views can respond to user-initiated events in one of three ways: method implementation, 
12705   through an event manager, and through `{{action}}` helper use in their template or layout.
12706
12707   ### Method Implementation
12708
12709   Views can respond to user-initiated events by implementing a method that matches the
12710   event name. A `jQuery.Event` object will be passed as the argument to this method.
12711
12712   ``` javascript
12713   AView = Ember.View.extend({
12714     click: function(event){
12715       // will be called when when an instance's
12716       // rendered element is clicked
12717     }
12718   });
12719   ```
12720
12721   ### Event Managers
12722
12723   Views can define an object as their `eventManager` property. This object can then
12724   implement methods that match the desired event names. Matching events that occur
12725   on the view's rendered HTML or the rendered HTML of any of its DOM descendants 
12726   will trigger this method.  A `jQuery.Event` object will be passed as the first 
12727   argument to the method and an  `Ember.View` object as the second. The `Ember.View`
12728   will be the view whose rendered HTML was interacted with. This may be the view with
12729   the `eventManager` property or one of its descendent views.
12730
12731   ``` javascript
12732   AView = Ember.View.extend({
12733     eventManager: Ember.Object.create({
12734       doubleClick: function(event, view){
12735         // will be called when when an instance's
12736         // rendered element or any rendering
12737         // of this views's descendent
12738         // elements is clicked
12739       }
12740     })
12741   });
12742   ```
12743
12744
12745   An event defined for an event manager takes precedence over events of the same
12746   name handled through methods on the view.
12747
12748   ``` javascript
12749   AView = Ember.View.extend({
12750     mouseEnter: function(event){
12751       // will never trigger.
12752     },
12753     eventManager: Ember.Object.create({
12754       mouseEnter: function(event, view){
12755         // takes presedence over AView#mouseEnter
12756       }
12757     })
12758   });
12759   ```
12760
12761   Similarly a view's event manager will take precedence for events of any views
12762   rendered as a descendent. A method name that matches an event name will not be called
12763   if the view instance was rendered inside the HTML representation of a view that has 
12764   an `eventManager` property defined that handles events of the name.  Events not handled
12765   by the event manager will still trigger method calls on the descendent.
12766
12767   ``` javascript
12768   OuterView = Ember.View.extend({
12769     template: Ember.Handlebars.compile("outer {{#view InnerView}}inner{{/view}} outer"),
12770     eventManager: Ember.Object.create({
12771       mouseEnter: function(event, view){
12772         // view might be instance of either
12773         // OutsideView or InnerView depending on
12774         // where on the page the user interaction occured
12775       }
12776     })
12777   });
12778
12779   InnerView = Ember.View.extend({
12780     click: function(event){
12781       // will be called if rendered inside
12782       // an OuterView because OuterView's
12783       // eventManager doesn't handle click events
12784     },
12785     mouseEnter: function(event){
12786       // will never be called if rendered inside 
12787       // an OuterView.
12788     }
12789   });
12790   ```
12791
12792   ### Handlebars `{{action}}` Helper
12793
12794   See `Handlebars.helpers.action`.
12795
12796   ### Event Names
12797
12798   Possible events names for any of the responding approaches described above are:
12799
12800   Touch events: 'touchStart', 'touchMove', 'touchEnd', 'touchCancel'
12801
12802   Keyboard events: 'keyDown', 'keyUp', 'keyPress'
12803
12804   Mouse events: 'mouseDown', 'mouseUp', 'contextMenu', 'click', 'doubleClick', 'mouseMove',
12805   'focusIn', 'focusOut', 'mouseEnter', 'mouseLeave'
12806
12807   Form events: 'submit', 'change', 'focusIn', 'focusOut', 'input'
12808
12809   HTML5 drag and drop events: 'dragStart', 'drag', 'dragEnter', 'dragLeave', 'drop', 'dragEnd'
12810   
12811   ## Handlebars `{{view}}` Helper
12812   
12813   Other `Ember.View` instances can be included as part of a view's template by using the `{{view}}`
12814   Handlebars helper. See `Handlebars.helpers.view` for additional information.
12815
12816   @class View
12817   @namespace Ember
12818   @extends Ember.Object
12819   @uses Ember.Evented
12820 */
12821 Ember.View = Ember.Object.extend(Ember.Evented,
12822 /** @scope Ember.View.prototype */ {
12823
12824   concatenatedProperties: ['classNames', 'classNameBindings', 'attributeBindings'],
12825
12826   /**
12827     @property isView
12828     @type Boolean
12829     @default true
12830     @final
12831   */
12832   isView: true,
12833
12834   // ..........................................................
12835   // TEMPLATE SUPPORT
12836   //
12837
12838   /**
12839     The name of the template to lookup if no template is provided.
12840
12841     Ember.View will look for a template with this name in this view's
12842     `templates` object. By default, this will be a global object
12843     shared in `Ember.TEMPLATES`.
12844
12845     @property templateName
12846     @type String
12847     @default null
12848   */
12849   templateName: null,
12850
12851   /**
12852     The name of the layout to lookup if no layout is provided.
12853
12854     Ember.View will look for a template with this name in this view's
12855     `templates` object. By default, this will be a global object
12856     shared in `Ember.TEMPLATES`.
12857
12858     @property layoutName
12859     @type String
12860     @default null
12861   */
12862   layoutName: null,
12863
12864   /**
12865     The hash in which to look for `templateName`.
12866
12867     @property templates
12868     @type Ember.Object
12869     @default Ember.TEMPLATES
12870   */
12871   templates: Ember.TEMPLATES,
12872
12873   /**
12874     The template used to render the view. This should be a function that
12875     accepts an optional context parameter and returns a string of HTML that
12876     will be inserted into the DOM relative to its parent view.
12877
12878     In general, you should set the `templateName` property instead of setting
12879     the template yourself.
12880
12881     @property template
12882     @type Function
12883   */
12884   template: Ember.computed(function(key, value) {
12885     if (value !== undefined) { return value; }
12886
12887     var templateName = get(this, 'templateName'),
12888         template = this.templateForName(templateName, 'template');
12889
12890     return template || get(this, 'defaultTemplate');
12891   }).property('templateName').cacheable(),
12892
12893   /**
12894     The controller managing this view. If this property is set, it will be
12895     made available for use by the template.
12896
12897     @property controller
12898     @type Object
12899   */
12900   controller: Ember.computed(function(key, value) {
12901     var parentView;
12902
12903     if (arguments.length === 2) {
12904       return value;
12905     } else {
12906       parentView = get(this, 'parentView');
12907       return parentView ? get(parentView, 'controller') : null;
12908     }
12909   }).property().cacheable(),
12910
12911   /**
12912     A view may contain a layout. A layout is a regular template but
12913     supersedes the `template` property during rendering. It is the
12914     responsibility of the layout template to retrieve the `template`
12915     property from the view (or alternatively, call `Handlebars.helpers.yield`,
12916     `{{yield}}`) to render it in the correct location.
12917
12918     This is useful for a view that has a shared wrapper, but which delegates
12919     the rendering of the contents of the wrapper to the `template` property
12920     on a subclass.
12921
12922     @property layout
12923     @type Function
12924   */
12925   layout: Ember.computed(function(key, value) {
12926     if (arguments.length === 2) { return value; }
12927
12928     var layoutName = get(this, 'layoutName'),
12929         layout = this.templateForName(layoutName, 'layout');
12930
12931     return layout || get(this, 'defaultLayout');
12932   }).property('layoutName').cacheable(),
12933
12934   templateForName: function(name, type) {
12935     if (!name) { return; }
12936
12937     var templates = get(this, 'templates'),
12938         template = get(templates, name);
12939
12940     if (!template) {
12941      throw new Ember.Error(fmt('%@ - Unable to find %@ "%@".', [this, type, name]));
12942     }
12943
12944     return template;
12945   },
12946
12947   /**
12948     The object from which templates should access properties.
12949
12950     This object will be passed to the template function each time the render
12951     method is called, but it is up to the individual function to decide what
12952     to do with it.
12953
12954     By default, this will be the view itself.
12955
12956     @property context
12957     @type Object
12958   */
12959   context: Ember.computed(function(key, value) {
12960     if (arguments.length === 2) {
12961       set(this, '_context', value);
12962       return value;
12963     } else {
12964       return get(this, '_context');
12965     }
12966   }).volatile(),
12967
12968   /**
12969     @private
12970
12971     Private copy of the view's template context. This can be set directly
12972     by Handlebars without triggering the observer that causes the view
12973     to be re-rendered.
12974
12975     The context of a view is looked up as follows:
12976
12977     1. Supplied context (usually by Handlebars)
12978     2. Specified controller
12979     3. `parentView`'s context (for a child of a ContainerView)
12980
12981     The code in Handlebars that overrides the `_context` property first
12982     checks to see whether the view has a specified controller. This is
12983     something of a hack and should be revisited.
12984
12985     @property _context
12986   */
12987   _context: Ember.computed(function(key, value) {
12988     var parentView, controller;
12989
12990     if (arguments.length === 2) {
12991       return value;
12992     }
12993
12994     if (VIEW_PRESERVES_CONTEXT) {
12995       if (controller = get(this, 'controller')) {
12996         return controller;
12997       }
12998
12999       parentView = get(this, '_parentView');
13000       if (parentView) {
13001         return get(parentView, '_context');
13002       }
13003     }
13004
13005     return this;
13006   }).cacheable(),
13007
13008   /**
13009     @private
13010
13011     If a value that affects template rendering changes, the view should be
13012     re-rendered to reflect the new value.
13013
13014     @method _displayPropertyDidChange
13015   */
13016   _displayPropertyDidChange: Ember.observer(function() {
13017     this.rerender();
13018   }, 'context', 'controller'),
13019
13020   /**
13021     If the view is currently inserted into the DOM of a parent view, this
13022     property will point to the parent of the view.
13023
13024     @property parentView
13025     @type Ember.View
13026     @default null
13027   */
13028   parentView: Ember.computed(function() {
13029     var parent = get(this, '_parentView');
13030
13031     if (parent && parent.isVirtual) {
13032       return get(parent, 'parentView');
13033     } else {
13034       return parent;
13035     }
13036   }).property('_parentView').volatile(),
13037
13038   _parentView: null,
13039
13040   // return the current view, not including virtual views
13041   concreteView: Ember.computed(function() {
13042     if (!this.isVirtual) { return this; }
13043     else { return get(this, 'parentView'); }
13044   }).property('_parentView').volatile(),
13045
13046   /**
13047     If false, the view will appear hidden in DOM.
13048
13049     @property isVisible
13050     @type Boolean
13051     @default null
13052   */
13053   isVisible: true,
13054
13055   /**
13056     @private
13057
13058     Array of child views. You should never edit this array directly.
13059     Instead, use appendChild and removeFromParent.
13060
13061     @property childViews
13062     @type Array
13063     @default []
13064   */
13065   childViews: childViewsProperty,
13066
13067   _childViews: [],
13068
13069   // When it's a virtual view, we need to notify the parent that their
13070   // childViews will change.
13071   _childViewsWillChange: Ember.beforeObserver(function() {
13072     if (this.isVirtual) {
13073       var parentView = get(this, 'parentView');
13074       if (parentView) { Ember.propertyWillChange(parentView, 'childViews'); }
13075     }
13076   }, 'childViews'),
13077
13078   // When it's a virtual view, we need to notify the parent that their
13079   // childViews did change.
13080   _childViewsDidChange: Ember.observer(function() {
13081     if (this.isVirtual) {
13082       var parentView = get(this, 'parentView');
13083       if (parentView) { Ember.propertyDidChange(parentView, 'childViews'); }
13084     }
13085   }, 'childViews'),
13086
13087   /**
13088     Return the nearest ancestor that is an instance of the provided
13089     class.
13090
13091     @property nearestInstanceOf
13092     @param {Class} klass Subclass of Ember.View (or Ember.View itself)
13093     @return Ember.View
13094   */
13095   nearestInstanceOf: function(klass) {
13096     var view = get(this, 'parentView');
13097
13098     while (view) {
13099       if(view instanceof klass) { return view; }
13100       view = get(view, 'parentView');
13101     }
13102   },
13103
13104   /**
13105     Return the nearest ancestor that has a given property.
13106
13107     @property nearestWithProperty
13108     @param {String} property A property name
13109     @return Ember.View
13110   */
13111   nearestWithProperty: function(property) {
13112     var view = get(this, 'parentView');
13113
13114     while (view) {
13115       if (property in view) { return view; }
13116       view = get(view, 'parentView');
13117     }
13118   },
13119
13120   /**
13121     Return the nearest ancestor whose parent is an instance of
13122     `klass`.
13123
13124     @property nearestChildOf
13125     @param {Class} klass Subclass of Ember.View (or Ember.View itself)
13126     @return Ember.View
13127   */
13128   nearestChildOf: function(klass) {
13129     var view = get(this, 'parentView');
13130
13131     while (view) {
13132       if(get(view, 'parentView') instanceof klass) { return view; }
13133       view = get(view, 'parentView');
13134     }
13135   },
13136
13137   /**
13138     Return the nearest ancestor that is an Ember.CollectionView
13139
13140     @property collectionView
13141     @return Ember.CollectionView
13142   */
13143   collectionView: Ember.computed(function() {
13144     return this.nearestInstanceOf(Ember.CollectionView);
13145   }).cacheable(),
13146
13147   /**
13148     Return the nearest ancestor that is a direct child of
13149     an Ember.CollectionView
13150
13151     @property itemView
13152     @return Ember.View
13153   */
13154   itemView: Ember.computed(function() {
13155     return this.nearestChildOf(Ember.CollectionView);
13156   }).cacheable(),
13157
13158   /**
13159     Return the nearest ancestor that has the property
13160     `content`.
13161
13162     @property contentView
13163     @return Ember.View
13164   */
13165   contentView: Ember.computed(function() {
13166     return this.nearestWithProperty('content');
13167   }).cacheable(),
13168
13169   /**
13170     @private
13171
13172     When the parent view changes, recursively invalidate
13173     collectionView, itemView, and contentView
13174
13175     @method _parentViewDidChange
13176   */
13177   _parentViewDidChange: Ember.observer(function() {
13178     if (this.isDestroying) { return; }
13179
13180     this.invokeRecursively(function(view) {
13181       view.propertyDidChange('collectionView');
13182       view.propertyDidChange('itemView');
13183       view.propertyDidChange('contentView');
13184     });
13185
13186     if (get(this, 'parentView.controller') && !get(this, 'controller')) {
13187       this.notifyPropertyChange('controller');
13188     }
13189   }, '_parentView'),
13190
13191   _controllerDidChange: Ember.observer(function() {
13192     if (this.isDestroying) { return; }
13193
13194     this.forEachChildView(function(view) {
13195       view.propertyDidChange('controller');
13196     });
13197   }, 'controller'),
13198
13199   cloneKeywords: function() {
13200     var templateData = get(this, 'templateData');
13201
13202     var keywords = templateData ? Ember.copy(templateData.keywords) : {};
13203     set(keywords, 'view', get(this, 'concreteView'));
13204     set(keywords, 'controller', get(this, 'controller'));
13205
13206     return keywords;
13207   },
13208
13209   /**
13210     Called on your view when it should push strings of HTML into a
13211     Ember.RenderBuffer. Most users will want to override the `template`
13212     or `templateName` properties instead of this method.
13213
13214     By default, Ember.View will look for a function in the `template`
13215     property and invoke it with the value of `context`. The value of
13216     `context` will be the view's controller unless you override it.
13217
13218     @method render
13219     @param {Ember.RenderBuffer} buffer The render buffer
13220   */
13221   render: function(buffer) {
13222     // If this view has a layout, it is the responsibility of the
13223     // the layout to render the view's template. Otherwise, render the template
13224     // directly.
13225     var template = get(this, 'layout') || get(this, 'template');
13226
13227     if (template) {
13228       var context = get(this, 'context');
13229       var keywords = this.cloneKeywords();
13230
13231       var data = {
13232         view: this,
13233         buffer: buffer,
13234         isRenderData: true,
13235         keywords: keywords
13236       };
13237
13238       // Invoke the template with the provided template context, which
13239       // is the view by default. A hash of data is also passed that provides
13240       // the template with access to the view and render buffer.
13241
13242       Ember.assert('template must be a function. Did you mean to call Ember.Handlebars.compile("...") or specify templateName instead?', typeof template === 'function');
13243       // The template should write directly to the render buffer instead
13244       // of returning a string.
13245       var output = template(context, { data: data });
13246
13247       // If the template returned a string instead of writing to the buffer,
13248       // push the string onto the buffer.
13249       if (output !== undefined) { buffer.push(output); }
13250     }
13251   },
13252
13253   invokeForState: function(name) {
13254     var stateName = this.state, args, fn;
13255
13256     // try to find the function for the state in the cache
13257     if (fn = invokeForState[stateName][name]) {
13258       args = a_slice.call(arguments);
13259       args[0] = this;
13260
13261       return fn.apply(this, args);
13262     }
13263
13264     // otherwise, find and cache the function for this state
13265     var parent = this, states = parent.states, state;
13266
13267     while (states) {
13268       state = states[stateName];
13269
13270       while (state) {
13271         fn = state[name];
13272
13273         if (fn) {
13274           invokeForState[stateName][name] = fn;
13275
13276           args = a_slice.call(arguments, 1);
13277           args.unshift(this);
13278
13279           return fn.apply(this, args);
13280         }
13281
13282         state = state.parentState;
13283       }
13284
13285       states = states.parent;
13286     }
13287   },
13288
13289   /**
13290     Renders the view again. This will work regardless of whether the
13291     view is already in the DOM or not. If the view is in the DOM, the
13292     rendering process will be deferred to give bindings a chance
13293     to synchronize.
13294
13295     If children were added during the rendering process using `appendChild`,
13296     `rerender` will remove them, because they will be added again
13297     if needed by the next `render`.
13298
13299     In general, if the display of your view changes, you should modify
13300     the DOM element directly instead of manually calling `rerender`, which can
13301     be slow.
13302
13303     @method rerender
13304   */
13305   rerender: function() {
13306     return this.invokeForState('rerender');
13307   },
13308
13309   clearRenderedChildren: function() {
13310     var lengthBefore = this.lengthBeforeRender,
13311         lengthAfter  = this.lengthAfterRender;
13312
13313     // If there were child views created during the last call to render(),
13314     // remove them under the assumption that they will be re-created when
13315     // we re-render.
13316
13317     // VIEW-TODO: Unit test this path.
13318     var childViews = this._childViews;
13319     for (var i=lengthAfter-1; i>=lengthBefore; i--) {
13320       if (childViews[i]) { childViews[i].destroy(); }
13321     }
13322   },
13323
13324   /**
13325     @private
13326
13327     Iterates over the view's `classNameBindings` array, inserts the value
13328     of the specified property into the `classNames` array, then creates an
13329     observer to update the view's element if the bound property ever changes
13330     in the future.
13331
13332     @method _applyClassNameBindings
13333   */
13334   _applyClassNameBindings: function() {
13335     var classBindings = get(this, 'classNameBindings'),
13336         classNames = get(this, 'classNames'),
13337         elem, newClass, dasherizedClass;
13338
13339     if (!classBindings) { return; }
13340
13341     // Loop through all of the configured bindings. These will be either
13342     // property names ('isUrgent') or property paths relative to the view
13343     // ('content.isUrgent')
13344     a_forEach(classBindings, function(binding) {
13345
13346       // Variable in which the old class value is saved. The observer function
13347       // closes over this variable, so it knows which string to remove when
13348       // the property changes.
13349       var oldClass;
13350       // Extract just the property name from bindings like 'foo:bar'
13351       var parsedPath = Ember.View._parsePropertyPath(binding);
13352
13353       // Set up an observer on the context. If the property changes, toggle the
13354       // class name.
13355       var observer = function() {
13356         // Get the current value of the property
13357         newClass = this._classStringForProperty(binding);
13358         elem = this.$();
13359         if (!elem) {
13360           removeObserver(this, parsedPath.path, observer);
13361           return;
13362         }
13363
13364         // If we had previously added a class to the element, remove it.
13365         if (oldClass) {
13366           elem.removeClass(oldClass);
13367           // Also remove from classNames so that if the view gets rerendered,
13368           // the class doesn't get added back to the DOM.
13369           classNames.removeObject(oldClass);
13370         }
13371
13372         // If necessary, add a new class. Make sure we keep track of it so
13373         // it can be removed in the future.
13374         if (newClass) {
13375           elem.addClass(newClass);
13376           oldClass = newClass;
13377         } else {
13378           oldClass = null;
13379         }
13380       };
13381
13382       // Get the class name for the property at its current value
13383       dasherizedClass = this._classStringForProperty(binding);
13384
13385       if (dasherizedClass) {
13386         // Ensure that it gets into the classNames array
13387         // so it is displayed when we render.
13388         classNames.push(dasherizedClass);
13389
13390         // Save a reference to the class name so we can remove it
13391         // if the observer fires. Remember that this variable has
13392         // been closed over by the observer.
13393         oldClass = dasherizedClass;
13394       }
13395
13396       addObserver(this, parsedPath.path, observer);
13397     }, this);
13398   },
13399
13400   /**
13401     @private
13402
13403     Iterates through the view's attribute bindings, sets up observers for each,
13404     then applies the current value of the attributes to the passed render buffer.
13405
13406     @method _applyAttributeBindings
13407     @param {Ember.RenderBuffer} buffer
13408   */
13409   _applyAttributeBindings: function(buffer) {
13410     var attributeBindings = get(this, 'attributeBindings'),
13411         attributeValue, elem, type;
13412
13413     if (!attributeBindings) { return; }
13414
13415     a_forEach(attributeBindings, function(binding) {
13416       var split = binding.split(':'),
13417           property = split[0],
13418           attributeName = split[1] || property;
13419
13420       // Create an observer to add/remove/change the attribute if the
13421       // JavaScript property changes.
13422       var observer = function() {
13423         elem = this.$();
13424         if (!elem) { return; }
13425
13426         attributeValue = get(this, property);
13427
13428         Ember.View.applyAttributeBindings(elem, attributeName, attributeValue);
13429       };
13430
13431       addObserver(this, property, observer);
13432
13433       // Determine the current value and add it to the render buffer
13434       // if necessary.
13435       attributeValue = get(this, property);
13436       Ember.View.applyAttributeBindings(buffer, attributeName, attributeValue);
13437     }, this);
13438   },
13439
13440   /**
13441     @private
13442
13443     Given a property name, returns a dasherized version of that
13444     property name if the property evaluates to a non-falsy value.
13445
13446     For example, if the view has property `isUrgent` that evaluates to true,
13447     passing `isUrgent` to this method will return `"is-urgent"`.
13448
13449     @method _classStringForProperty
13450     @param property
13451   */
13452   _classStringForProperty: function(property) {
13453     var parsedPath = Ember.View._parsePropertyPath(property);
13454     var path = parsedPath.path;
13455
13456     var val = get(this, path);
13457     if (val === undefined && Ember.isGlobalPath(path)) {
13458       val = get(window, path);
13459     }
13460
13461     return Ember.View._classStringForValue(path, val, parsedPath.className, parsedPath.falsyClassName);
13462   },
13463
13464   // ..........................................................
13465   // ELEMENT SUPPORT
13466   //
13467
13468   /**
13469     Returns the current DOM element for the view.
13470
13471     @property element
13472     @type DOMElement
13473   */
13474   element: Ember.computed(function(key, value) {
13475     if (value !== undefined) {
13476       return this.invokeForState('setElement', value);
13477     } else {
13478       return this.invokeForState('getElement');
13479     }
13480   }).property('_parentView').cacheable(),
13481
13482   /**
13483     Returns a jQuery object for this view's element. If you pass in a selector
13484     string, this method will return a jQuery object, using the current element
13485     as its buffer.
13486
13487     For example, calling `view.$('li')` will return a jQuery object containing
13488     all of the `li` elements inside the DOM element of this view.
13489
13490     @property $
13491     @param {String} [selector] a jQuery-compatible selector string
13492     @return {jQuery} the CoreQuery object for the DOM node
13493   */
13494   $: function(sel) {
13495     return this.invokeForState('$', sel);
13496   },
13497
13498   mutateChildViews: function(callback) {
13499     var childViews = this._childViews,
13500         idx = childViews.length,
13501         view;
13502
13503     while(--idx >= 0) {
13504       view = childViews[idx];
13505       callback.call(this, view, idx);
13506     }
13507
13508     return this;
13509   },
13510
13511   forEachChildView: function(callback) {
13512     var childViews = this._childViews;
13513
13514     if (!childViews) { return this; }
13515
13516     var len = childViews.length,
13517         view, idx;
13518
13519     for(idx = 0; idx < len; idx++) {
13520       view = childViews[idx];
13521       callback.call(this, view);
13522     }
13523
13524     return this;
13525   },
13526
13527   /**
13528     Appends the view's element to the specified parent element.
13529
13530     If the view does not have an HTML representation yet, `createElement()`
13531     will be called automatically.
13532
13533     Note that this method just schedules the view to be appended; the DOM
13534     element will not be appended to the given element until all bindings have
13535     finished synchronizing.
13536
13537     This is not typically a function that you will need to call directly
13538     when building your application. You might consider using Ember.ContainerView
13539     instead. If you do need to use appendTo, be sure that the target element you
13540     are providing is associated with an Ember.Application and does not have an
13541     ancestor element that is associated with an Ember view.
13542
13543     @method appendTo
13544     @param {String|DOMElement|jQuery} A selector, element, HTML string, or jQuery object
13545     @return {Ember.View} receiver
13546   */
13547   appendTo: function(target) {
13548     // Schedule the DOM element to be created and appended to the given
13549     // element after bindings have synchronized.
13550     this._insertElementLater(function() {
13551       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'));
13552       this.$().appendTo(target);
13553     });
13554
13555     return this;
13556   },
13557
13558   /**
13559     Replaces the content of the specified parent element with this view's element.
13560     If the view does not have an HTML representation yet, `createElement()`
13561     will be called automatically.
13562
13563     Note that this method just schedules the view to be appended; the DOM
13564     element will not be appended to the given element until all bindings have
13565     finished synchronizing
13566
13567     @method replaceIn
13568     @param {String|DOMElement|jQuery} A selector, element, HTML string, or jQuery object
13569     @return {Ember.View} received
13570   */
13571   replaceIn: function(target) {
13572     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'));
13573
13574     this._insertElementLater(function() {
13575       Ember.$(target).empty();
13576       this.$().appendTo(target);
13577     });
13578
13579     return this;
13580   },
13581
13582   /**
13583     @private
13584
13585     Schedules a DOM operation to occur during the next render phase. This
13586     ensures that all bindings have finished synchronizing before the view is
13587     rendered.
13588
13589     To use, pass a function that performs a DOM operation..
13590
13591     Before your function is called, this view and all child views will receive
13592     the `willInsertElement` event. After your function is invoked, this view
13593     and all of its child views will receive the `didInsertElement` event.
13594
13595         view._insertElementLater(function() {
13596           this.createElement();
13597           this.$().appendTo('body');
13598         });
13599
13600     @method _insertElementLater
13601     @param {Function} fn the function that inserts the element into the DOM
13602   */
13603   _insertElementLater: function(fn) {
13604     this._scheduledInsert = Ember.run.scheduleOnce('render', this, '_insertElement', fn);
13605   },
13606
13607   /**
13608    @private
13609   */
13610   _insertElement: function (fn) {
13611     this._scheduledInsert = null;
13612     this.invokeForState('insertElement', fn);
13613   },
13614
13615   /**
13616     Appends the view's element to the document body. If the view does
13617     not have an HTML representation yet, `createElement()` will be called
13618     automatically.
13619
13620     Note that this method just schedules the view to be appended; the DOM
13621     element will not be appended to the document body until all bindings have
13622     finished synchronizing.
13623
13624     @method append
13625     @return {Ember.View} receiver
13626   */
13627   append: function() {
13628     return this.appendTo(document.body);
13629   },
13630
13631   /**
13632     Removes the view's element from the element to which it is attached.
13633
13634     @method remove
13635     @return {Ember.View} receiver
13636   */
13637   remove: function() {
13638     // What we should really do here is wait until the end of the run loop
13639     // to determine if the element has been re-appended to a different
13640     // element.
13641     // In the interim, we will just re-render if that happens. It is more
13642     // important than elements get garbage collected.
13643     this.destroyElement();
13644     this.invokeRecursively(function(view) {
13645       view.clearRenderedChildren();
13646     });
13647   },
13648
13649   /**
13650     The ID to use when trying to locate the element in the DOM. If you do not
13651     set the elementId explicitly, then the view's GUID will be used instead.
13652     This ID must be set at the time the view is created.
13653
13654     @property elementId
13655     @type String
13656   */
13657   elementId: Ember.computed(function(key, value) {
13658     return value !== undefined ? value : Ember.guidFor(this);
13659   }).cacheable(),
13660
13661   // TODO: Perhaps this should be removed from the production build somehow.
13662   _elementIdDidChange: Ember.beforeObserver(function() {
13663     throw "Changing a view's elementId after creation is not allowed.";
13664   }, 'elementId'),
13665
13666   /**
13667     Attempts to discover the element in the parent element. The default
13668     implementation looks for an element with an ID of elementId (or the view's
13669     guid if elementId is null). You can override this method to provide your
13670     own form of lookup. For example, if you want to discover your element
13671     using a CSS class name instead of an ID.
13672
13673     @method findElementInParentElement
13674     @param {DOMElement} parentElement The parent's DOM element
13675     @return {DOMElement} The discovered element
13676   */
13677   findElementInParentElement: function(parentElem) {
13678     var id = "#" + get(this, 'elementId');
13679     return Ember.$(id)[0] || Ember.$(id, parentElem)[0];
13680   },
13681
13682   /**
13683     Creates a new renderBuffer with the passed tagName. You can override this
13684     method to provide further customization to the buffer if needed. Normally
13685     you will not need to call or override this method.
13686
13687     @method renderBuffer
13688     @param [tagName] {String}
13689     @return {Ember.RenderBuffer}
13690   */
13691   renderBuffer: function(tagName) {
13692     tagName = tagName || get(this, 'tagName');
13693
13694     // Explicitly check for null or undefined, as tagName
13695     // may be an empty string, which would evaluate to false.
13696     if (tagName === null || tagName === undefined) {
13697       tagName = 'div';
13698     }
13699
13700     return Ember.RenderBuffer(tagName);
13701   },
13702
13703   /**
13704     Creates a DOM representation of the view and all of its
13705     child views by recursively calling the `render()` method.
13706
13707     After the element has been created, `didInsertElement` will
13708     be called on this view and all of its child views.
13709
13710     @method createElement
13711     @return {Ember.View} receiver
13712   */
13713   createElement: function() {
13714     if (get(this, 'element')) { return this; }
13715
13716     var buffer = this.renderToBuffer();
13717     set(this, 'element', buffer.element());
13718
13719     return this;
13720   },
13721
13722   /**
13723     Called when a view is going to insert an element into the DOM.
13724
13725     @event willInsertElement
13726   */
13727   willInsertElement: Ember.K,
13728
13729   /**
13730     Called when the element of the view has been inserted into the DOM.
13731     Override this function to do any set up that requires an element in the
13732     document body.
13733
13734     @event didInsertElement
13735   */
13736   didInsertElement: Ember.K,
13737
13738   /**
13739     Called when the view is about to rerender, but before anything has
13740     been torn down. This is a good opportunity to tear down any manual
13741     observers you have installed based on the DOM state
13742
13743     @event willRerender
13744   */
13745   willRerender: Ember.K,
13746
13747   /**
13748     @private
13749
13750     Run this callback on the current view and recursively on child views.
13751
13752     @method invokeRecursively
13753     @param fn {Function}
13754   */
13755   invokeRecursively: function(fn) {
13756     fn.call(this, this);
13757
13758     this.forEachChildView(function(view) {
13759       view.invokeRecursively(fn);
13760     });
13761   },
13762
13763   /**
13764     Invalidates the cache for a property on all child views.
13765
13766     @method invalidateRecursively
13767   */
13768   invalidateRecursively: function(key) {
13769     this.forEachChildView(function(view) {
13770       view.propertyDidChange(key);
13771     });
13772   },
13773
13774   /**
13775     @private
13776
13777     Invokes the receiver's willInsertElement() method if it exists and then
13778     invokes the same on all child views.
13779
13780     NOTE: In some cases this was called when the element existed. This no longer
13781     works so we let people know. We can remove this warning code later.
13782
13783     @method _notifyWillInsertElement
13784   */
13785   _notifyWillInsertElement: function() {
13786     this.invokeRecursively(function(view) {
13787       view.trigger('willInsertElement');
13788     });
13789   },
13790
13791   /**
13792     @private
13793
13794     Invokes the receiver's didInsertElement() method if it exists and then
13795     invokes the same on all child views.
13796
13797     @method _notifyDidInsertElement
13798   */
13799   _notifyDidInsertElement: function() {
13800     this.invokeRecursively(function(view) {
13801       view.trigger('didInsertElement');
13802     });
13803   },
13804
13805   /**
13806     @private
13807
13808     Invokes the receiver's willRerender() method if it exists and then
13809     invokes the same on all child views.
13810
13811     @method _notifyWillRerender
13812   */
13813   _notifyWillRerender: function() {
13814     this.invokeRecursively(function(view) {
13815       view.trigger('willRerender');
13816     });
13817   },
13818
13819   /**
13820     Destroys any existing element along with the element for any child views
13821     as well. If the view does not currently have a element, then this method
13822     will do nothing.
13823
13824     If you implement willDestroyElement() on your view, then this method will
13825     be invoked on your view before your element is destroyed to give you a
13826     chance to clean up any event handlers, etc.
13827
13828     If you write a willDestroyElement() handler, you can assume that your
13829     didInsertElement() handler was called earlier for the same element.
13830
13831     Normally you will not call or override this method yourself, but you may
13832     want to implement the above callbacks when it is run.
13833
13834     @method destroyElement
13835     @return {Ember.View} receiver
13836   */
13837   destroyElement: function() {
13838     return this.invokeForState('destroyElement');
13839   },
13840
13841   /**
13842     Called when the element of the view is going to be destroyed. Override
13843     this function to do any teardown that requires an element, like removing
13844     event listeners.
13845
13846     @event willDestroyElement
13847   */
13848   willDestroyElement: function() {},
13849
13850   /**
13851     @private
13852
13853     Invokes the `willDestroyElement` callback on the view and child views.
13854
13855     @method _notifyWillDestroyElement
13856   */
13857   _notifyWillDestroyElement: function() {
13858     this.invokeRecursively(function(view) {
13859       view.trigger('willDestroyElement');
13860     });
13861   },
13862
13863   _elementWillChange: Ember.beforeObserver(function() {
13864     this.forEachChildView(function(view) {
13865       Ember.propertyWillChange(view, 'element');
13866     });
13867   }, 'element'),
13868
13869   /**
13870     @private
13871
13872     If this view's element changes, we need to invalidate the caches of our
13873     child views so that we do not retain references to DOM elements that are
13874     no longer needed.
13875
13876     @method _elementDidChange
13877   */
13878   _elementDidChange: Ember.observer(function() {
13879     this.forEachChildView(function(view) {
13880       Ember.propertyDidChange(view, 'element');
13881     });
13882   }, 'element'),
13883
13884   /**
13885     Called when the parentView property has changed.
13886
13887     @event parentViewDidChange
13888   */
13889   parentViewDidChange: Ember.K,
13890
13891   /**
13892     @private
13893
13894     Invoked by the view system when this view needs to produce an HTML
13895     representation. This method will create a new render buffer, if needed,
13896     then apply any default attributes, such as class names and visibility.
13897     Finally, the `render()` method is invoked, which is responsible for
13898     doing the bulk of the rendering.
13899
13900     You should not need to override this method; instead, implement the
13901     `template` property, or if you need more control, override the `render`
13902     method.
13903
13904     @method renderToBuffer
13905     @param {Ember.RenderBuffer} buffer the render buffer. If no buffer is
13906       passed, a default buffer, using the current view's `tagName`, will
13907       be used.
13908   */
13909   renderToBuffer: function(parentBuffer, bufferOperation) {
13910     var buffer;
13911
13912     Ember.run.sync();
13913
13914     // Determine where in the parent buffer to start the new buffer.
13915     // By default, a new buffer will be appended to the parent buffer.
13916     // The buffer operation may be changed if the child views array is
13917     // mutated by Ember.ContainerView.
13918     bufferOperation = bufferOperation || 'begin';
13919
13920     // If this is the top-most view, start a new buffer. Otherwise,
13921     // create a new buffer relative to the original using the
13922     // provided buffer operation (for example, `insertAfter` will
13923     // insert a new buffer after the "parent buffer").
13924     if (parentBuffer) {
13925       var tagName = get(this, 'tagName');
13926       if (tagName === null || tagName === undefined) {
13927         tagName = 'div';
13928       }
13929
13930       buffer = parentBuffer[bufferOperation](tagName);
13931     } else {
13932       buffer = this.renderBuffer();
13933     }
13934
13935     this.buffer = buffer;
13936     this.transitionTo('inBuffer', false);
13937
13938     this.lengthBeforeRender = this._childViews.length;
13939
13940     this.beforeRender(buffer);
13941     this.render(buffer);
13942     this.afterRender(buffer);
13943
13944     this.lengthAfterRender = this._childViews.length;
13945
13946     return buffer;
13947   },
13948
13949   renderToBufferIfNeeded: function () {
13950     return this.invokeForState('renderToBufferIfNeeded', this);
13951   },
13952
13953   beforeRender: function(buffer) {
13954     this.applyAttributesToBuffer(buffer);
13955   },
13956
13957   afterRender: Ember.K,
13958
13959   applyAttributesToBuffer: function(buffer) {
13960     // Creates observers for all registered class name and attribute bindings,
13961     // then adds them to the element.
13962     this._applyClassNameBindings();
13963
13964     // Pass the render buffer so the method can apply attributes directly.
13965     // This isn't needed for class name bindings because they use the
13966     // existing classNames infrastructure.
13967     this._applyAttributeBindings(buffer);
13968
13969
13970     a_forEach(get(this, 'classNames'), function(name){ buffer.addClass(name); });
13971     buffer.id(get(this, 'elementId'));
13972
13973     var role = get(this, 'ariaRole');
13974     if (role) {
13975       buffer.attr('role', role);
13976     }
13977
13978     if (get(this, 'isVisible') === false) {
13979       buffer.style('display', 'none');
13980     }
13981   },
13982
13983   // ..........................................................
13984   // STANDARD RENDER PROPERTIES
13985   //
13986
13987   /**
13988     Tag name for the view's outer element. The tag name is only used when
13989     an element is first created. If you change the tagName for an element, you
13990     must destroy and recreate the view element.
13991
13992     By default, the render buffer will use a `<div>` tag for views.
13993
13994     @property tagName
13995     @type String
13996     @default null
13997   */
13998
13999   // We leave this null by default so we can tell the difference between
14000   // the default case and a user-specified tag.
14001   tagName: null,
14002
14003   /**
14004     The WAI-ARIA role of the control represented by this view. For example, a
14005     button may have a role of type 'button', or a pane may have a role of
14006     type 'alertdialog'. This property is used by assistive software to help
14007     visually challenged users navigate rich web applications.
14008
14009     The full list of valid WAI-ARIA roles is available at:
14010     http://www.w3.org/TR/wai-aria/roles#roles_categorization
14011
14012     @property ariaRole
14013     @type String
14014     @default null
14015   */
14016   ariaRole: null,
14017
14018   /**
14019     Standard CSS class names to apply to the view's outer element. This
14020     property automatically inherits any class names defined by the view's
14021     superclasses as well.
14022
14023     @property classNames
14024     @type Array
14025     @default ['ember-view']
14026   */
14027   classNames: ['ember-view'],
14028
14029   /**
14030     A list of properties of the view to apply as class names. If the property
14031     is a string value, the value of that string will be applied as a class
14032     name.
14033
14034         // Applies the 'high' class to the view element
14035         Ember.View.create({
14036           classNameBindings: ['priority']
14037           priority: 'high'
14038         });
14039
14040     If the value of the property is a Boolean, the name of that property is
14041     added as a dasherized class name.
14042
14043         // Applies the 'is-urgent' class to the view element
14044         Ember.View.create({
14045           classNameBindings: ['isUrgent']
14046           isUrgent: true
14047         });
14048
14049     If you would prefer to use a custom value instead of the dasherized
14050     property name, you can pass a binding like this:
14051
14052         // Applies the 'urgent' class to the view element
14053         Ember.View.create({
14054           classNameBindings: ['isUrgent:urgent']
14055           isUrgent: true
14056         });
14057
14058     This list of properties is inherited from the view's superclasses as well.
14059
14060     @property classNameBindings
14061     @type Array
14062     @default []
14063   */
14064   classNameBindings: [],
14065
14066   /**
14067     A list of properties of the view to apply as attributes. If the property is
14068     a string value, the value of that string will be applied as the attribute.
14069
14070         // Applies the type attribute to the element
14071         // with the value "button", like <div type="button">
14072         Ember.View.create({
14073           attributeBindings: ['type'],
14074           type: 'button'
14075         });
14076
14077     If the value of the property is a Boolean, the name of that property is
14078     added as an attribute.
14079
14080         // Renders something like <div enabled="enabled">
14081         Ember.View.create({
14082           attributeBindings: ['enabled'],
14083           enabled: true
14084         });
14085
14086     @property attributeBindings
14087   */
14088   attributeBindings: [],
14089
14090   state: 'preRender',
14091
14092   // .......................................................
14093   // CORE DISPLAY METHODS
14094   //
14095
14096   /**
14097     @private
14098
14099     Setup a view, but do not finish waking it up.
14100     - configure childViews
14101     - register the view with the global views hash, which is used for event
14102       dispatch
14103
14104     @method init
14105   */
14106   init: function() {
14107     this._super();
14108
14109     // Register the view for event handling. This hash is used by
14110     // Ember.EventDispatcher to dispatch incoming events.
14111     if (!this.isVirtual) Ember.View.views[get(this, 'elementId')] = this;
14112
14113     // setup child views. be sure to clone the child views array first
14114     this._childViews = this._childViews.slice();
14115
14116     Ember.assert("Only arrays are allowed for 'classNameBindings'", Ember.typeOf(this.classNameBindings) === 'array');
14117     this.classNameBindings = Ember.A(this.classNameBindings.slice());
14118
14119     Ember.assert("Only arrays are allowed for 'classNames'", Ember.typeOf(this.classNames) === 'array');
14120     this.classNames = Ember.A(this.classNames.slice());
14121
14122     var viewController = get(this, 'viewController');
14123     if (viewController) {
14124       viewController = get(viewController);
14125       if (viewController) {
14126         set(viewController, 'view', this);
14127       }
14128     }
14129   },
14130
14131   appendChild: function(view, options) {
14132     return this.invokeForState('appendChild', view, options);
14133   },
14134
14135   /**
14136     Removes the child view from the parent view.
14137
14138     @method removeChild
14139     @param {Ember.View} view
14140     @return {Ember.View} receiver
14141   */
14142   removeChild: function(view) {
14143     // If we're destroying, the entire subtree will be
14144     // freed, and the DOM will be handled separately,
14145     // so no need to mess with childViews.
14146     if (this.isDestroying) { return; }
14147
14148     // update parent node
14149     set(view, '_parentView', null);
14150
14151     // remove view from childViews array.
14152     var childViews = this._childViews;
14153
14154     Ember.EnumerableUtils.removeObject(childViews, view);
14155
14156     this.propertyDidChange('childViews'); // HUH?! what happened to will change?
14157
14158     return this;
14159   },
14160
14161   /**
14162     Removes all children from the parentView.
14163
14164     @method removeAllChildren
14165     @return {Ember.View} receiver
14166   */
14167   removeAllChildren: function() {
14168     return this.mutateChildViews(function(view) {
14169       this.removeChild(view);
14170     });
14171   },
14172
14173   destroyAllChildren: function() {
14174     return this.mutateChildViews(function(view) {
14175       view.destroy();
14176     });
14177   },
14178
14179   /**
14180     Removes the view from its parentView, if one is found. Otherwise
14181     does nothing.
14182
14183     @method removeFromParent
14184     @return {Ember.View} receiver
14185   */
14186   removeFromParent: function() {
14187     var parent = get(this, '_parentView');
14188
14189     // Remove DOM element from parent
14190     this.remove();
14191
14192     if (parent) { parent.removeChild(this); }
14193     return this;
14194   },
14195
14196   /**
14197     You must call `destroy` on a view to destroy the view (and all of its
14198     child views). This will remove the view from any parent node, then make
14199     sure that the DOM element managed by the view can be released by the
14200     memory manager.
14201
14202     @method willDestroy
14203   */
14204   willDestroy: function() {
14205     // calling this._super() will nuke computed properties and observers,
14206     // so collect any information we need before calling super.
14207     var childViews = this._childViews,
14208         parent     = get(this, '_parentView'),
14209         childLen;
14210
14211     // destroy the element -- this will avoid each child view destroying
14212     // the element over and over again...
14213     if (!this.removedFromDOM) { this.destroyElement(); }
14214
14215     // remove from non-virtual parent view if viewName was specified
14216     if (this.viewName) {
14217       var nonVirtualParentView = get(this, 'parentView');
14218       if (nonVirtualParentView) {
14219         set(nonVirtualParentView, this.viewName, null);
14220       }
14221     }
14222
14223     // remove from parent if found. Don't call removeFromParent,
14224     // as removeFromParent will try to remove the element from
14225     // the DOM again.
14226     if (parent) { parent.removeChild(this); }
14227
14228     this.state = 'destroyed';
14229
14230     childLen = childViews.length;
14231     for (var i=childLen-1; i>=0; i--) {
14232       childViews[i].removedFromDOM = true;
14233       childViews[i].destroy();
14234     }
14235
14236     // next remove view from global hash
14237     if (!this.isVirtual) delete Ember.View.views[get(this, 'elementId')];
14238   },
14239
14240   /**
14241     Instantiates a view to be added to the childViews array during view
14242     initialization. You generally will not call this method directly unless
14243     you are overriding createChildViews(). Note that this method will
14244     automatically configure the correct settings on the new view instance to
14245     act as a child of the parent.
14246
14247     @method createChildView
14248     @param {Class} viewClass
14249     @param {Hash} [attrs] Attributes to add
14250     @return {Ember.View} new instance
14251   */
14252   createChildView: function(view, attrs) {
14253     if (Ember.View.detect(view)) {
14254       attrs = attrs || {};
14255       attrs._parentView = this;
14256       attrs.templateData = attrs.templateData || get(this, 'templateData');
14257
14258       view = view.create(attrs);
14259
14260       // don't set the property on a virtual view, as they are invisible to
14261       // consumers of the view API
14262       if (view.viewName) { set(get(this, 'concreteView'), view.viewName, view); }
14263     } else {
14264       Ember.assert('You must pass instance or subclass of View', view instanceof Ember.View);
14265       Ember.assert("You can only pass attributes when a class is provided", !attrs);
14266
14267       if (!get(view, 'templateData')) {
14268         set(view, 'templateData', get(this, 'templateData'));
14269       }
14270
14271       set(view, '_parentView', this);
14272     }
14273
14274     return view;
14275   },
14276
14277   becameVisible: Ember.K,
14278   becameHidden: Ember.K,
14279
14280   /**
14281     @private
14282
14283     When the view's `isVisible` property changes, toggle the visibility
14284     element of the actual DOM element.
14285
14286     @method _isVisibleDidChange
14287   */
14288   _isVisibleDidChange: Ember.observer(function() {
14289     var $el = this.$();
14290     if (!$el) { return; }
14291
14292     var isVisible = get(this, 'isVisible');
14293
14294     $el.toggle(isVisible);
14295
14296     if (this._isAncestorHidden()) { return; }
14297
14298     if (isVisible) {
14299       this._notifyBecameVisible();
14300     } else {
14301       this._notifyBecameHidden();
14302     }
14303   }, 'isVisible'),
14304
14305   _notifyBecameVisible: function() {
14306     this.trigger('becameVisible');
14307
14308     this.forEachChildView(function(view) {
14309       var isVisible = get(view, 'isVisible');
14310
14311       if (isVisible || isVisible === null) {
14312         view._notifyBecameVisible();
14313       }
14314     });
14315   },
14316
14317   _notifyBecameHidden: function() {
14318     this.trigger('becameHidden');
14319     this.forEachChildView(function(view) {
14320       var isVisible = get(view, 'isVisible');
14321
14322       if (isVisible || isVisible === null) {
14323         view._notifyBecameHidden();
14324       }
14325     });
14326   },
14327
14328   _isAncestorHidden: function() {
14329     var parent = get(this, 'parentView');
14330
14331     while (parent) {
14332       if (get(parent, 'isVisible') === false) { return true; }
14333
14334       parent = get(parent, 'parentView');
14335     }
14336
14337     return false;
14338   },
14339
14340   clearBuffer: function() {
14341     this.invokeRecursively(function(view) {
14342       this.buffer = null;
14343     });
14344   },
14345
14346   transitionTo: function(state, children) {
14347     this.state = state;
14348
14349     if (children !== false) {
14350       this.forEachChildView(function(view) {
14351         view.transitionTo(state);
14352       });
14353     }
14354   },
14355
14356   /**
14357     @private
14358
14359     Override the default event firing from Ember.Evented to
14360     also call methods with the given name.
14361
14362     @method trigger
14363     @param name {String}
14364   */
14365   trigger: function(name) {
14366     this._super.apply(this, arguments);
14367     var method = this[name];
14368     if (method) {
14369       var args = [], i, l;
14370       for (i = 1, l = arguments.length; i < l; i++) {
14371         args.push(arguments[i]);
14372       }
14373       return method.apply(this, args);
14374     }
14375   },
14376
14377   has: function(name) {
14378     return Ember.typeOf(this[name]) === 'function' || this._super(name);
14379   },
14380
14381   // .......................................................
14382   // EVENT HANDLING
14383   //
14384
14385   /**
14386     @private
14387
14388     Handle events from `Ember.EventDispatcher`
14389
14390     @method handleEvent
14391     @param eventName {String}
14392     @param evt {Event}
14393   */
14394   handleEvent: function(eventName, evt) {
14395     return this.invokeForState('handleEvent', eventName, evt);
14396   }
14397
14398 });
14399
14400 /*
14401   Describe how the specified actions should behave in the various
14402   states that a view can exist in. Possible states:
14403
14404   * preRender: when a view is first instantiated, and after its
14405     element was destroyed, it is in the preRender state
14406   * inBuffer: once a view has been rendered, but before it has
14407     been inserted into the DOM, it is in the inBuffer state
14408   * inDOM: once a view has been inserted into the DOM it is in
14409     the inDOM state. A view spends the vast majority of its
14410     existence in this state.
14411   * destroyed: once a view has been destroyed (using the destroy
14412     method), it is in this state. No further actions can be invoked
14413     on a destroyed view.
14414 */
14415
14416   // in the destroyed state, everything is illegal
14417
14418   // before rendering has begun, all legal manipulations are noops.
14419
14420   // inside the buffer, legal manipulations are done on the buffer
14421
14422   // once the view has been inserted into the DOM, legal manipulations
14423   // are done on the DOM element.
14424
14425 var DOMManager = {
14426   prepend: function(view, html) {
14427     view.$().prepend(html);
14428   },
14429
14430   after: function(view, html) {
14431     view.$().after(html);
14432   },
14433
14434   html: function(view, html) {
14435     view.$().html(html);
14436   },
14437
14438   replace: function(view) {
14439     var element = get(view, 'element');
14440
14441     set(view, 'element', null);
14442
14443     view._insertElementLater(function() {
14444       Ember.$(element).replaceWith(get(view, 'element'));
14445     });
14446   },
14447
14448   remove: function(view) {
14449     view.$().remove();
14450   },
14451
14452   empty: function(view) {
14453     view.$().empty();
14454   }
14455 };
14456
14457 Ember.View.reopen({
14458   states: Ember.View.states,
14459   domManager: DOMManager
14460 });
14461
14462 Ember.View.reopenClass({
14463
14464   /**
14465     @private
14466
14467     Parse a path and return an object which holds the parsed properties.
14468
14469     For example a path like "content.isEnabled:enabled:disabled" wil return the
14470     following object:
14471
14472         {
14473           path: "content.isEnabled",
14474           className: "enabled",
14475           falsyClassName: "disabled",
14476           classNames: ":enabled:disabled"
14477         }
14478
14479     @method _parsePropertyPath
14480     @static
14481   */
14482   _parsePropertyPath: function(path) {
14483     var split = path.split(':'),
14484         propertyPath = split[0],
14485         classNames = "",
14486         className,
14487         falsyClassName;
14488
14489     // check if the property is defined as prop:class or prop:trueClass:falseClass
14490     if (split.length > 1) {
14491       className = split[1];
14492       if (split.length === 3) { falsyClassName = split[2]; }
14493
14494       classNames = ':' + className;
14495       if (falsyClassName) { classNames += ":" + falsyClassName; }
14496     }
14497
14498     return {
14499       path: propertyPath,
14500       classNames: classNames,
14501       className: (className === '') ? undefined : className,
14502       falsyClassName: falsyClassName
14503     };
14504   },
14505
14506   /**
14507     @private
14508
14509     Get the class name for a given value, based on the path, optional className
14510     and optional falsyClassName.
14511
14512     - if a className or falsyClassName has been specified:
14513       - if the value is truthy and className has been specified, className is returned
14514       - if the value is falsy and falsyClassName has been specified, falsyClassName is returned
14515       - otherwise null is returned
14516     - if the value is true, the dasherized last part of the supplied path is returned
14517     - if the value is not false, undefined or null, the value is returned
14518     - if none of the above rules apply, null is returned
14519
14520     @method _classStringForValue
14521     @param path
14522     @param val
14523     @param className
14524     @param falsyClassName
14525     @static
14526   */
14527   _classStringForValue: function(path, val, className, falsyClassName) {
14528     // When using the colon syntax, evaluate the truthiness or falsiness
14529     // of the value to determine which className to return
14530     if (className || falsyClassName) {
14531       if (className && !!val) {
14532         return className;
14533
14534       } else if (falsyClassName && !val) {
14535         return falsyClassName;
14536
14537       } else {
14538         return null;
14539       }
14540
14541     // If value is a Boolean and true, return the dasherized property
14542     // name.
14543     } else if (val === true) {
14544       // Normalize property path to be suitable for use
14545       // as a class name. For exaple, content.foo.barBaz
14546       // becomes bar-baz.
14547       var parts = path.split('.');
14548       return Ember.String.dasherize(parts[parts.length-1]);
14549
14550     // If the value is not false, undefined, or null, return the current
14551     // value of the property.
14552     } else if (val !== false && val !== undefined && val !== null) {
14553       return val;
14554
14555     // Nothing to display. Return null so that the old class is removed
14556     // but no new class is added.
14557     } else {
14558       return null;
14559     }
14560   }
14561 });
14562
14563 /**
14564   Global views hash
14565
14566   @property views
14567   @static
14568   @type Hash
14569 */
14570 Ember.View.views = {};
14571
14572 // If someone overrides the child views computed property when
14573 // defining their class, we want to be able to process the user's
14574 // supplied childViews and then restore the original computed property
14575 // at view initialization time. This happens in Ember.ContainerView's init
14576 // method.
14577 Ember.View.childViewsProperty = childViewsProperty;
14578
14579 Ember.View.applyAttributeBindings = function(elem, name, value) {
14580   var type = Ember.typeOf(value);
14581   var currentValue = elem.attr(name);
14582
14583   // if this changes, also change the logic in ember-handlebars/lib/helpers/binding.js
14584   if ((type === 'string' || (type === 'number' && !isNaN(value))) && value !== currentValue) {
14585     elem.attr(name, value);
14586   } else if (value && type === 'boolean') {
14587     elem.attr(name, name);
14588   } else if (!value) {
14589     elem.removeAttr(name);
14590   }
14591 };
14592
14593 })();
14594
14595
14596
14597 (function() {
14598 /**
14599 @module ember
14600 @submodule ember-views
14601 */
14602
14603 var get = Ember.get, set = Ember.set;
14604
14605 Ember.View.states = {
14606   _default: {
14607     // appendChild is only legal while rendering the buffer.
14608     appendChild: function() {
14609       throw "You can't use appendChild outside of the rendering process";
14610     },
14611
14612     $: function() {
14613       return undefined;
14614     },
14615
14616     getElement: function() {
14617       return null;
14618     },
14619
14620     // Handle events from `Ember.EventDispatcher`
14621     handleEvent: function() {
14622       return true; // continue event propagation
14623     },
14624
14625     destroyElement: function(view) {
14626       set(view, 'element', null);
14627       if (view._scheduledInsert) {
14628         Ember.run.cancel(view._scheduledInsert);
14629         view._scheduledInsert = null;
14630       }
14631       return view;
14632     },
14633
14634     renderToBufferIfNeeded: function () {
14635       return false;
14636     }
14637   }
14638 };
14639
14640 Ember.View.reopen({
14641   states: Ember.View.states
14642 });
14643
14644 })();
14645
14646
14647
14648 (function() {
14649 /**
14650 @module ember
14651 @submodule ember-views
14652 */
14653
14654 Ember.View.states.preRender = {
14655   parentState: Ember.View.states._default,
14656
14657   // a view leaves the preRender state once its element has been
14658   // created (createElement).
14659   insertElement: function(view, fn) {
14660     view.createElement();
14661     view._notifyWillInsertElement();
14662     // after createElement, the view will be in the hasElement state.
14663     fn.call(view);
14664     view.transitionTo('inDOM');
14665     view._notifyDidInsertElement();
14666   },
14667
14668   renderToBufferIfNeeded: function(view) {
14669     return view.renderToBuffer();
14670   },
14671
14672   empty: Ember.K,
14673
14674   setElement: function(view, value) {
14675     if (value !== null) {
14676       view.transitionTo('hasElement');
14677     }
14678     return value;
14679   }
14680 };
14681
14682 })();
14683
14684
14685
14686 (function() {
14687 /**
14688 @module ember
14689 @submodule ember-views
14690 */
14691
14692 var get = Ember.get, set = Ember.set, meta = Ember.meta;
14693
14694 Ember.View.states.inBuffer = {
14695   parentState: Ember.View.states._default,
14696
14697   $: function(view, sel) {
14698     // if we don't have an element yet, someone calling this.$() is
14699     // trying to update an element that isn't in the DOM. Instead,
14700     // rerender the view to allow the render method to reflect the
14701     // changes.
14702     view.rerender();
14703     return Ember.$();
14704   },
14705
14706   // when a view is rendered in a buffer, rerendering it simply
14707   // replaces the existing buffer with a new one
14708   rerender: function(view) {
14709     Ember.deprecate("Something you did caused a view to re-render after it rendered but before it was inserted into the DOM. Because this is avoidable and the cause of significant performance issues in applications, this behavior is deprecated. If you want to use the debugger to find out what caused this, you can set ENV.RAISE_ON_DEPRECATION to true.");
14710
14711     view._notifyWillRerender();
14712
14713     view.clearRenderedChildren();
14714     view.renderToBuffer(view.buffer, 'replaceWith');
14715   },
14716
14717   // when a view is rendered in a buffer, appending a child
14718   // view will render that view and append the resulting
14719   // buffer into its buffer.
14720   appendChild: function(view, childView, options) {
14721     var buffer = view.buffer;
14722
14723     childView = this.createChildView(childView, options);
14724     view._childViews.push(childView);
14725
14726     childView.renderToBuffer(buffer);
14727
14728     view.propertyDidChange('childViews');
14729
14730     return childView;
14731   },
14732
14733   // when a view is rendered in a buffer, destroying the
14734   // element will simply destroy the buffer and put the
14735   // state back into the preRender state.
14736   destroyElement: function(view) {
14737     view.clearBuffer();
14738     view._notifyWillDestroyElement();
14739     view.transitionTo('preRender');
14740
14741     return view;
14742   },
14743
14744   empty: function() {
14745     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.");
14746   },
14747
14748   renderToBufferIfNeeded: function (view) {
14749     return view.buffer;
14750   },
14751
14752   // It should be impossible for a rendered view to be scheduled for
14753   // insertion.
14754   insertElement: function() {
14755     throw "You can't insert an element that has already been rendered";
14756   },
14757
14758   setElement: function(view, value) {
14759     if (value === null) {
14760       view.transitionTo('preRender');
14761     } else {
14762       view.clearBuffer();
14763       view.transitionTo('hasElement');
14764     }
14765
14766     return value;
14767   }
14768 };
14769
14770
14771 })();
14772
14773
14774
14775 (function() {
14776 /**
14777 @module ember
14778 @submodule ember-views
14779 */
14780
14781 var get = Ember.get, set = Ember.set, meta = Ember.meta;
14782
14783 Ember.View.states.hasElement = {
14784   parentState: Ember.View.states._default,
14785
14786   $: function(view, sel) {
14787     var elem = get(view, 'element');
14788     return sel ? Ember.$(sel, elem) : Ember.$(elem);
14789   },
14790
14791   getElement: function(view) {
14792     var parent = get(view, 'parentView');
14793     if (parent) { parent = get(parent, 'element'); }
14794     if (parent) { return view.findElementInParentElement(parent); }
14795     return Ember.$("#" + get(view, 'elementId'))[0];
14796   },
14797
14798   setElement: function(view, value) {
14799     if (value === null) {
14800       view.transitionTo('preRender');
14801     } else {
14802       throw "You cannot set an element to a non-null value when the element is already in the DOM.";
14803     }
14804
14805     return value;
14806   },
14807
14808   // once the view has been inserted into the DOM, rerendering is
14809   // deferred to allow bindings to synchronize.
14810   rerender: function(view) {
14811     view._notifyWillRerender();
14812
14813     view.clearRenderedChildren();
14814
14815     view.domManager.replace(view);
14816     return view;
14817   },
14818
14819   // once the view is already in the DOM, destroying it removes it
14820   // from the DOM, nukes its element, and puts it back into the
14821   // preRender state if inDOM.
14822
14823   destroyElement: function(view) {
14824     view._notifyWillDestroyElement();
14825     view.domManager.remove(view);
14826     set(view, 'element', null);
14827     if (view._scheduledInsert) {
14828       Ember.run.cancel(view._scheduledInsert);
14829       view._scheduledInsert = null;
14830     }
14831     return view;
14832   },
14833
14834   empty: function(view) {
14835     var _childViews = view._childViews, len, idx;
14836     if (_childViews) {
14837       len = _childViews.length;
14838       for (idx = 0; idx < len; idx++) {
14839         _childViews[idx]._notifyWillDestroyElement();
14840       }
14841     }
14842     view.domManager.empty(view);
14843   },
14844
14845   // Handle events from `Ember.EventDispatcher`
14846   handleEvent: function(view, eventName, evt) {
14847     if (view.has(eventName)) {
14848       // Handler should be able to re-dispatch events, so we don't
14849       // preventDefault or stopPropagation.
14850       return view.trigger(eventName, evt);
14851     } else {
14852       return true; // continue event propagation
14853     }
14854   }
14855 };
14856
14857 Ember.View.states.inDOM = {
14858   parentState: Ember.View.states.hasElement,
14859
14860   insertElement: function(view, fn) {
14861     throw "You can't insert an element into the DOM that has already been inserted";
14862   }
14863 };
14864
14865 })();
14866
14867
14868
14869 (function() {
14870 /**
14871 @module ember
14872 @submodule ember-views
14873 */
14874
14875 var destroyedError = "You can't call %@ on a destroyed view", fmt = Ember.String.fmt;
14876
14877 Ember.View.states.destroyed = {
14878   parentState: Ember.View.states._default,
14879
14880   appendChild: function() {
14881     throw fmt(destroyedError, ['appendChild']);
14882   },
14883   rerender: function() {
14884     throw fmt(destroyedError, ['rerender']);
14885   },
14886   destroyElement: function() {
14887     throw fmt(destroyedError, ['destroyElement']);
14888   },
14889   empty: function() {
14890     throw fmt(destroyedError, ['empty']);
14891   },
14892
14893   setElement: function() {
14894     throw fmt(destroyedError, ["set('element', ...)"]);
14895   },
14896
14897   renderToBufferIfNeeded: function() {
14898     throw fmt(destroyedError, ["renderToBufferIfNeeded"]);
14899   },
14900
14901   // Since element insertion is scheduled, don't do anything if
14902   // the view has been destroyed between scheduling and execution
14903   insertElement: Ember.K
14904 };
14905
14906
14907 })();
14908
14909
14910
14911 (function() {
14912
14913 })();
14914
14915
14916
14917 (function() {
14918 /**
14919 @module ember
14920 @submodule ember-views
14921 */
14922
14923 var get = Ember.get, set = Ember.set, meta = Ember.meta;
14924 var forEach = Ember.EnumerableUtils.forEach;
14925
14926 var childViewsProperty = Ember.computed(function() {
14927   return get(this, '_childViews');
14928 }).property('_childViews').cacheable();
14929
14930 /**
14931   A `ContainerView` is an `Ember.View` subclass that allows for manual or programatic
14932   management of a view's `childViews` array that will correctly update the `ContainerView`
14933   instance's rendered DOM representation.
14934
14935   ## Setting Initial Child Views
14936   The initial array of child views can be set in one of two ways. You can provide
14937   a `childViews` property at creation time that contains instance of `Ember.View`:
14938
14939   ``` javascript
14940   aContainer = Ember.ContainerView.create({
14941     childViews: [Ember.View.create(), Ember.View.create()]
14942   });
14943   ```
14944
14945   You can also provide a list of property names whose values are instances of `Ember.View`:
14946
14947   ``` javascript
14948   aContainer = Ember.ContainerView.create({
14949     childViews: ['aView', 'bView', 'cView'],
14950     aView: Ember.View.create(),
14951     bView: Ember.View.create()
14952     cView: Ember.View.create()
14953   });
14954   ```
14955
14956   The two strategies can be combined:
14957
14958   ``` javascript
14959   aContainer = Ember.ContainerView.create({
14960     childViews: ['aView', Ember.View.create()],
14961     aView: Ember.View.create()
14962   });
14963   ```
14964
14965   Each child view's rendering will be inserted into the container's rendered HTML in the same
14966   order as its position in the `childViews` property.
14967
14968   ## Adding and Removing Child Views
14969   The views in a container's `childViews` array should be added and removed by manipulating
14970   the `childViews` property directly.
14971
14972   To remove a view pass that view into a `removeObject` call on the container's `childViews` property.
14973
14974   Given an empty `<body>` the following code
14975
14976   ``` javascript
14977   aContainer = Ember.ContainerView.create({
14978     classNames: ['the-container'],
14979     childViews: ['aView', 'bView'],
14980     aView: Ember.View.create({
14981       template: Ember.Handlebars.compile("A")
14982     }),
14983     bView: Ember.View.create({
14984       template: Ember.Handlebars.compile("B")
14985     })
14986   });
14987
14988   aContainer.appendTo('body');
14989   ``` 
14990
14991   Results in the HTML
14992
14993   ``` html
14994   <div class="ember-view the-container">
14995     <div class="ember-view">A</div>
14996     <div class="ember-view">B</div>
14997   </div>
14998   ```
14999
15000   Removing a view
15001
15002   ``` javascript
15003   aContainer.get('childViews'); // [aContainer.aView, aContainer.bView]
15004   aContainer.get('childViews').removeObject(aContainer.get('bView'));
15005   aContainer.get('childViews'); // [aContainer.aView]
15006   ```
15007
15008   Will result in the following HTML
15009
15010   ``` html
15011   <div class="ember-view the-container">
15012     <div class="ember-view">A</div>
15013   </div>
15014   ```
15015
15016
15017   Similarly, adding a child view is accomplished by adding `Ember.View` instances to the
15018   container's `childViews` property.
15019
15020   Given an empty `<body>` the following code
15021
15022   ``` javascript
15023   aContainer = Ember.ContainerView.create({
15024     classNames: ['the-container'],
15025     childViews: ['aView', 'bView'],
15026     aView: Ember.View.create({
15027       template: Ember.Handlebars.compile("A")
15028     }),
15029     bView: Ember.View.create({
15030       template: Ember.Handlebars.compile("B")
15031     })
15032   });
15033
15034   aContainer.appendTo('body');
15035   ```
15036
15037   Results in the HTML
15038
15039   ``` html
15040   <div class="ember-view the-container">
15041     <div class="ember-view">A</div>
15042     <div class="ember-view">B</div>
15043   </div>
15044   ```
15045
15046   Adding a view
15047
15048   ``` javascript
15049   AnotherViewClass = Ember.View.extend({
15050     template: Ember.Handlebars.compile("Another view")
15051   });
15052
15053   aContainer.get('childViews'); // [aContainer.aView, aContainer.bView]
15054   aContainer.get('childViews').pushObject(AnotherViewClass.create());
15055   aContainer.get('childViews'); // [aContainer.aView, aContainer.bView, <AnotherViewClass instance>]
15056   ```
15057
15058   Will result in the following HTML
15059
15060   ``` html
15061   <div class="ember-view the-container">
15062     <div class="ember-view">A</div>
15063     <div class="ember-view">B</div>
15064     <div class="ember-view">Another view</div>
15065   </div>
15066   ```
15067
15068
15069   Direct manipulation of childViews presence or absence in the DOM via calls to
15070   `remove` or `removeFromParent` or calls to a container's `removeChild` may not behave
15071   correctly.
15072
15073   Calling `remove()` on a child view will remove the view's HTML, but it will remain as part of its
15074   container's `childView`s property.
15075
15076   Calling `removeChild()` on the container will remove the passed view instance from the container's
15077   `childView`s but keep its HTML within the container's rendered view.
15078
15079   Calling `removeFromParent()` behaves as expected but should be avoided in favor of direct
15080   manipulation of a container's `childViews` property.
15081
15082   ``` javascript
15083   aContainer = Ember.ContainerView.create({
15084     classNames: ['the-container'],
15085     childViews: ['aView', 'bView'],
15086     aView: Ember.View.create({
15087       template: Ember.Handlebars.compile("A")
15088     }),
15089     bView: Ember.View.create({
15090       template: Ember.Handlebars.compile("B")
15091     })
15092   });
15093
15094   aContainer.appendTo('body');
15095   ```
15096
15097   Results in the HTML
15098
15099   ``` html
15100   <div class="ember-view the-container">
15101     <div class="ember-view">A</div>
15102     <div class="ember-view">B</div>
15103   </div>
15104   ```
15105
15106   Calling `aContainer.get('aView').removeFromParent()` will result in the following HTML
15107
15108   ``` html
15109   <div class="ember-view the-container">
15110     <div class="ember-view">B</div>
15111   </div>
15112   ```
15113
15114   And the `Ember.View` instance stored in `aContainer.aView` will be removed from `aContainer`'s
15115   `childViews` array.
15116
15117   ## Templates and Layout
15118
15119   A `template`, `templateName`, `defaultTemplate`, `layout`, `layoutName` or `defaultLayout`
15120   property on a container view will not result in the template or layout being rendered.
15121   The HTML contents of a `Ember.ContainerView`'s DOM representation will only be the rendered HTML
15122   of its child views.
15123
15124   ## Binding a View to Display
15125
15126   If you would like to display a single view in your ContainerView, you can set its `currentView`
15127   property. When the `currentView` property is set to a view instance, it will be added to the
15128   ContainerView's `childViews` array. If the `currentView` property is later changed to a
15129   different view, the new view will replace the old view. If `currentView` is set to `null`, the
15130   last `currentView` will be removed.
15131
15132   This functionality is useful for cases where you want to bind the display of a ContainerView to
15133   a controller or state manager. For example, you can bind the `currentView` of a container to
15134   a controller like this:
15135
15136   ``` javascript
15137   App.appController = Ember.Object.create({
15138     view: Ember.View.create({
15139       templateName: 'person_template'
15140     })
15141   });
15142   ```
15143
15144   ``` handlebars
15145   {{view Ember.ContainerView currentViewBinding="App.appController.view"}}
15146   ```
15147
15148   @class ContainerView
15149   @namespace Ember
15150   @extends Ember.View
15151 */
15152
15153 Ember.ContainerView = Ember.View.extend({
15154
15155   init: function() {
15156     this._super();
15157
15158     var childViews = get(this, 'childViews');
15159     Ember.defineProperty(this, 'childViews', childViewsProperty);
15160
15161     var _childViews = this._childViews;
15162
15163     forEach(childViews, function(viewName, idx) {
15164       var view;
15165
15166       if ('string' === typeof viewName) {
15167         view = get(this, viewName);
15168         view = this.createChildView(view);
15169         set(this, viewName, view);
15170       } else {
15171         view = this.createChildView(viewName);
15172       }
15173
15174       _childViews[idx] = view;
15175     }, this);
15176
15177     var currentView = get(this, 'currentView');
15178     if (currentView) _childViews.push(this.createChildView(currentView));
15179
15180     // Make the _childViews array observable
15181     Ember.A(_childViews);
15182
15183     // Sets up an array observer on the child views array. This
15184     // observer will detect when child views are added or removed
15185     // and update the DOM to reflect the mutation.
15186     get(this, 'childViews').addArrayObserver(this, {
15187       willChange: 'childViewsWillChange',
15188       didChange: 'childViewsDidChange'
15189     });
15190   },
15191
15192   /**
15193     @private
15194
15195     Instructs each child view to render to the passed render buffer.
15196
15197     @method render
15198     @param {Ember.RenderBuffer} buffer the buffer to render to
15199   */
15200   render: function(buffer) {
15201     this.forEachChildView(function(view) {
15202       view.renderToBuffer(buffer);
15203     });
15204   },
15205
15206   /**
15207     @private
15208
15209     When the container view is destroyed, tear down the child views
15210     array observer.
15211
15212     @method willDestroy
15213   */
15214   willDestroy: function() {
15215     get(this, 'childViews').removeArrayObserver(this, {
15216       willChange: 'childViewsWillChange',
15217       didChange: 'childViewsDidChange'
15218     });
15219
15220     this._super();
15221   },
15222
15223   /**
15224     @private
15225
15226     When a child view is removed, destroy its element so that
15227     it is removed from the DOM.
15228
15229     The array observer that triggers this action is set up in the
15230     `renderToBuffer` method.
15231
15232     @method childViewsWillChange
15233     @param {Ember.Array} views the child views array before mutation
15234     @param {Number} start the start position of the mutation
15235     @param {Number} removed the number of child views removed
15236   **/
15237   childViewsWillChange: function(views, start, removed) {
15238     if (removed === 0) { return; }
15239
15240     var changedViews = views.slice(start, start+removed);
15241     this.initializeViews(changedViews, null, null);
15242
15243     this.invokeForState('childViewsWillChange', views, start, removed);
15244   },
15245
15246   /**
15247     @private
15248
15249     When a child view is added, make sure the DOM gets updated appropriately.
15250
15251     If the view has already rendered an element, we tell the child view to
15252     create an element and insert it into the DOM. If the enclosing container view
15253     has already written to a buffer, but not yet converted that buffer into an
15254     element, we insert the string representation of the child into the appropriate
15255     place in the buffer.
15256
15257     @method childViewsDidChange
15258     @param {Ember.Array} views the array of child views afte the mutation has occurred
15259     @param {Number} start the start position of the mutation
15260     @param {Number} removed the number of child views removed
15261     @param {Number} the number of child views added
15262   */
15263   childViewsDidChange: function(views, start, removed, added) {
15264     var len = get(views, 'length');
15265
15266     // No new child views were added; bail out.
15267     if (added === 0) return;
15268
15269     var changedViews = views.slice(start, start+added);
15270     this.initializeViews(changedViews, this, get(this, 'templateData'));
15271
15272     // Let the current state handle the changes
15273     this.invokeForState('childViewsDidChange', views, start, added);
15274   },
15275
15276   initializeViews: function(views, parentView, templateData) {
15277     forEach(views, function(view) {
15278       set(view, '_parentView', parentView);
15279
15280       if (!get(view, 'templateData')) {
15281         set(view, 'templateData', templateData);
15282       }
15283     });
15284   },
15285
15286   currentView: null,
15287
15288   _currentViewWillChange: Ember.beforeObserver(function() {
15289     var childViews = get(this, 'childViews'),
15290         currentView = get(this, 'currentView');
15291
15292     if (currentView) {
15293       childViews.removeObject(currentView);
15294       currentView.destroy();
15295     }
15296   }, 'currentView'),
15297
15298   _currentViewDidChange: Ember.observer(function() {
15299     var childViews = get(this, 'childViews'),
15300         currentView = get(this, 'currentView');
15301
15302     if (currentView) {
15303       childViews.pushObject(currentView);
15304     }
15305   }, 'currentView'),
15306
15307   _ensureChildrenAreInDOM: function () {
15308     this.invokeForState('ensureChildrenAreInDOM', this);
15309   }
15310 });
15311
15312 // Ember.ContainerView extends the default view states to provide different
15313 // behavior for childViewsWillChange and childViewsDidChange.
15314 Ember.ContainerView.states = {
15315   parent: Ember.View.states,
15316
15317   inBuffer: {
15318     childViewsDidChange: function(parentView, views, start, added) {
15319       var buffer = parentView.buffer,
15320           startWith, prev, prevBuffer, view;
15321
15322       // Determine where to begin inserting the child view(s) in the
15323       // render buffer.
15324       if (start === 0) {
15325         // If views were inserted at the beginning, prepend the first
15326         // view to the render buffer, then begin inserting any
15327         // additional views at the beginning.
15328         view = views[start];
15329         startWith = start + 1;
15330         view.renderToBuffer(buffer, 'prepend');
15331       } else {
15332         // Otherwise, just insert them at the same place as the child
15333         // views mutation.
15334         view = views[start - 1];
15335         startWith = start;
15336       }
15337
15338       for (var i=startWith; i<start+added; i++) {
15339         prev = view;
15340         view = views[i];
15341         prevBuffer = prev.buffer;
15342         view.renderToBuffer(prevBuffer, 'insertAfter');
15343       }
15344     }
15345   },
15346
15347   hasElement: {
15348     childViewsWillChange: function(view, views, start, removed) {
15349       for (var i=start; i<start+removed; i++) {
15350         views[i].remove();
15351       }
15352     },
15353
15354     childViewsDidChange: function(view, views, start, added) {
15355       Ember.run.scheduleOnce('render', this, '_ensureChildrenAreInDOM');
15356     },
15357
15358     ensureChildrenAreInDOM: function(view) {
15359       var childViews = view.get('childViews'), i, len, childView, previous, buffer;
15360       for (i = 0, len = childViews.length; i < len; i++) {
15361         childView = childViews[i];
15362         buffer = childView.renderToBufferIfNeeded();
15363         if (buffer) {
15364           childView._notifyWillInsertElement();
15365           if (previous) {
15366             previous.domManager.after(previous, buffer.string());
15367           } else {
15368             view.domManager.prepend(view, buffer.string());
15369           }
15370           childView.transitionTo('inDOM');
15371           childView.propertyDidChange('element');
15372           childView._notifyDidInsertElement();
15373         }
15374         previous = childView;
15375       }
15376     }
15377   }
15378 };
15379
15380 Ember.ContainerView.states.inDOM = {
15381   parentState: Ember.ContainerView.states.hasElement
15382 };
15383
15384 Ember.ContainerView.reopen({
15385   states: Ember.ContainerView.states
15386 });
15387
15388 })();
15389
15390
15391
15392 (function() {
15393 /**
15394 @module ember
15395 @submodule ember-views
15396 */
15397
15398 var get = Ember.get, set = Ember.set, fmt = Ember.String.fmt;
15399
15400 /**
15401   `Ember.CollectionView` is an `Ember.View` descendent responsible for managing a
15402   collection (an array or array-like object) by maintaing a child view object and 
15403   associated DOM representation for each item in the array and ensuring that child
15404   views and their associated rendered HTML are updated when items in the array
15405   are added, removed, or replaced.
15406
15407   ## Setting content
15408   The managed collection of objects is referenced as the `Ember.CollectionView` instance's
15409   `content` property.
15410
15411   ``` javascript
15412   someItemsView = Ember.CollectionView.create({
15413     content: ['A', 'B','C']
15414   })
15415   ```
15416
15417   The view for each item in the collection will have its `content` property set
15418   to the item.
15419
15420   ## Specifying itemViewClass
15421   By default the view class for each item in the managed collection will be an instance
15422   of `Ember.View`. You can supply a different class by setting the `CollectionView`'s
15423   `itemViewClass` property.
15424
15425   Given an empty `<body>` and the following code:
15426
15427   ``` javascript 
15428   someItemsView = Ember.CollectionView.create({
15429     classNames: ['a-collection'],
15430     content: ['A','B','C'],
15431     itemViewClass: Ember.View.extend({
15432       template: Ember.Handlebars.compile("the letter: {{view.content}}")
15433     })
15434   });
15435
15436   someItemsView.appendTo('body');
15437   ```
15438
15439   Will result in the following HTML structure
15440
15441   ``` html
15442   <div class="ember-view a-collection">
15443     <div class="ember-view">the letter: A</div>
15444     <div class="ember-view">the letter: B</div>
15445     <div class="ember-view">the letter: C</div>
15446   </div>
15447   ```
15448
15449   ## Automatic matching of parent/child tagNames
15450
15451   Setting the `tagName` property of a `CollectionView` to any of 
15452   "ul", "ol", "table", "thead", "tbody", "tfoot", "tr", or "select" will result
15453   in the item views receiving an appropriately matched `tagName` property.
15454
15455
15456   Given an empty `<body>` and the following code:
15457
15458   ``` javascript
15459   anUndorderedListView = Ember.CollectionView.create({
15460     tagName: 'ul',
15461     content: ['A','B','C'],
15462     itemViewClass: Ember.View.extend({
15463       template: Ember.Handlebars.compile("the letter: {{view.content}}")
15464     })
15465   });
15466
15467   anUndorderedListView.appendTo('body');
15468   ```
15469
15470   Will result in the following HTML structure
15471
15472   ``` html
15473   <ul class="ember-view a-collection">
15474     <li class="ember-view">the letter: A</li>
15475     <li class="ember-view">the letter: B</li>
15476     <li class="ember-view">the letter: C</li>
15477   </ul>
15478   ```
15479
15480   Additional tagName pairs can be provided by adding to `Ember.CollectionView.CONTAINER_MAP `
15481
15482   ``` javascript
15483   Ember.CollectionView.CONTAINER_MAP['article'] = 'section'
15484   ```
15485
15486
15487   ## Empty View
15488   You can provide an `Ember.View` subclass to the `Ember.CollectionView` instance as its
15489   `emptyView` property. If the `content` property of a `CollectionView` is set to `null`
15490   or an empty array, an instance of this view will be the `CollectionView`s only child.
15491
15492   ``` javascript
15493   aListWithNothing = Ember.CollectionView.create({
15494     classNames: ['nothing']
15495     content: null,
15496     emptyView: Ember.View.extend({
15497       template: Ember.Handlebars.compile("The collection is empty")
15498     })
15499   });
15500
15501   aListWithNothing.appendTo('body');
15502   ```
15503
15504   Will result in the following HTML structure
15505
15506   ``` html
15507   <div class="ember-view nothing">
15508     <div class="ember-view">
15509       The collection is empty
15510     </div>
15511   </div>
15512   ```
15513
15514   ## Adding and Removing items
15515   The `childViews` property of a `CollectionView` should not be directly manipulated. Instead,
15516   add, remove, replace items from its `content` property. This will trigger
15517   appropriate changes to its rendered HTML.
15518
15519   ## Use in templates via the `{{collection}}` Ember.Handlebars helper
15520   Ember.Handlebars provides a helper specifically for adding `CollectionView`s to templates.
15521   See `Ember.Handlebars.collection` for more details
15522
15523   @class CollectionView
15524   @namespace Ember
15525   @extends Ember.ContainerView
15526   @since Ember 0.9
15527 */
15528 Ember.CollectionView = Ember.ContainerView.extend(
15529 /** @scope Ember.CollectionView.prototype */ {
15530
15531   /**
15532     A list of items to be displayed by the Ember.CollectionView.
15533
15534     @property content
15535     @type Ember.Array
15536     @default null
15537   */
15538   content: null,
15539
15540   /**
15541     @private
15542
15543     This provides metadata about what kind of empty view class this
15544     collection would like if it is being instantiated from another
15545     system (like Handlebars)
15546
15547     @property emptyViewClass
15548   */
15549   emptyViewClass: Ember.View,
15550
15551   /**
15552     An optional view to display if content is set to an empty array.
15553
15554     @property emptyView
15555     @type Ember.View
15556     @default null
15557   */
15558   emptyView: null,
15559
15560   /**
15561     @property itemViewClass
15562     @type Ember.View
15563     @default Ember.View
15564   */
15565   itemViewClass: Ember.View,
15566
15567   init: function() {
15568     var ret = this._super();
15569     this._contentDidChange();
15570     return ret;
15571   },
15572
15573   _contentWillChange: Ember.beforeObserver(function() {
15574     var content = this.get('content');
15575
15576     if (content) { content.removeArrayObserver(this); }
15577     var len = content ? get(content, 'length') : 0;
15578     this.arrayWillChange(content, 0, len);
15579   }, 'content'),
15580
15581   /**
15582     @private
15583
15584     Check to make sure that the content has changed, and if so,
15585     update the children directly. This is always scheduled
15586     asynchronously, to allow the element to be created before
15587     bindings have synchronized and vice versa.
15588
15589     @method _contentDidChange
15590   */
15591   _contentDidChange: Ember.observer(function() {
15592     var content = get(this, 'content');
15593
15594     if (content) {
15595       Ember.assert(fmt("an Ember.CollectionView's content must implement Ember.Array. You passed %@", [content]), Ember.Array.detect(content));
15596       content.addArrayObserver(this);
15597     }
15598
15599     var len = content ? get(content, 'length') : 0;
15600     this.arrayDidChange(content, 0, null, len);
15601   }, 'content'),
15602
15603   willDestroy: function() {
15604     var content = get(this, 'content');
15605     if (content) { content.removeArrayObserver(this); }
15606
15607     this._super();
15608   },
15609
15610   arrayWillChange: function(content, start, removedCount) {
15611     // If the contents were empty before and this template collection has an
15612     // empty view remove it now.
15613     var emptyView = get(this, 'emptyView');
15614     if (emptyView && emptyView instanceof Ember.View) {
15615       emptyView.removeFromParent();
15616     }
15617
15618     // Loop through child views that correspond with the removed items.
15619     // Note that we loop from the end of the array to the beginning because
15620     // we are mutating it as we go.
15621     var childViews = get(this, 'childViews'), childView, idx, len;
15622
15623     len = get(childViews, 'length');
15624
15625     var removingAll = removedCount === len;
15626
15627     if (removingAll) {
15628       this.invokeForState('empty');
15629     }
15630
15631     for (idx = start + removedCount - 1; idx >= start; idx--) {
15632       childView = childViews[idx];
15633       if (removingAll) { childView.removedFromDOM = true; }
15634       childView.destroy();
15635     }
15636   },
15637
15638   /**
15639     Called when a mutation to the underlying content array occurs.
15640
15641     This method will replay that mutation against the views that compose the
15642     Ember.CollectionView, ensuring that the view reflects the model.
15643
15644     This array observer is added in contentDidChange.
15645
15646     @method arrayDidChange
15647     @param {Array} addedObjects the objects that were added to the content
15648     @param {Array} removedObjects the objects that were removed from the content
15649     @param {Number} changeIndex the index at which the changes occurred
15650   */
15651   arrayDidChange: function(content, start, removed, added) {
15652     var itemViewClass = get(this, 'itemViewClass'),
15653         childViews = get(this, 'childViews'),
15654         addedViews = [], view, item, idx, len, itemTagName;
15655
15656     if ('string' === typeof itemViewClass) {
15657       itemViewClass = get(itemViewClass);
15658     }
15659
15660     Ember.assert(fmt("itemViewClass must be a subclass of Ember.View, not %@", [itemViewClass]), Ember.View.detect(itemViewClass));
15661
15662     len = content ? get(content, 'length') : 0;
15663     if (len) {
15664       for (idx = start; idx < start+added; idx++) {
15665         item = content.objectAt(idx);
15666
15667         view = this.createChildView(itemViewClass, {
15668           content: item,
15669           contentIndex: idx
15670         });
15671
15672         addedViews.push(view);
15673       }
15674     } else {
15675       var emptyView = get(this, 'emptyView');
15676       if (!emptyView) { return; }
15677
15678       emptyView = this.createChildView(emptyView);
15679       addedViews.push(emptyView);
15680       set(this, 'emptyView', emptyView);
15681     }
15682     childViews.replace(start, 0, addedViews);
15683   },
15684
15685   createChildView: function(view, attrs) {
15686     view = this._super(view, attrs);
15687
15688     var itemTagName = get(view, 'tagName');
15689     var tagName = (itemTagName === null || itemTagName === undefined) ? Ember.CollectionView.CONTAINER_MAP[get(this, 'tagName')] : itemTagName;
15690
15691     set(view, 'tagName', tagName);
15692
15693     return view;
15694   }
15695 });
15696
15697 /**
15698   A map of parent tags to their default child tags. You can add
15699   additional parent tags if you want collection views that use
15700   a particular parent tag to default to a child tag.
15701
15702   @property CONTAINER_MAP
15703   @type Hash
15704   @static
15705   @final
15706 */
15707 Ember.CollectionView.CONTAINER_MAP = {
15708   ul: 'li',
15709   ol: 'li',
15710   table: 'tr',
15711   thead: 'tr',
15712   tbody: 'tr',
15713   tfoot: 'tr',
15714   tr: 'td',
15715   select: 'option'
15716 };
15717
15718 })();
15719
15720
15721
15722 (function() {
15723
15724 })();
15725
15726
15727
15728 (function() {
15729 /*globals jQuery*/
15730 /**
15731 Ember Views
15732
15733 @module ember
15734 @submodule ember-views
15735 @require ember-runtime
15736 @main ember-views
15737 */
15738
15739 })();
15740
15741 (function() {
15742 var get = Ember.get, set = Ember.set;
15743
15744 /**
15745 @module ember
15746 @submodule ember-states
15747 */
15748
15749 /**
15750   @class State
15751   @namespace Ember
15752   @extends Ember.Object
15753   @uses Ember.Evented
15754 */
15755 Ember.State = Ember.Object.extend(Ember.Evented,
15756 /** @scope Ember.State.prototype */{
15757   isState: true,
15758
15759   /**
15760     A reference to the parent state.
15761
15762     @property parentState
15763     @type Ember.State
15764   */
15765   parentState: null,
15766   start: null,
15767
15768   /**
15769     The name of this state.
15770
15771     @property name
15772     @type String
15773   */
15774   name: null,
15775
15776   /**
15777     The full path to this state.
15778
15779     @property path
15780     @type String
15781   */
15782   path: Ember.computed(function() {
15783     var parentPath = get(this, 'parentState.path'),
15784         path = get(this, 'name');
15785
15786     if (parentPath) {
15787       path = parentPath + '.' + path;
15788     }
15789
15790     return path;
15791   }).property().cacheable(),
15792
15793   /**
15794     @private
15795
15796     Override the default event firing from Ember.Evented to
15797     also call methods with the given name.
15798
15799     @method trigger
15800     @param name
15801   */
15802   trigger: function(name) {
15803     if (this[name]) {
15804       this[name].apply(this, [].slice.call(arguments, 1));
15805     }
15806     this._super.apply(this, arguments);
15807   },
15808
15809   init: function() {
15810     var states = get(this, 'states'), foundStates;
15811     set(this, 'childStates', Ember.A());
15812     set(this, 'eventTransitions', get(this, 'eventTransitions') || {});
15813
15814     var name, value, transitionTarget;
15815
15816     // As a convenience, loop over the properties
15817     // of this state and look for any that are other
15818     // Ember.State instances or classes, and move them
15819     // to the `states` hash. This avoids having to
15820     // create an explicit separate hash.
15821
15822     if (!states) {
15823       states = {};
15824
15825       for (name in this) {
15826         if (name === "constructor") { continue; }
15827
15828         if (value = this[name]) {
15829           if (transitionTarget = value.transitionTarget) {
15830             this.eventTransitions[name] = transitionTarget;
15831           }
15832
15833           this.setupChild(states, name, value);
15834         }
15835       }
15836
15837       set(this, 'states', states);
15838     } else {
15839       for (name in states) {
15840         this.setupChild(states, name, states[name]);
15841       }
15842     }
15843
15844     set(this, 'pathsCache', {});
15845     set(this, 'pathsCacheNoContext', {});
15846   },
15847
15848   setupChild: function(states, name, value) {
15849     if (!value) { return false; }
15850
15851     if (value.isState) {
15852       set(value, 'name', name);
15853     } else if (Ember.State.detect(value)) {
15854       value = value.create({
15855         name: name
15856       });
15857     }
15858
15859     if (value.isState) {
15860       set(value, 'parentState', this);
15861       get(this, 'childStates').pushObject(value);
15862       states[name] = value;
15863       return value;
15864     }
15865   },
15866
15867   lookupEventTransition: function(name) {
15868     var path, state = this;
15869
15870     while(state && !path) {
15871       path = state.eventTransitions[name];
15872       state = state.get('parentState');
15873     }
15874
15875     return path;
15876   },
15877
15878   /**
15879     A Boolean value indicating whether the state is a leaf state
15880     in the state hierarchy. This is false if the state has child
15881     states; otherwise it is true.
15882
15883     @property isLeaf
15884     @type Boolean
15885   */
15886   isLeaf: Ember.computed(function() {
15887     return !get(this, 'childStates').length;
15888   }).cacheable(),
15889
15890   /**
15891     A boolean value indicating whether the state takes a context.
15892     By default we assume all states take contexts.
15893
15894     @property hasContext
15895     @default true
15896   */
15897   hasContext: true,
15898
15899   /**
15900     This is the default transition event.
15901
15902     @event setup
15903     @param {Ember.StateManager} manager
15904     @param context
15905     @see Ember.StateManager#transitionEvent
15906   */
15907   setup: Ember.K,
15908
15909   /**
15910     This event fires when the state is entered.
15911
15912     @event enter
15913     @param {Ember.StateManager} manager
15914   */
15915   enter: Ember.K,
15916
15917   /**
15918     This event fires when the state is exited.
15919
15920     @event exit
15921     @param {Ember.StateManager} manager
15922   */
15923   exit: Ember.K
15924 });
15925
15926 var Event = Ember.$ && Ember.$.Event;
15927
15928 Ember.State.reopenClass(
15929 /** @scope Ember.State */{
15930
15931   /**
15932   Creates an action function for transitioning to the named state while preserving context.
15933
15934   The following example StateManagers are equivalent:
15935
15936       aManager = Ember.StateManager.create({
15937         stateOne: Ember.State.create({
15938           changeToStateTwo: Ember.State.transitionTo('stateTwo')
15939         }),
15940         stateTwo: Ember.State.create({})
15941       })
15942
15943       bManager = Ember.StateManager.create({
15944         stateOne: Ember.State.create({
15945           changeToStateTwo: function(manager, context){
15946             manager.transitionTo('stateTwo', context)
15947           }
15948         }),
15949         stateTwo: Ember.State.create({})
15950       })
15951
15952   @method transitionTo
15953   @static
15954   @param {String} target
15955   */
15956   transitionTo: function(target) {
15957     var event = function(stateManager, context) {
15958       if (Event && context instanceof Event) {
15959         if (context.hasOwnProperty('context')) {
15960           context = context.context;
15961         } else {
15962           // If we received an event and it doesn't contain
15963           // a context, don't pass along a superfluous
15964           // context to the target of the event.
15965           return stateManager.transitionTo(target);
15966         }
15967       }
15968
15969       stateManager.transitionTo(target, context);
15970     };
15971
15972     event.transitionTarget = target;
15973
15974     return event;
15975   }
15976 });
15977
15978 })();
15979
15980
15981
15982 (function() {
15983 /**
15984 @module ember
15985 @submodule ember-states
15986 */
15987
15988 var get = Ember.get, set = Ember.set, fmt = Ember.String.fmt;
15989 var arrayForEach = Ember.ArrayPolyfills.forEach;
15990 /**
15991   A Transition takes the enter, exit and resolve states and normalizes
15992   them:
15993
15994   * takes any passed in contexts into consideration
15995   * adds in `initialState`s
15996
15997   @class Transition
15998   @private
15999 */
16000 var Transition = function(raw) {
16001   this.enterStates = raw.enterStates.slice();
16002   this.exitStates = raw.exitStates.slice();
16003   this.resolveState = raw.resolveState;
16004
16005   this.finalState = raw.enterStates[raw.enterStates.length - 1] || raw.resolveState;
16006 };
16007
16008 Transition.prototype = {
16009   /**
16010     Normalize the passed in enter, exit and resolve states.
16011
16012     This process also adds `finalState` and `contexts` to the Transition object.
16013
16014     @method normalize
16015     @param {Ember.StateManager} manager the state manager running the transition
16016     @param {Array} contexts a list of contexts passed into `transitionTo`
16017   */
16018   normalize: function(manager, contexts) {
16019     this.matchContextsToStates(contexts);
16020     this.addInitialStates();
16021     this.removeUnchangedContexts(manager);
16022     return this;
16023   },
16024
16025   /**
16026     Match each of the contexts passed to `transitionTo` to a state.
16027     This process may also require adding additional enter and exit
16028     states if there are more contexts than enter states.
16029
16030     @method matchContextsToStates
16031     @param {Array} contexts a list of contexts passed into `transitionTo`
16032   */
16033   matchContextsToStates: function(contexts) {
16034     var stateIdx = this.enterStates.length - 1,
16035         matchedContexts = [],
16036         state,
16037         context;
16038
16039     // Next, we will match the passed in contexts to the states they
16040     // represent.
16041     //
16042     // First, assign a context to each enter state in reverse order. If
16043     // any contexts are left, add a parent state to the list of states
16044     // to enter and exit, and assign a context to the parent state.
16045     //
16046     // If there are still contexts left when the state manager is
16047     // reached, raise an exception.
16048     //
16049     // This allows the following:
16050     //
16051     // |- root
16052     // | |- post
16053     // | | |- comments
16054     // | |- about (* current state)
16055     //
16056     // For `transitionTo('post.comments', post, post.get('comments')`,
16057     // the first context (`post`) will be assigned to `root.post`, and
16058     // the second context (`post.get('comments')`) will be assigned
16059     // to `root.post.comments`.
16060     //
16061     // For the following:
16062     //
16063     // |- root
16064     // | |- post
16065     // | | |- index (* current state)
16066     // | | |- comments
16067     //
16068     // For `transitionTo('post.comments', otherPost, otherPost.get('comments')`,
16069     // the `<root.post>` state will be added to the list of enter and exit
16070     // states because its context has changed.
16071
16072     while (contexts.length > 0) {
16073       if (stateIdx >= 0) {
16074         state = this.enterStates[stateIdx--];
16075       } else {
16076         if (this.enterStates.length) {
16077           state = get(this.enterStates[0], 'parentState');
16078           if (!state) { throw "Cannot match all contexts to states"; }
16079         } else {
16080           // If re-entering the current state with a context, the resolve
16081           // state will be the current state.
16082           state = this.resolveState;
16083         }
16084
16085         this.enterStates.unshift(state);
16086         this.exitStates.unshift(state);
16087       }
16088
16089       // in routers, only states with dynamic segments have a context
16090       if (get(state, 'hasContext')) {
16091         context = contexts.pop();
16092       } else {
16093         context = null;
16094       }
16095
16096       matchedContexts.unshift(context);
16097     }
16098
16099     this.contexts = matchedContexts;
16100   },
16101
16102   /**
16103     Add any `initialState`s to the list of enter states.
16104
16105     @method addInitialStates
16106   */
16107   addInitialStates: function() {
16108     var finalState = this.finalState, initialState;
16109
16110     while(true) {
16111       initialState = get(finalState, 'initialState') || 'start';
16112       finalState = get(finalState, 'states.' + initialState);
16113
16114       if (!finalState) { break; }
16115
16116       this.finalState = finalState;
16117       this.enterStates.push(finalState);
16118       this.contexts.push(undefined);
16119     }
16120   },
16121
16122   /**
16123     Remove any states that were added because the number of contexts
16124     exceeded the number of explicit enter states, but the context has
16125     not changed since the last time the state was entered.
16126
16127     @method removeUnchangedContexts
16128     @param {Ember.StateManager} manager passed in to look up the last
16129       context for a states
16130   */
16131   removeUnchangedContexts: function(manager) {
16132     // Start from the beginning of the enter states. If the state was added
16133     // to the list during the context matching phase, make sure the context
16134     // has actually changed since the last time the state was entered.
16135     while (this.enterStates.length > 0) {
16136       if (this.enterStates[0] !== this.exitStates[0]) { break; }
16137
16138       if (this.enterStates.length === this.contexts.length) {
16139         if (manager.getStateMeta(this.enterStates[0], 'context') !== this.contexts[0]) { break; }
16140         this.contexts.shift();
16141       }
16142
16143       this.resolveState = this.enterStates.shift();
16144       this.exitStates.shift();
16145     }
16146   }
16147 };
16148
16149 /**
16150   StateManager is part of Ember's implementation of a finite state machine. A StateManager
16151   instance manages a number of properties that are instances of `Ember.State`,
16152   tracks the current active state, and triggers callbacks when states have changed.
16153
16154   ## Defining States
16155
16156   The states of StateManager can be declared in one of two ways. First, you can define
16157   a `states` property that contains all the states:
16158
16159       managerA = Ember.StateManager.create({
16160         states: {
16161           stateOne: Ember.State.create(),
16162           stateTwo: Ember.State.create()
16163         }
16164       })
16165
16166       managerA.get('states')
16167       // {
16168       //   stateOne: Ember.State.create(),
16169       //   stateTwo: Ember.State.create()
16170       // }
16171
16172   You can also add instances of `Ember.State` (or an `Ember.State` subclass) directly as properties
16173   of a StateManager. These states will be collected into the `states` property for you.
16174
16175       managerA = Ember.StateManager.create({
16176         stateOne: Ember.State.create(),
16177         stateTwo: Ember.State.create()
16178       })
16179
16180       managerA.get('states')
16181       // {
16182       //   stateOne: Ember.State.create(),
16183       //   stateTwo: Ember.State.create()
16184       // }
16185
16186   ## The Initial State
16187   When created a StateManager instance will immediately enter into the state
16188   defined as its `start` property or the state referenced by name in its
16189   `initialState` property:
16190
16191       managerA = Ember.StateManager.create({
16192         start: Ember.State.create({})
16193       })
16194
16195       managerA.get('currentState.name') // 'start'
16196
16197       managerB = Ember.StateManager.create({
16198         initialState: 'beginHere',
16199         beginHere: Ember.State.create({})
16200       })
16201
16202       managerB.get('currentState.name') // 'beginHere'
16203
16204   Because it is a property you may also provide a computed function if you wish to derive
16205   an `initialState` programmatically:
16206
16207       managerC = Ember.StateManager.create({
16208         initialState: function(){
16209           if (someLogic) {
16210             return 'active';
16211           } else {
16212             return 'passive';
16213           }
16214         }.property(),
16215         active: Ember.State.create({}),
16216         passive: Ember.State.create({})
16217       })
16218
16219   ## Moving Between States
16220   A StateManager can have any number of Ember.State objects as properties
16221   and can have a single one of these states as its current state.
16222
16223   Calling `transitionTo` transitions between states:
16224
16225       robotManager = Ember.StateManager.create({
16226         initialState: 'poweredDown',
16227         poweredDown: Ember.State.create({}),
16228         poweredUp: Ember.State.create({})
16229       })
16230
16231       robotManager.get('currentState.name') // 'poweredDown'
16232       robotManager.transitionTo('poweredUp')
16233       robotManager.get('currentState.name') // 'poweredUp'
16234
16235   Before transitioning into a new state the existing `currentState` will have its
16236   `exit` method called with the StateManager instance as its first argument and
16237   an object representing the transition as its second argument.
16238
16239   After transitioning into a new state the new `currentState` will have its
16240   `enter` method called with the StateManager instance as its first argument and
16241   an object representing the transition as its second argument.
16242
16243       robotManager = Ember.StateManager.create({
16244         initialState: 'poweredDown',
16245         poweredDown: Ember.State.create({
16246           exit: function(stateManager){
16247             console.log("exiting the poweredDown state")
16248           }
16249         }),
16250         poweredUp: Ember.State.create({
16251           enter: function(stateManager){
16252             console.log("entering the poweredUp state. Destroy all humans.")
16253           }
16254         })
16255       })
16256
16257       robotManager.get('currentState.name') // 'poweredDown'
16258       robotManager.transitionTo('poweredUp')
16259       // will log
16260       // 'exiting the poweredDown state'
16261       // 'entering the poweredUp state. Destroy all humans.'
16262
16263
16264   Once a StateManager is already in a state, subsequent attempts to enter that state will
16265   not trigger enter or exit method calls. Attempts to transition into a state that the
16266   manager does not have will result in no changes in the StateManager's current state:
16267
16268       robotManager = Ember.StateManager.create({
16269         initialState: 'poweredDown',
16270         poweredDown: Ember.State.create({
16271           exit: function(stateManager){
16272             console.log("exiting the poweredDown state")
16273           }
16274         }),
16275         poweredUp: Ember.State.create({
16276           enter: function(stateManager){
16277             console.log("entering the poweredUp state. Destroy all humans.")
16278           }
16279         })
16280       })
16281
16282       robotManager.get('currentState.name') // 'poweredDown'
16283       robotManager.transitionTo('poweredUp')
16284       // will log
16285       // 'exiting the poweredDown state'
16286       // 'entering the poweredUp state. Destroy all humans.'
16287       robotManager.transitionTo('poweredUp') // no logging, no state change
16288
16289       robotManager.transitionTo('someUnknownState') // silently fails
16290       robotManager.get('currentState.name') // 'poweredUp'
16291
16292
16293   Each state property may itself contain properties that are instances of Ember.State.
16294   The StateManager can transition to specific sub-states in a series of transitionTo method calls or
16295   via a single transitionTo with the full path to the specific state. The StateManager will also
16296   keep track of the full path to its currentState
16297
16298       robotManager = Ember.StateManager.create({
16299         initialState: 'poweredDown',
16300         poweredDown: Ember.State.create({
16301           charging: Ember.State.create(),
16302           charged: Ember.State.create()
16303         }),
16304         poweredUp: Ember.State.create({
16305           mobile: Ember.State.create(),
16306           stationary: Ember.State.create()
16307         })
16308       })
16309
16310       robotManager.get('currentState.name') // 'poweredDown'
16311
16312       robotManager.transitionTo('poweredUp')
16313       robotManager.get('currentState.name') // 'poweredUp'
16314
16315       robotManager.transitionTo('mobile')
16316       robotManager.get('currentState.name') // 'mobile'
16317
16318       // transition via a state path
16319       robotManager.transitionTo('poweredDown.charging')
16320       robotManager.get('currentState.name') // 'charging'
16321
16322       robotManager.get('currentState.path') // 'poweredDown.charging'
16323
16324   Enter transition methods will be called for each state and nested child state in their
16325   hierarchical order.  Exit methods will be called for each state and its nested states in
16326   reverse hierarchical order.
16327
16328   Exit transitions for a parent state are not called when entering into one of its child states,
16329   only when transitioning to a new section of possible states in the hierarchy.
16330
16331       robotManager = Ember.StateManager.create({
16332         initialState: 'poweredDown',
16333         poweredDown: Ember.State.create({
16334           enter: function(){},
16335           exit: function(){
16336             console.log("exited poweredDown state")
16337           },
16338           charging: Ember.State.create({
16339             enter: function(){},
16340             exit: function(){}
16341           }),
16342           charged: Ember.State.create({
16343             enter: function(){
16344               console.log("entered charged state")
16345             },
16346             exit: function(){
16347               console.log("exited charged state")
16348             }
16349           })
16350         }),
16351         poweredUp: Ember.State.create({
16352           enter: function(){
16353             console.log("entered poweredUp state")
16354           },
16355           exit: function(){},
16356           mobile: Ember.State.create({
16357             enter: function(){
16358               console.log("entered mobile state")
16359             },
16360             exit: function(){}
16361           }),
16362           stationary: Ember.State.create({
16363             enter: function(){},
16364             exit: function(){}
16365           })
16366         })
16367       })
16368
16369
16370       robotManager.get('currentState.path') // 'poweredDown'
16371       robotManager.transitionTo('charged')
16372       // logs 'entered charged state'
16373       // but does *not* log  'exited poweredDown state'
16374       robotManager.get('currentState.name') // 'charged
16375
16376       robotManager.transitionTo('poweredUp.mobile')
16377       // logs
16378       // 'exited charged state'
16379       // 'exited poweredDown state'
16380       // 'entered poweredUp state'
16381       // 'entered mobile state'
16382
16383   During development you can set a StateManager's `enableLogging` property to `true` to
16384   receive console messages of state transitions.
16385
16386       robotManager = Ember.StateManager.create({
16387         enableLogging: true
16388       })
16389
16390   ## Managing currentState with Actions
16391   To control which transitions between states are possible for a given state, StateManager
16392   can receive and route action messages to its states via the `send` method.  Calling to `send` with
16393   an action name will begin searching for a method with the same name starting at the current state
16394   and moving up through the parent states in a state hierarchy until an appropriate method is found
16395   or the StateManager instance itself is reached.
16396
16397   If an appropriately named method is found it will be called with the state manager as the first
16398   argument and an optional `context` object as the second argument.
16399
16400       managerA = Ember.StateManager.create({
16401         initialState: 'stateOne.substateOne.subsubstateOne',
16402         stateOne: Ember.State.create({
16403           substateOne: Ember.State.create({
16404             anAction: function(manager, context){
16405               console.log("an action was called")
16406             },
16407             subsubstateOne: Ember.State.create({})
16408           })
16409         })
16410       })
16411
16412       managerA.get('currentState.name') // 'subsubstateOne'
16413       managerA.send('anAction')
16414       // 'stateOne.substateOne.subsubstateOne' has no anAction method
16415       // so the 'anAction' method of 'stateOne.substateOne' is called
16416       // and logs "an action was called"
16417       // with managerA as the first argument
16418       // and no second argument
16419
16420       someObject = {}
16421       managerA.send('anAction', someObject)
16422       // the 'anAction' method of 'stateOne.substateOne' is called again
16423       // with managerA as the first argument and
16424       // someObject as the second argument.
16425
16426
16427   If the StateManager attempts to send an action but does not find an appropriately named
16428   method in the current state or while moving upwards through the state hierarchy
16429   it will throw a new Ember.Error. Action detection only moves upwards through the state hierarchy
16430   from the current state. It does not search in other portions of the hierarchy.
16431
16432       managerB = Ember.StateManager.create({
16433         initialState: 'stateOne.substateOne.subsubstateOne',
16434         stateOne: Ember.State.create({
16435           substateOne: Ember.State.create({
16436             subsubstateOne: Ember.State.create({})
16437           })
16438         }),
16439         stateTwo: Ember.State.create({
16440          anAction: function(manager, context){
16441            // will not be called below because it is
16442            // not a parent of the current state
16443          }
16444         })
16445       })
16446
16447       managerB.get('currentState.name') // 'subsubstateOne'
16448       managerB.send('anAction')
16449       // Error: <Ember.StateManager:ember132> could not
16450       // respond to event anAction in state stateOne.substateOne.subsubstateOne.
16451
16452   Inside of an action method the given state should delegate `transitionTo` calls on its
16453   StateManager.
16454
16455       robotManager = Ember.StateManager.create({
16456         initialState: 'poweredDown.charging',
16457         poweredDown: Ember.State.create({
16458           charging: Ember.State.create({
16459             chargeComplete: function(manager, context){
16460               manager.transitionTo('charged')
16461             }
16462           }),
16463           charged: Ember.State.create({
16464             boot: function(manager, context){
16465               manager.transitionTo('poweredUp')
16466             }
16467           })
16468         }),
16469         poweredUp: Ember.State.create({
16470           beginExtermination: function(manager, context){
16471             manager.transitionTo('rampaging')
16472           },
16473           rampaging: Ember.State.create()
16474         })
16475       })
16476
16477       robotManager.get('currentState.name') // 'charging'
16478       robotManager.send('boot') // throws error, no boot action
16479                                 // in current hierarchy
16480       robotManager.get('currentState.name') // remains 'charging'
16481
16482       robotManager.send('beginExtermination') // throws error, no beginExtermination
16483                                               // action in current hierarchy
16484       robotManager.get('currentState.name') // remains 'charging'
16485
16486       robotManager.send('chargeComplete')
16487       robotManager.get('currentState.name') // 'charged'
16488
16489       robotManager.send('boot')
16490       robotManager.get('currentState.name') // 'poweredUp'
16491
16492       robotManager.send('beginExtermination', allHumans)
16493       robotManager.get('currentState.name') // 'rampaging'
16494
16495   Transition actions can also be created using the `transitionTo` method of the Ember.State class. The
16496   following example StateManagers are equivalent:
16497
16498       aManager = Ember.StateManager.create({
16499         stateOne: Ember.State.create({
16500           changeToStateTwo: Ember.State.transitionTo('stateTwo')
16501         }),
16502         stateTwo: Ember.State.create({})
16503       })
16504
16505       bManager = Ember.StateManager.create({
16506         stateOne: Ember.State.create({
16507           changeToStateTwo: function(manager, context){
16508             manager.transitionTo('stateTwo', context)
16509           }
16510         }),
16511         stateTwo: Ember.State.create({})
16512       })
16513
16514   @class StateManager
16515   @namespace Ember
16516   @extends Ember.State
16517 **/
16518 Ember.StateManager = Ember.State.extend({
16519   /**
16520     @private
16521
16522     When creating a new statemanager, look for a default state to transition
16523     into. This state can either be named `start`, or can be specified using the
16524     `initialState` property.
16525
16526     @method init
16527   */
16528   init: function() {
16529     this._super();
16530
16531     set(this, 'stateMeta', Ember.Map.create());
16532
16533     var initialState = get(this, 'initialState');
16534
16535     if (!initialState && get(this, 'states.start')) {
16536       initialState = 'start';
16537     }
16538
16539     if (initialState) {
16540       this.transitionTo(initialState);
16541       Ember.assert('Failed to transition to initial state "' + initialState + '"', !!get(this, 'currentState'));
16542     }
16543   },
16544
16545   stateMetaFor: function(state) {
16546     var meta = get(this, 'stateMeta'),
16547         stateMeta = meta.get(state);
16548
16549     if (!stateMeta) {
16550       stateMeta = {};
16551       meta.set(state, stateMeta);
16552     }
16553
16554     return stateMeta;
16555   },
16556
16557   setStateMeta: function(state, key, value) {
16558     return set(this.stateMetaFor(state), key, value);
16559   },
16560
16561   getStateMeta: function(state, key) {
16562     return get(this.stateMetaFor(state), key);
16563   },
16564
16565   /**
16566     The current state from among the manager's possible states. This property should
16567     not be set directly.  Use `transitionTo` to move between states by name.
16568
16569     @property currentState
16570     @type Ember.State
16571   */
16572   currentState: null,
16573
16574   /**
16575    The path of the current state. Returns a string representation of the current
16576    state.
16577
16578    @property currentPath
16579    @type String
16580   */
16581   currentPath: Ember.computed('currentState', function() {
16582     return get(this, 'currentState.path');
16583   }).cacheable(),
16584
16585   /**
16586     The name of transitionEvent that this stateManager will dispatch
16587
16588     @property transitionEvent
16589     @type String
16590     @default 'setup'
16591   */
16592   transitionEvent: 'setup',
16593
16594   /**
16595     If set to true, `errorOnUnhandledEvents` will cause an exception to be
16596     raised if you attempt to send an event to a state manager that is not
16597     handled by the current state or any of its parent states.
16598
16599     @property errorOnUnhandledEvents
16600     @type Boolean
16601     @default true
16602   */
16603   errorOnUnhandledEvent: true,
16604
16605   send: function(event, context) {
16606     Ember.assert('Cannot send event "' + event + '" while currentState is ' + get(this, 'currentState'), get(this, 'currentState'));
16607     return this.sendRecursively(event, get(this, 'currentState'), context);
16608   },
16609
16610   sendRecursively: function(event, currentState, context) {
16611     var log = this.enableLogging,
16612         action = currentState[event];
16613
16614     // Test to see if the action is a method that
16615     // can be invoked. Don't blindly check just for
16616     // existence, because it is possible the state
16617     // manager has a child state of the given name,
16618     // and we should still raise an exception in that
16619     // case.
16620     if (typeof action === 'function') {
16621       if (log) { Ember.Logger.log(fmt("STATEMANAGER: Sending event '%@' to state %@.", [event, get(currentState, 'path')])); }
16622       return action.call(currentState, this, context);
16623     } else {
16624       var parentState = get(currentState, 'parentState');
16625       if (parentState) {
16626         return this.sendRecursively(event, parentState, context);
16627       } else if (get(this, 'errorOnUnhandledEvent')) {
16628         throw new Ember.Error(this.toString() + " could not respond to event " + event + " in state " + get(this, 'currentState.path') + ".");
16629       }
16630     }
16631   },
16632
16633   /**
16634     Finds a state by its state path.
16635
16636     Example:
16637
16638         manager = Ember.StateManager.create({
16639           root: Ember.State.create({
16640             dashboard: Ember.State.create()
16641           })
16642         });
16643
16644         manager.getStateByPath(manager, "root.dashboard")
16645
16646         // returns the dashboard state
16647
16648     @method getStateByPath
16649     @param {Ember.State} root the state to start searching from
16650     @param {String} path the state path to follow
16651     @return {Ember.State} the state at the end of the path
16652   */
16653   getStateByPath: function(root, path) {
16654     var parts = path.split('.'),
16655         state = root;
16656
16657     for (var i=0, l=parts.length; i<l; i++) {
16658       state = get(get(state, 'states'), parts[i]);
16659       if (!state) { break; }
16660     }
16661
16662     return state;
16663   },
16664
16665   findStateByPath: function(state, path) {
16666     var possible;
16667
16668     while (!possible && state) {
16669       possible = this.getStateByPath(state, path);
16670       state = get(state, 'parentState');
16671     }
16672
16673     return possible;
16674   },
16675
16676   /**
16677     A state stores its child states in its `states` hash.
16678     This code takes a path like `posts.show` and looks
16679     up `origin.states.posts.states.show`.
16680
16681     It returns a list of all of the states from the
16682     origin, which is the list of states to call `enter`
16683     on.
16684
16685     @method findStateByPath
16686     @param origin
16687     @param path
16688   */
16689   findStatesByPath: function(origin, path) {
16690     if (!path || path === "") { return undefined; }
16691     var r = path.split('.'),
16692         ret = [];
16693
16694     for (var i=0, len = r.length; i < len; i++) {
16695       var states = get(origin, 'states');
16696
16697       if (!states) { return undefined; }
16698
16699       var s = get(states, r[i]);
16700       if (s) { origin = s; ret.push(s); }
16701       else { return undefined; }
16702     }
16703
16704     return ret;
16705   },
16706
16707   goToState: function() {
16708     // not deprecating this yet so people don't constantly need to
16709     // make trivial changes for little reason.
16710     return this.transitionTo.apply(this, arguments);
16711   },
16712
16713   transitionTo: function(path, context) {
16714     // XXX When is transitionTo called with no path
16715     if (Ember.empty(path)) { return; }
16716
16717     // The ES6 signature of this function is `path, ...contexts`
16718     var contexts = context ? Array.prototype.slice.call(arguments, 1) : [],
16719         currentState = get(this, 'currentState') || this;
16720
16721     // First, get the enter, exit and resolve states for the current state
16722     // and specified path. If possible, use an existing cache.
16723     var hash = this.contextFreeTransition(currentState, path);
16724
16725     // Next, process the raw state information for the contexts passed in.
16726     var transition = new Transition(hash).normalize(this, contexts);
16727
16728     this.enterState(transition);
16729     this.triggerSetupContext(transition);
16730   },
16731
16732   contextFreeTransition: function(currentState, path) {
16733     var cache = currentState.pathsCache[path];
16734     if (cache) { return cache; }
16735
16736     var enterStates = this.findStatesByPath(currentState, path),
16737         exitStates = [],
16738         resolveState = currentState;
16739
16740     // Walk up the states. For each state, check whether a state matching
16741     // the `path` is nested underneath. This will find the closest
16742     // parent state containing `path`.
16743     //
16744     // This allows the user to pass in a relative path. For example, for
16745     // the following state hierarchy:
16746     //
16747     //    | |root
16748     //    | |- posts
16749     //    | | |- show (* current)
16750     //    | |- comments
16751     //    | | |- show
16752     //
16753     // If the current state is `<root.posts.show>`, an attempt to
16754     // transition to `comments.show` will match `<root.comments.show>`.
16755     //
16756     // First, this code will look for root.posts.show.comments.show.
16757     // Next, it will look for root.posts.comments.show. Finally,
16758     // it will look for `root.comments.show`, and find the state.
16759     //
16760     // After this process, the following variables will exist:
16761     //
16762     // * resolveState: a common parent state between the current
16763     //   and target state. In the above example, `<root>` is the
16764     //   `resolveState`.
16765     // * enterStates: a list of all of the states represented
16766     //   by the path from the `resolveState`. For example, for
16767     //   the path `root.comments.show`, `enterStates` would have
16768     //   `[<root.comments>, <root.comments.show>]`
16769     // * exitStates: a list of all of the states from the
16770     //   `resolveState` to the `currentState`. In the above
16771     //   example, `exitStates` would have
16772     //   `[<root.posts>`, `<root.posts.show>]`.
16773     while (resolveState && !enterStates) {
16774       exitStates.unshift(resolveState);
16775
16776       resolveState = get(resolveState, 'parentState');
16777       if (!resolveState) {
16778         enterStates = this.findStatesByPath(this, path);
16779         if (!enterStates) {
16780           Ember.assert('Could not find state for path: "'+path+'"');
16781           return;
16782         }
16783       }
16784       enterStates = this.findStatesByPath(resolveState, path);
16785     }
16786
16787     // If the path contains some states that are parents of both the
16788     // current state and the target state, remove them.
16789     //
16790     // For example, in the following hierarchy:
16791     //
16792     // |- root
16793     // | |- post
16794     // | | |- index (* current)
16795     // | | |- show
16796     //
16797     // If the `path` is `root.post.show`, the three variables will
16798     // be:
16799     //
16800     // * resolveState: `<state manager>`
16801     // * enterStates: `[<root>, <root.post>, <root.post.show>]`
16802     // * exitStates: `[<root>, <root.post>, <root.post.index>]`
16803     //
16804     // The goal of this code is to remove the common states, so we
16805     // have:
16806     //
16807     // * resolveState: `<root.post>`
16808     // * enterStates: `[<root.post.show>]`
16809     // * exitStates: `[<root.post.index>]`
16810     //
16811     // This avoid unnecessary calls to the enter and exit transitions.
16812     while (enterStates.length > 0 && enterStates[0] === exitStates[0]) {
16813       resolveState = enterStates.shift();
16814       exitStates.shift();
16815     }
16816
16817     // Cache the enterStates, exitStates, and resolveState for the
16818     // current state and the `path`.
16819     var transitions = currentState.pathsCache[path] = {
16820       exitStates: exitStates,
16821       enterStates: enterStates,
16822       resolveState: resolveState
16823     };
16824
16825     return transitions;
16826   },
16827
16828   triggerSetupContext: function(transitions) {
16829     var contexts = transitions.contexts,
16830         offset = transitions.enterStates.length - contexts.length,
16831         enterStates = transitions.enterStates,
16832         transitionEvent = get(this, 'transitionEvent');
16833
16834     Ember.assert("More contexts provided than states", offset >= 0);
16835
16836     arrayForEach.call(enterStates, function(state, idx) {
16837       state.trigger(transitionEvent, this, contexts[idx-offset]);
16838     }, this);
16839   },
16840
16841   getState: function(name) {
16842     var state = get(this, name),
16843         parentState = get(this, 'parentState');
16844
16845     if (state) {
16846       return state;
16847     } else if (parentState) {
16848       return parentState.getState(name);
16849     }
16850   },
16851
16852   enterState: function(transition) {
16853     var log = this.enableLogging;
16854
16855     var exitStates = transition.exitStates.slice(0).reverse();
16856     arrayForEach.call(exitStates, function(state) {
16857       state.trigger('exit', this);
16858     }, this);
16859
16860     arrayForEach.call(transition.enterStates, function(state) {
16861       if (log) { Ember.Logger.log("STATEMANAGER: Entering " + get(state, 'path')); }
16862       state.trigger('enter', this);
16863     }, this);
16864
16865     set(this, 'currentState', transition.finalState);
16866   }
16867 });
16868
16869 })();
16870
16871
16872
16873 (function() {
16874 /**
16875 Ember States
16876
16877 @module ember
16878 @submodule ember-states
16879 @requires ember-runtime
16880 */
16881
16882 })();
16883
16884 (function() {
16885 var get = Ember.get;
16886
16887 Ember._ResolvedState = Ember.Object.extend({
16888   manager: null,
16889   state: null,
16890   match: null,
16891
16892   object: Ember.computed(function(key, value) {
16893     if (arguments.length === 2) {
16894       this._object = value;
16895       return value;
16896     } else {
16897       if (this._object) {
16898         return this._object;
16899       } else {
16900         var state = get(this, 'state'),
16901             match = get(this, 'match'),
16902             manager = get(this, 'manager');
16903         return state.deserialize(manager, match.hash);
16904       }
16905     }
16906   }).property(),
16907
16908   hasPromise: Ember.computed(function() {
16909     return Ember.canInvoke(get(this, 'object'), 'then');
16910   }).property('object'),
16911
16912   promise: Ember.computed(function() {
16913     var object = get(this, 'object');
16914     if (Ember.canInvoke(object, 'then')) {
16915       return object;
16916     } else {
16917       return {
16918         then: function(success) { success(object); }
16919       };
16920     }
16921   }).property('object'),
16922
16923   transition: function() {
16924     var manager = get(this, 'manager'),
16925         path = get(this, 'state.path'),
16926         object = get(this, 'object');
16927     manager.transitionTo(path, object);
16928   }
16929 });
16930
16931 })();
16932
16933
16934
16935 (function() {
16936 /**
16937 @module ember
16938 @submodule ember-routing
16939 */
16940
16941 var get = Ember.get;
16942
16943 // The Ember Routable mixin assumes the existance of a simple
16944 // routing shim that supports the following three behaviors:
16945 //
16946 // * .getURL() - this is called when the page loads
16947 // * .setURL(newURL) - this is called from within the state
16948 //   manager when the state changes to a routable state
16949 // * .onURLChange(callback) - this happens when the user presses
16950 //   the back or forward button
16951
16952 var paramForClass = function(classObject) {
16953   var className = classObject.toString(),
16954       parts = className.split("."),
16955       last = parts[parts.length - 1];
16956
16957   return Ember.String.underscore(last) + "_id";
16958 };
16959
16960 var merge = function(original, hash) {
16961   for (var prop in hash) {
16962     if (!hash.hasOwnProperty(prop)) { continue; }
16963     if (original.hasOwnProperty(prop)) { continue; }
16964
16965     original[prop] = hash[prop];
16966   }
16967 };
16968
16969 /**
16970   @class Routable
16971   @namespace Ember
16972   @extends Ember.Mixin
16973 */
16974 Ember.Routable = Ember.Mixin.create({
16975   init: function() {
16976     var redirection;
16977     this.on('setup', this, this.stashContext);
16978
16979     if (redirection = get(this, 'redirectsTo')) {
16980       Ember.assert("You cannot use `redirectsTo` if you already have a `connectOutlets` method", this.connectOutlets === Ember.K);
16981
16982       this.connectOutlets = function(router) {
16983         router.transitionTo(redirection);
16984       };
16985     }
16986
16987     // normalize empty route to '/'
16988     var route = get(this, 'route');
16989     if (route === '') {
16990       route = '/';
16991     }
16992
16993     this._super();
16994
16995     Ember.assert("You cannot use `redirectsTo` on a state that has child states", !redirection || (!!redirection && !!get(this, 'isLeaf')));
16996   },
16997
16998   setup: function() {
16999     return this.connectOutlets.apply(this, arguments);
17000   },
17001
17002   /**
17003     @private
17004
17005     Whenever a routable state is entered, the context it was entered with
17006     is stashed so that we can regenerate the state's `absoluteURL` on
17007     demand.
17008
17009     @method stashContext
17010     @param manager {Ember.StateManager}
17011     @param context
17012   */
17013   stashContext: function(manager, context) {
17014     this.router = manager;
17015
17016     var serialized = this.serialize(manager, context);
17017     Ember.assert('serialize must return a hash', !serialized || typeof serialized === 'object');
17018
17019     manager.setStateMeta(this, 'context', context);
17020     manager.setStateMeta(this, 'serialized', serialized);
17021
17022     if (get(this, 'isRoutable') && !get(manager, 'isRouting')) {
17023       this.updateRoute(manager, get(manager, 'location'));
17024     }
17025   },
17026
17027   /**
17028     @private
17029
17030     Whenever a routable state is entered, the router's location object
17031     is notified to set the URL to the current absolute path.
17032
17033     In general, this will update the browser's URL.
17034
17035     @method updateRoute
17036     @param manager {Ember.StateManager}
17037     @param location {Ember.Location}
17038   */
17039   updateRoute: function(manager, location) {
17040     if (get(this, 'isLeafRoute')) {
17041       var path = this.absoluteRoute(manager);
17042       location.setURL(path);
17043     }
17044   },
17045
17046   /**
17047     @private
17048
17049     Get the absolute route for the current state and a given
17050     hash.
17051
17052     This method is private, as it expects a serialized hash,
17053     not the original context object.
17054
17055     @method absoluteRoute
17056     @param manager {Ember.StateManager}
17057     @param hash {Hash}
17058   */
17059   absoluteRoute: function(manager, hash) {
17060     var parentState = get(this, 'parentState');
17061     var path = '', generated;
17062
17063     // If the parent state is routable, use its current path
17064     // as this route's prefix.
17065     if (get(parentState, 'isRoutable')) {
17066       path = parentState.absoluteRoute(manager, hash);
17067     }
17068
17069     var matcher = get(this, 'routeMatcher'),
17070         serialized = manager.getStateMeta(this, 'serialized');
17071
17072     // merge the existing serialized object in with the passed
17073     // in hash.
17074     hash = hash || {};
17075     merge(hash, serialized);
17076
17077     generated = matcher && matcher.generate(hash);
17078
17079     if (generated) {
17080       path = path + '/' + generated;
17081     }
17082
17083     return path;
17084   },
17085
17086   /**
17087     @private
17088
17089     At the moment, a state is routable if it has a string `route`
17090     property. This heuristic may change.
17091
17092     @property isRoutable
17093     @type Boolean
17094   */
17095   isRoutable: Ember.computed(function() {
17096     return typeof get(this, 'route') === 'string';
17097   }).cacheable(),
17098
17099   /**
17100     @private
17101
17102     Determine if this is the last routeable state
17103
17104     @property isLeafRoute
17105     @type Boolean
17106   */
17107   isLeafRoute: Ember.computed(function() {
17108     if (get(this, 'isLeaf')) { return true; }
17109     return !get(this, 'childStates').findProperty('isRoutable');
17110   }).cacheable(),
17111
17112   /**
17113     @private
17114
17115     A _RouteMatcher object generated from the current route's `route`
17116     string property.
17117
17118     @property routeMatcher
17119     @type Ember._RouteMatcher
17120   */
17121   routeMatcher: Ember.computed(function() {
17122     var route = get(this, 'route');
17123     if (route) {
17124       return Ember._RouteMatcher.create({ route: route });
17125     }
17126   }).cacheable(),
17127
17128   /**
17129     @private
17130
17131     Check whether the route has dynamic segments and therefore takes
17132     a context.
17133
17134     @property hasContext
17135     @type Boolean
17136   */
17137   hasContext: Ember.computed(function() {
17138     var routeMatcher = get(this, 'routeMatcher');
17139     if (routeMatcher) {
17140       return routeMatcher.identifiers.length > 0;
17141     }
17142   }).cacheable(),
17143
17144   /**
17145     @private
17146
17147     The model class associated with the current state. This property
17148     uses the `modelType` property, in order to allow it to be
17149     specified as a String.
17150
17151     @property modelClass
17152     @type Ember.Object
17153   */
17154   modelClass: Ember.computed(function() {
17155     var modelType = get(this, 'modelType');
17156
17157     if (typeof modelType === 'string') {
17158       return Ember.get(window, modelType);
17159     } else {
17160       return modelType;
17161     }
17162   }).cacheable(),
17163
17164   /**
17165     @private
17166
17167     Get the model class for the state. The heuristic is:
17168
17169     * The state must have a single dynamic segment
17170     * The dynamic segment must end in `_id`
17171     * A dynamic segment like `blog_post_id` is converted into `BlogPost`
17172     * The name is then looked up on the passed in namespace
17173
17174     The process of initializing an application with a router will
17175     pass the application's namespace into the router, which will be
17176     used here.
17177
17178     @method modelClassFor
17179     @param namespace {Ember.Namespace}
17180   */
17181   modelClassFor: function(namespace) {
17182     var modelClass, routeMatcher, identifiers, match, className;
17183
17184     // if an explicit modelType was specified, use that
17185     if (modelClass = get(this, 'modelClass')) { return modelClass; }
17186
17187     // if the router has no lookup namespace, we won't be able to guess
17188     // the modelType
17189     if (!namespace) { return; }
17190
17191     // make sure this state is actually a routable state
17192     routeMatcher = get(this, 'routeMatcher');
17193     if (!routeMatcher) { return; }
17194
17195     // only guess modelType for states with a single dynamic segment
17196     // (no more, no fewer)
17197     identifiers = routeMatcher.identifiers;
17198     if (identifiers.length !== 2) { return; }
17199
17200     // extract the `_id` from the end of the dynamic segment; if the
17201     // dynamic segment does not end in `_id`, we can't guess the
17202     // modelType
17203     match = identifiers[1].match(/^(.*)_id$/);
17204     if (!match) { return; }
17205
17206     // convert the underscored type into a class form and look it up
17207     // on the router's namespace
17208     className = Ember.String.classify(match[1]);
17209     return get(namespace, className);
17210   },
17211
17212   /**
17213     The default method that takes a `params` object and converts
17214     it into an object.
17215
17216     By default, a params hash that looks like `{ post_id: 1 }`
17217     will be looked up as `namespace.Post.find(1)`. This is
17218     designed to work seamlessly with Ember Data, but will work
17219     fine with any class that has a `find` method.
17220
17221     @method deserialize
17222     @param manager {Ember.StateManager}
17223     @param params {Hash}
17224   */
17225   deserialize: function(manager, params) {
17226     var modelClass, routeMatcher, param;
17227
17228     if (modelClass = this.modelClassFor(get(manager, 'namespace'))) {
17229       Ember.assert("Expected "+modelClass.toString()+" to implement `find` for use in '"+this.get('path')+"' `deserialize`. Please implement the `find` method or overwrite `deserialize`.", modelClass.find);
17230       return modelClass.find(params[paramForClass(modelClass)]);
17231     }
17232
17233     return params;
17234   },
17235
17236   /**
17237     The default method that takes an object and converts it into
17238     a params hash.
17239
17240     By default, if there is a single dynamic segment named
17241     `blog_post_id` and the object is a `BlogPost` with an
17242     `id` of `12`, the serialize method will produce:
17243
17244         { blog_post_id: 12 }
17245
17246     @method serialize
17247     @param manager {Ember.StateManager}
17248     @param context
17249   */
17250   serialize: function(manager, context) {
17251     var modelClass, routeMatcher, namespace, param, id;
17252
17253     if (Ember.empty(context)) { return ''; }
17254
17255     if (modelClass = this.modelClassFor(get(manager, 'namespace'))) {
17256       param = paramForClass(modelClass);
17257       id = get(context, 'id');
17258       context = {};
17259       context[param] = id;
17260     }
17261
17262     return context;
17263   },
17264
17265   /**
17266     @private
17267     @method resolvePath
17268     @param manager {Ember.StateManager}
17269     @param path {String}
17270   */
17271   resolvePath: function(manager, path) {
17272     if (get(this, 'isLeafRoute')) { return Ember.A(); }
17273
17274     var childStates = get(this, 'childStates'), match;
17275
17276     childStates = Ember.A(childStates.filterProperty('isRoutable'));
17277
17278     childStates = childStates.sort(function(a, b) {
17279       var aDynamicSegments = get(a, 'routeMatcher.identifiers.length'),
17280           bDynamicSegments = get(b, 'routeMatcher.identifiers.length'),
17281           aRoute = get(a, 'route'),
17282           bRoute = get(b, 'route');
17283
17284       if (aRoute.indexOf(bRoute) === 0) {
17285         return -1;
17286       } else if (bRoute.indexOf(aRoute) === 0) {
17287         return 1;
17288       }
17289
17290       if (aDynamicSegments !== bDynamicSegments) {
17291         return aDynamicSegments - bDynamicSegments;
17292       }
17293
17294       return get(b, 'route.length') - get(a, 'route.length');
17295     });
17296
17297     var state = childStates.find(function(state) {
17298       var matcher = get(state, 'routeMatcher');
17299       if (match = matcher.match(path)) { return true; }
17300     });
17301
17302     Ember.assert("Could not find state for path " + path, !!state);
17303
17304     var resolvedState = Ember._ResolvedState.create({
17305       manager: manager,
17306       state: state,
17307       match: match
17308     });
17309
17310     var states = state.resolvePath(manager, match.remaining);
17311
17312     return Ember.A([resolvedState]).pushObjects(states);
17313   },
17314
17315   /**
17316     @private
17317
17318     Once `unroute` has finished unwinding, `routePath` will be called
17319     with the remainder of the route.
17320
17321     For example, if you were in the /posts/1/comments state, and you
17322     moved into the /posts/2/comments state, `routePath` will be called
17323     on the state whose path is `/posts` with the path `/2/comments`.
17324
17325     @method routePath
17326     @param manager {Ember.StateManager}
17327     @param path {String}
17328   */
17329   routePath: function(manager, path) {
17330     if (get(this, 'isLeafRoute')) { return; }
17331
17332     var resolvedStates = this.resolvePath(manager, path),
17333         hasPromises = resolvedStates.some(function(s) { return get(s, 'hasPromise'); });
17334
17335     function runTransition() {
17336       resolvedStates.forEach(function(rs) { rs.transition(); });
17337     }
17338
17339     if (hasPromises) {
17340       manager.transitionTo('loading');
17341
17342       Ember.assert('Loading state should be the child of a route', Ember.Routable.detect(get(manager, 'currentState.parentState')));
17343       Ember.assert('Loading state should not be a route', !Ember.Routable.detect(get(manager, 'currentState')));
17344
17345       manager.handleStatePromises(resolvedStates, runTransition);
17346     } else {
17347       runTransition();
17348     }
17349   },
17350
17351   /**
17352     @private
17353
17354     When you move to a new route by pressing the back
17355     or forward button, this method is called first.
17356
17357     Its job is to move the state manager into a parent
17358     state of the state it will eventually move into.
17359
17360     @method unroutePath
17361     @param router {Ember.Router}
17362     @param path {String}
17363   */
17364   unroutePath: function(router, path) {
17365     var parentState = get(this, 'parentState');
17366
17367     // If we're at the root state, we're done
17368     if (parentState === router) {
17369       return;
17370     }
17371
17372     path = path.replace(/^(?=[^\/])/, "/");
17373     var absolutePath = this.absoluteRoute(router);
17374
17375     var route = get(this, 'route');
17376
17377     // If the current path is empty, move up one state,
17378     // because the index ('/') state must be a leaf node.
17379     if (route !== '/') {
17380       // If the current path is a prefix of the path we're trying
17381       // to go to, we're done.
17382       var index = path.indexOf(absolutePath),
17383           next = path.charAt(absolutePath.length);
17384
17385       if (index === 0 && (next === "/" || next === "")) {
17386         return;
17387       }
17388     }
17389
17390     // Transition to the parent and call unroute again.
17391     router.enterState({
17392       exitStates: [this],
17393       enterStates: [],
17394       finalState: parentState
17395     });
17396
17397     router.send('unroutePath', path);
17398   },
17399
17400   parentTemplate: Ember.computed(function() {
17401     var state = this, parentState, template;
17402
17403     while (state = get(state, 'parentState')) {
17404       if (template = get(state, 'template')) {
17405         return template;
17406       }
17407     }
17408
17409     return 'application';
17410   }).cacheable(),
17411
17412   _template: Ember.computed(function(key, value) {
17413     if (arguments.length > 1) { return value; }
17414
17415     if (value = get(this, 'template')) {
17416       return value;
17417     }
17418
17419     // If no template was explicitly supplied convert
17420     // the class name into a template name. For example,
17421     // App.PostRoute will return `post`.
17422     var className = this.constructor.toString(), baseName;
17423     if (/^[^\[].*Route$/.test(className)) {
17424       baseName = className.match(/([^\.]+\.)*([^\.]+)/)[2];
17425       baseName = baseName.replace(/Route$/, '');
17426       return baseName.charAt(0).toLowerCase() + baseName.substr(1);
17427     }
17428   }).cacheable(),
17429
17430   render: function(options) {
17431     options = options || {};
17432
17433     var template = options.template || get(this, '_template'),
17434         parentTemplate = options.into || get(this, 'parentTemplate'),
17435         controller = get(this.router, parentTemplate + "Controller");
17436
17437     var viewName = Ember.String.classify(template) + "View",
17438         viewClass = get(get(this.router, 'namespace'), viewName);
17439
17440     viewClass = (viewClass || Ember.View).extend({
17441       templateName: template
17442     });
17443
17444     controller.set('view', viewClass.create());
17445   },
17446
17447   /**
17448     The `connectOutlets` event will be triggered once a
17449     state has been entered. It will be called with the
17450     route's context.
17451
17452     @event connectOutlets
17453     @param router {Ember.Router}
17454     @param [context*]
17455   */
17456   connectOutlets: Ember.K,
17457
17458   /**
17459    The `navigateAway` event will be triggered when the
17460    URL changes due to the back/forward button
17461
17462    @event navigateAway
17463   */
17464   navigateAway: Ember.K
17465 });
17466
17467 })();
17468
17469
17470
17471 (function() {
17472 /**
17473 @module ember
17474 @submodule ember-routing
17475 */
17476
17477 /**
17478   @class Route
17479   @namespace Ember
17480   @extends Ember.State
17481   @uses Ember.Routable
17482 */
17483 Ember.Route = Ember.State.extend(Ember.Routable);
17484
17485 })();
17486
17487
17488
17489 (function() {
17490 var escapeForRegex = function(text) {
17491   return text.replace(/[\-\[\]{}()*+?.,\\\^\$|#\s]/g, "\\$&");
17492 };
17493
17494 /**
17495   @class _RouteMatcher
17496   @namespace Ember
17497   @private
17498   @extends Ember.Object
17499 */
17500 Ember._RouteMatcher = Ember.Object.extend({
17501   state: null,
17502
17503   init: function() {
17504     var route = this.route,
17505         identifiers = [],
17506         count = 1,
17507         escaped;
17508
17509     // Strip off leading slash if present
17510     if (route.charAt(0) === '/') {
17511       route = this.route = route.substr(1);
17512     }
17513
17514     escaped = escapeForRegex(route);
17515
17516     var regex = escaped.replace(/:([a-z_]+)(?=$|\/)/gi, function(match, id) {
17517       identifiers[count++] = id;
17518       return "([^/]+)";
17519     });
17520
17521     this.identifiers = identifiers;
17522     this.regex = new RegExp("^/?" + regex);
17523   },
17524
17525   match: function(path) {
17526     var match = path.match(this.regex);
17527
17528     if (match) {
17529       var identifiers = this.identifiers,
17530           hash = {};
17531
17532       for (var i=1, l=identifiers.length; i<l; i++) {
17533         hash[identifiers[i]] = match[i];
17534       }
17535
17536       return {
17537         remaining: path.substr(match[0].length),
17538         hash: identifiers.length > 0 ? hash : null
17539       };
17540     }
17541   },
17542
17543   generate: function(hash) {
17544     var identifiers = this.identifiers, route = this.route, id;
17545     for (var i=1, l=identifiers.length; i<l; i++) {
17546       id = identifiers[i];
17547       route = route.replace(new RegExp(":" + id), hash[id]);
17548     }
17549     return route;
17550   }
17551 });
17552
17553 })();
17554
17555
17556
17557 (function() {
17558 /**
17559 @module ember
17560 @submodule ember-routing
17561 */
17562
17563 var get = Ember.get, set = Ember.set;
17564
17565 /*
17566   This file implements the `location` API used by Ember's router.
17567
17568   That API is:
17569
17570   getURL: returns the current URL
17571   setURL(path): sets the current URL
17572   onUpdateURL(callback): triggers the callback when the URL changes
17573   formatURL(url): formats `url` to be placed into `href` attribute
17574
17575   Calling setURL will not trigger onUpdateURL callbacks.
17576
17577   TODO: This should perhaps be moved so that it's visible in the doc output.
17578 */
17579
17580 /**
17581   Ember.Location returns an instance of the correct implementation of
17582   the `location` API.
17583
17584   You can pass it a `implementation` ('hash', 'history', 'none') to force a
17585   particular implementation.
17586
17587   @class Location
17588   @namespace Ember
17589   @static
17590 */
17591 Ember.Location = {
17592   create: function(options) {
17593     var implementation = options && options.implementation;
17594     Ember.assert("Ember.Location.create: you must specify a 'implementation' option", !!implementation);
17595
17596     var implementationClass = this.implementations[implementation];
17597     Ember.assert("Ember.Location.create: " + implementation + " is not a valid implementation", !!implementationClass);
17598
17599     return implementationClass.create.apply(implementationClass, arguments);
17600   },
17601
17602   registerImplementation: function(name, implementation) {
17603     this.implementations[name] = implementation;
17604   },
17605
17606   implementations: {}
17607 };
17608
17609 })();
17610
17611
17612
17613 (function() {
17614 /**
17615 @module ember
17616 @submodule ember-routing
17617 */
17618
17619 var get = Ember.get, set = Ember.set;
17620
17621 /**
17622   Ember.NoneLocation does not interact with the browser. It is useful for
17623   testing, or when you need to manage state with your Router, but temporarily
17624   don't want it to muck with the URL (for example when you embed your
17625   application in a larger page).
17626
17627   @class NoneLocation
17628   @namespace Ember
17629   @extends Ember.Object
17630 */
17631 Ember.NoneLocation = Ember.Object.extend({
17632   path: '',
17633
17634   getURL: function() {
17635     return get(this, 'path');
17636   },
17637
17638   setURL: function(path) {
17639     set(this, 'path', path);
17640   },
17641
17642   onUpdateURL: function(callback) {
17643     // We are not wired up to the browser, so we'll never trigger the callback.
17644   },
17645
17646   formatURL: function(url) {
17647     // The return value is not overly meaningful, but we do not want to throw
17648     // errors when test code renders templates containing {{action href=true}}
17649     // helpers.
17650     return url;
17651   }
17652 });
17653
17654 Ember.Location.registerImplementation('none', Ember.NoneLocation);
17655
17656 })();
17657
17658
17659
17660 (function() {
17661 /**
17662 @module ember
17663 @submodule ember-routing
17664 */
17665
17666 var get = Ember.get, set = Ember.set;
17667
17668 /**
17669   Ember.HashLocation implements the location API using the browser's
17670   hash. At present, it relies on a hashchange event existing in the
17671   browser.
17672
17673   @class HashLocation
17674   @namespace Ember
17675   @extends Ember.Object
17676 */
17677 Ember.HashLocation = Ember.Object.extend({
17678
17679   init: function() {
17680     set(this, 'location', get(this, 'location') || window.location);
17681   },
17682
17683   /**
17684     @private
17685
17686     Returns the current `location.hash`, minus the '#' at the front.
17687
17688     @method getURL
17689   */
17690   getURL: function() {
17691     return get(this, 'location').hash.substr(1);
17692   },
17693
17694   /**
17695     @private
17696
17697     Set the `location.hash` and remembers what was set. This prevents
17698     `onUpdateURL` callbacks from triggering when the hash was set by
17699     `HashLocation`.
17700
17701     @method setURL
17702     @param path {String}
17703   */
17704   setURL: function(path) {
17705     get(this, 'location').hash = path;
17706     set(this, 'lastSetURL', path);
17707   },
17708
17709   /**
17710     @private
17711
17712     Register a callback to be invoked when the hash changes. These
17713     callbacks will execute when the user presses the back or forward
17714     button, but not after `setURL` is invoked.
17715
17716     @method onUpdateURL
17717     @param callback {Function}
17718   */
17719   onUpdateURL: function(callback) {
17720     var self = this;
17721     var guid = Ember.guidFor(this);
17722
17723     Ember.$(window).bind('hashchange.ember-location-'+guid, function() {
17724       var path = location.hash.substr(1);
17725       if (get(self, 'lastSetURL') === path) { return; }
17726
17727       set(self, 'lastSetURL', null);
17728
17729       callback(location.hash.substr(1));
17730     });
17731   },
17732
17733   /**
17734     @private
17735
17736     Given a URL, formats it to be placed into the page as part
17737     of an element's `href` attribute.
17738
17739     This is used, for example, when using the {{action}} helper
17740     to generate a URL based on an event.
17741
17742     @method formatURL
17743     @param url {String}
17744   */
17745   formatURL: function(url) {
17746     return '#'+url;
17747   },
17748
17749   willDestroy: function() {
17750     var guid = Ember.guidFor(this);
17751
17752     Ember.$(window).unbind('hashchange.ember-location-'+guid);
17753   }
17754 });
17755
17756 Ember.Location.registerImplementation('hash', Ember.HashLocation);
17757
17758 })();
17759
17760
17761
17762 (function() {
17763 /**
17764 @module ember
17765 @submodule ember-routing
17766 */
17767
17768 var get = Ember.get, set = Ember.set;
17769
17770 /**
17771   Ember.HistoryLocation implements the location API using the browser's
17772   history.pushState API.
17773
17774   @class HistoryLocation
17775   @namespace Ember
17776   @extends Ember.Object
17777 */
17778 Ember.HistoryLocation = Ember.Object.extend({
17779
17780   init: function() {
17781     set(this, 'location', get(this, 'location') || window.location);
17782     set(this, '_initialURL', get(this, 'location').pathname);
17783   },
17784
17785   /**
17786     Will be pre-pended to path upon state change
17787
17788     @property rootURL
17789     @default '/'
17790   */
17791   rootURL: '/',
17792
17793   /**
17794     @private
17795
17796     Used to give history a starting reference
17797
17798     @property _initialURL
17799     @default null
17800   */
17801   _initialURL: null,
17802
17803   /**
17804     @private
17805
17806     Returns the current `location.pathname`.
17807
17808     @method getURL
17809   */
17810   getURL: function() {
17811     return get(this, 'location').pathname;
17812   },
17813
17814   /**
17815     @private
17816
17817     Uses `history.pushState` to update the url without a page reload.
17818
17819     @method setURL
17820     @param path {String}
17821   */
17822   setURL: function(path) {
17823     var state = window.history.state,
17824         initialURL = get(this, '_initialURL');
17825
17826     path = this.formatURL(path);
17827
17828     if ((initialURL !== path && !state) || (state && state.path !== path)) {
17829       window.history.pushState({ path: path }, null, path);
17830     }
17831   },
17832
17833   /**
17834     @private
17835
17836     Register a callback to be invoked whenever the browser
17837     history changes, including using forward and back buttons.
17838
17839     @method onUpdateURL
17840     @param callback {Function}
17841   */
17842   onUpdateURL: function(callback) {
17843     var guid = Ember.guidFor(this);
17844
17845     Ember.$(window).bind('popstate.ember-location-'+guid, function(e) {
17846       callback(location.pathname);
17847     });
17848   },
17849
17850   /**
17851     @private
17852
17853     Used when using `{{action}}` helper.  The url is always appended to the rootURL.
17854
17855     @method formatURL
17856     @param url {String}
17857   */
17858   formatURL: function(url) {
17859     var rootURL = get(this, 'rootURL');
17860
17861     if (url !== '') {
17862       rootURL = rootURL.replace(/\/$/, '');
17863     }
17864
17865     return rootURL + url;
17866   },
17867
17868   willDestroy: function() {
17869     var guid = Ember.guidFor(this);
17870
17871     Ember.$(window).unbind('popstate.ember-location-'+guid);
17872   }
17873 });
17874
17875 Ember.Location.registerImplementation('history', Ember.HistoryLocation);
17876
17877 })();
17878
17879
17880
17881 (function() {
17882
17883 })();
17884
17885
17886
17887 (function() {
17888 /**
17889 @module ember
17890 @submodule ember-routing
17891 */
17892
17893 var get = Ember.get, set = Ember.set;
17894
17895 var merge = function(original, hash) {
17896   for (var prop in hash) {
17897     if (!hash.hasOwnProperty(prop)) { continue; }
17898     if (original.hasOwnProperty(prop)) { continue; }
17899
17900     original[prop] = hash[prop];
17901   }
17902 };
17903
17904 /**
17905   `Ember.Router` is the subclass of `Ember.StateManager` responsible for providing URL-based
17906   application state detection. The `Ember.Router` instance of an application detects the browser URL
17907   at application load time and attempts to match it to a specific application state. Additionally
17908   the router will update the URL to reflect an application's state changes over time.
17909
17910   ## Adding a Router Instance to Your Application
17911   An instance of Ember.Router can be associated with an instance of Ember.Application in one of two ways:
17912
17913   You can provide a subclass of Ember.Router as the `Router` property of your application. An instance
17914   of this Router class will be instantiated and route detection will be enabled when the application's
17915   `initialize` method is called. The Router instance will be available as the `router` property
17916   of the application:
17917
17918       App = Ember.Application.create({
17919         Router: Ember.Router.extend({ ... })
17920       });
17921
17922       App.initialize();
17923       App.get('router') // an instance of App.Router
17924
17925   If you want to define a Router instance elsewhere, you can pass the instance to the application's
17926   `initialize` method:
17927
17928       App = Ember.Application.create();
17929       aRouter = Ember.Router.create({ ... });
17930
17931       App.initialize(aRouter);
17932       App.get('router') // aRouter
17933
17934   ## Adding Routes to a Router
17935   The `initialState` property of Ember.Router instances is named `root`. The state stored in this
17936   property must be a subclass of Ember.Route. The `root` route acts as the container for the
17937   set of routable states but is not routable itself. It should have states that are also subclasses
17938   of Ember.Route which each have a `route` property describing the URL pattern you would like to detect.
17939
17940       App = Ember.Application.create({
17941         Router: Ember.Router.extend({
17942           root: Ember.Route.extend({
17943             index: Ember.Route.extend({
17944               route: '/'
17945             }),
17946             ... additional Ember.Routes ...
17947           })
17948         })
17949       });
17950       App.initialize();
17951
17952
17953   When an application loads, Ember will parse the URL and attempt to find an Ember.Route within
17954   the application's states that matches. (The example URL-matching below will use the default
17955   'hash syntax' provided by `Ember.HashLocation`.)
17956
17957   In the following route structure:
17958
17959       App = Ember.Application.create({
17960         Router: Ember.Router.extend({
17961           root: Ember.Route.extend({
17962             aRoute: Ember.Route.extend({
17963               route: '/'
17964             }),
17965             bRoute: Ember.Route.extend({
17966               route: '/alphabeta'
17967             })
17968           })
17969         })
17970       });
17971       App.initialize();
17972
17973   Loading the page at the URL '#/' will detect the route property of 'root.aRoute' ('/') and
17974   transition the router first to the state named 'root' and then to the substate 'aRoute'.
17975
17976   Respectively, loading the page at the URL '#/alphabeta' would detect the route property of
17977   'root.bRoute' ('/alphabeta') and transition the router first to the state named 'root' and
17978   then to the substate 'bRoute'.
17979
17980   ## Adding Nested Routes to a Router
17981   Routes can contain nested subroutes each with their own `route` property describing the nested
17982   portion of the URL they would like to detect and handle. Router, like all instances of StateManager,
17983   cannot call `transitonTo` with an intermediary state. To avoid transitioning the Router into an
17984   intermediary state when detecting URLs, a Route with nested routes must define both a base `route`
17985   property for itself and a child Route with a `route` property of `'/'` which will be transitioned
17986   to when the base route is detected in the URL:
17987
17988   Given the following application code:
17989
17990       App = Ember.Application.create({
17991         Router: Ember.Router.extend({
17992           root: Ember.Route.extend({
17993             aRoute: Ember.Route.extend({
17994               route: '/theBaseRouteForThisSet',
17995
17996               indexSubRoute: Ember.Route.extend({
17997                 route: '/'
17998               }),
17999
18000               subRouteOne: Ember.Route.extend({
18001                 route: '/subroute1'
18002               }),
18003
18004               subRouteTwo: Ember.Route.extend({
18005                 route: '/subRoute2'
18006               })
18007
18008             })
18009           })
18010         })
18011       });
18012       App.initialize();
18013
18014   When the application is loaded at '/theBaseRouteForThisSet' the Router will transition to the route
18015   at path 'root.aRoute' and then transition to state 'indexSubRoute'.
18016
18017   When the application is loaded at '/theBaseRouteForThisSet/subRoute1' the Router will transition to
18018   the route at path 'root.aRoute' and then transition to state 'subRouteOne'.
18019
18020   ## Route Transition Events
18021   Transitioning between Ember.Route instances (including the transition into the detected
18022   route when loading the application)  triggers the same transition events as state transitions for
18023   base `Ember.State`s. However, the default `setup` transition event is named `connectOutlets` on
18024   Ember.Router instances (see 'Changing View Hierarchy in Response To State Change').
18025
18026   The following route structure when loaded with the URL "#/"
18027
18028       App = Ember.Application.create({
18029         Router: Ember.Router.extend({
18030           root: Ember.Route.extend({
18031             aRoute: Ember.Route.extend({
18032               route: '/',
18033               enter: function(router) {
18034                 console.log("entering root.aRoute from", router.get('currentState.name'));
18035               },
18036               connectOutlets: function(router) {
18037                 console.log("entered root.aRoute, fully transitioned to", router.get('currentState.path'));
18038               }
18039             })
18040           })
18041         })
18042       });
18043       App.initialize();
18044
18045   Will result in console output of:
18046
18047       'entering root.aRoute from root'
18048       'entered root.aRoute, fully transitioned to root.aRoute '
18049
18050   Ember.Route has two additional callbacks for handling URL serialization and deserialization. See
18051   'Serializing/Deserializing URLs'
18052
18053   ## Routes With Dynamic Segments
18054   An Ember.Route's `route` property can reference dynamic sections of the URL by prefacing a URL segment
18055   with the ':' character.  The values of these dynamic segments will be passed as a hash to the
18056   `deserialize` method of the matching Route (see 'Serializing/Deserializing URLs').
18057
18058   ## Serializing/Deserializing URLs
18059   Ember.Route has two callbacks for associating a particular object context with a URL: `serialize`
18060   for converting an object into a parameters hash to fill dynamic segments of a URL and `deserialize`
18061   for converting a hash of dynamic segments from the URL into the appropriate object.
18062
18063   ### Deserializing A URL's Dynamic Segments
18064   When an application is first loaded or the URL is changed manually (e.g. through the browser's
18065   back button) the `deserialize` method of the URL's matching Ember.Route will be called with
18066   the application's router as its first argument and a hash of the URL's dynamic segments and values
18067   as its second argument.
18068
18069   The following route structure when loaded with the URL "#/fixed/thefirstvalue/anotherFixed/thesecondvalue":
18070
18071       App = Ember.Application.create({
18072         Router: Ember.Router.extend({
18073           root: Ember.Route.extend({
18074             aRoute: Ember.Route.extend({
18075               route: '/fixed/:dynamicSectionA/anotherFixed/:dynamicSectionB',
18076               deserialize: function(router, params) {}
18077             })
18078           })
18079         })
18080       });
18081       App.initialize();
18082
18083   Will call the 'deserialize' method of the Route instance at the path 'root.aRoute' with the
18084   following hash as its second argument:
18085
18086       {
18087         dynamicSectionA: 'thefirstvalue',
18088         dynamicSectionB: 'thesecondvalue'
18089       }
18090
18091   Within `deserialize` you should use this information to retrieve or create an appropriate context
18092   object for the given URL (e.g. by loading from a remote API or accessing the browser's
18093   `localStorage`). This object must be the `return` value of `deserialize` and will be
18094   passed to the Route's `connectOutlets` and `serialize` methods.
18095
18096   When an application's state is changed from within the application itself, the context provided for
18097   the transition will be passed and `deserialize` is not called (see 'Transitions Between States').
18098
18099   ### Serializing An Object For URLs with Dynamic Segments
18100   When transitioning into a Route whose `route` property contains dynamic segments the Route's
18101   `serialize` method is called with the Route's router as the first argument and the Route's
18102   context as the second argument.  The return value of `serialize` will be used to populate the
18103   dynamic segments and should be an object with keys that match the names of the dynamic sections.
18104
18105   Given the following route structure:
18106
18107       App = Ember.Application.create({
18108         Router: Ember.Router.extend({
18109           root: Ember.Route.extend({
18110             aRoute: Ember.Route.extend({
18111               route: '/'
18112             }),
18113             bRoute: Ember.Route.extend({
18114               route: '/staticSection/:someDynamicSegment',
18115               serialize: function(router, context) {
18116                 return {
18117                   someDynamicSegment: context.get('name')
18118                 }
18119               }
18120             })
18121           })
18122         })
18123       });
18124       App.initialize();
18125
18126
18127   Transitioning to "root.bRoute" with a context of `Object.create({name: 'Yehuda'})` will call
18128   the Route's `serialize` method with the context as its second argument and update the URL to
18129   '#/staticSection/Yehuda'.
18130
18131   ## Transitions Between States
18132   Once a routed application has initialized its state based on the entry URL, subsequent transitions to other
18133   states will update the URL if the entered Route has a `route` property. Given the following route structure
18134   loaded at the URL '#/':
18135
18136       App = Ember.Application.create({
18137         Router: Ember.Router.extend({
18138           root: Ember.Route.extend({
18139             aRoute: Ember.Route.extend({
18140               route: '/',
18141               moveElsewhere: Ember.Route.transitionTo('bRoute')
18142             }),
18143             bRoute: Ember.Route.extend({
18144               route: '/someOtherLocation'
18145             })
18146           })
18147         })
18148       });
18149       App.initialize();
18150
18151   And application code:
18152
18153       App.get('router').send('moveElsewhere');
18154
18155   Will transition the application's state to 'root.bRoute' and trigger an update of the URL to
18156   '#/someOtherLocation'.
18157
18158   For URL patterns with dynamic segments a context can be supplied as the second argument to `send`.
18159   The router will match dynamic segments names to keys on this object and fill in the URL with the
18160   supplied values. Given the following state structure loaded at the URL '#/':
18161
18162       App = Ember.Application.create({
18163         Router: Ember.Router.extend({
18164           root: Ember.Route.extend({
18165             aRoute: Ember.Route.extend({
18166               route: '/',
18167               moveElsewhere: Ember.Route.transitionTo('bRoute')
18168             }),
18169             bRoute: Ember.Route.extend({
18170               route: '/a/route/:dynamicSection/:anotherDynamicSection',
18171               connectOutlets: function(router, context) {},
18172             })
18173           })
18174         })
18175       });
18176       App.initialize();
18177
18178   And application code:
18179
18180       App.get('router').send('moveElsewhere', {
18181         dynamicSection: '42',
18182         anotherDynamicSection: 'Life'
18183       });
18184
18185   Will transition the application's state to 'root.bRoute' and trigger an update of the URL to
18186   '#/a/route/42/Life'.
18187
18188   The context argument will also be passed as the second argument to the `serialize` method call.
18189
18190   ## Injection of Controller Singletons
18191   During application initialization Ember will detect properties of the application ending in 'Controller',
18192   create singleton instances of each class, and assign them as properties on the router.  The property name
18193   will be the UpperCamel name converted to lowerCamel format. These controller classes should be subclasses
18194   of Ember.ObjectController, Ember.ArrayController, Ember.Controller, or a custom Ember.Object that includes the
18195   Ember.ControllerMixin mixin.
18196
18197   ``` javascript
18198   App = Ember.Application.create({
18199     FooController: Ember.Object.create(Ember.ControllerMixin),
18200     Router: Ember.Router.extend({ ... })
18201   });
18202
18203   App.get('router.fooController'); // instance of App.FooController
18204   ```
18205
18206   The controller singletons will have their `namespace` property set to the application and their `target`
18207   property set to the application's router singleton for easy integration with Ember's user event system.
18208   See 'Changing View Hierarchy in Response To State Change' and 'Responding to User-initiated Events.'
18209
18210   ## Responding to User-initiated Events
18211   Controller instances injected into the router at application initialization have their `target` property
18212   set to the application's router instance. These controllers will also be the default `context` for their
18213   associated views.  Uses of the `{{action}}` helper will automatically target the application's router.
18214
18215   Given the following application entered at the URL '#/':
18216
18217   ``` javascript
18218   App = Ember.Application.create({
18219     Router: Ember.Router.extend({
18220       root: Ember.Route.extend({
18221         aRoute: Ember.Route.extend({
18222           route: '/',
18223           anActionOnTheRouter: function(router, context) {
18224             router.transitionTo('anotherState', context);
18225           }
18226         })
18227         anotherState: Ember.Route.extend({
18228           route: '/differentUrl',
18229           connectOutlets: function(router, context) {
18230
18231           }
18232         })
18233       })
18234     })
18235   });
18236   App.initialize();
18237   ```
18238
18239   The following template:
18240
18241   ``` handlebars
18242   <script type="text/x-handlebars" data-template-name="aView">
18243       <h1><a {{action anActionOnTheRouter}}>{{title}}</a></h1>
18244   </script>
18245   ```
18246
18247   Will delegate `click` events on the rendered `h1` to the application's router instance. In this case the
18248   `anActionOnTheRouter` method of the state at 'root.aRoute' will be called with the view's controller
18249   as the context argument. This context will be passed to the `connectOutlets` as its second argument.
18250
18251   Different `context` can be supplied from within the `{{action}}` helper, allowing specific context passing
18252   between application states:
18253
18254   ``` handlebars
18255   <script type="text/x-handlebars" data-template-name="photos">
18256     {{#each photo in controller}}
18257       <h1><a {{action showPhoto photo}}>{{title}}</a></h1>
18258     {{/each}}
18259   </script>
18260   ```
18261
18262   See `Handlebars.helpers.action` for additional usage examples.
18263
18264
18265   ## Changing View Hierarchy in Response To State Change
18266
18267   Changes in application state that change the URL should be accompanied by associated changes in view
18268   hierarchy.  This can be accomplished by calling 'connectOutlet' on the injected controller singletons from
18269   within the 'connectOutlets' event of an Ember.Route:
18270
18271   ``` javascript
18272   App = Ember.Application.create({
18273     OneController: Ember.ObjectController.extend(),
18274     OneView: Ember.View.extend(),
18275
18276     AnotherController: Ember.ObjectController.extend(),
18277     AnotherView: Ember.View.extend(),
18278
18279     Router: Ember.Router.extend({
18280       root: Ember.Route.extend({
18281         aRoute: Ember.Route.extend({
18282           route: '/',
18283           connectOutlets: function(router, context) {
18284             router.get('oneController').connectOutlet('another');
18285           },
18286         })
18287       })
18288     })
18289   });
18290   App.initialize();
18291   ```
18292
18293
18294   This will detect the '{{outlet}}' portion of `oneController`'s view (an instance of `App.OneView`) and
18295   fill it with a rendered instance of `App.AnotherView` whose `context` will be the single instance of
18296   `App.AnotherController` stored on the router in the `anotherController` property.
18297
18298   For more information about Outlets, see `Ember.Handlebars.helpers.outlet`. For additional information on
18299   the `connectOutlet` method, see `Ember.Controller.connectOutlet`. For more information on
18300   controller injections, see `Ember.Application#initialize()`. For additional information about view context,
18301   see `Ember.View`.
18302
18303   @class Router
18304   @namespace Ember
18305   @extends Ember.StateManager
18306 */
18307 Ember.Router = Ember.StateManager.extend(
18308 /** @scope Ember.Router.prototype */ {
18309
18310   /**
18311     @property initialState
18312     @type String
18313     @default 'root'
18314   */
18315   initialState: 'root',
18316
18317   /**
18318     The `Ember.Location` implementation to be used to manage the application
18319     URL state. The following values are supported:
18320
18321     * 'hash': Uses URL fragment identifiers (like #/blog/1) for routing.
18322     * 'history': Uses the browser's history.pushstate API for routing. Only works in
18323        modern browsers with pushstate support.
18324     * 'none': Does not read or set the browser URL, but still allows for
18325       routing to happen. Useful for testing.
18326
18327     @property location
18328     @type String
18329     @default 'hash'
18330   */
18331   location: 'hash',
18332
18333   /**
18334     This is only used when a history location is used so that applications that
18335     don't live at the root of the domain can append paths to their root.
18336
18337     @property rootURL
18338     @type String
18339     @default '/'
18340   */
18341
18342   rootURL: '/',
18343
18344   transitionTo: function() {
18345     this.abortRoutingPromises();
18346     this._super.apply(this, arguments);
18347   },
18348
18349   route: function(path) {
18350     this.abortRoutingPromises();
18351
18352     set(this, 'isRouting', true);
18353
18354     var routableState;
18355
18356     try {
18357       path = path.replace(get(this, 'rootURL'), '');
18358       path = path.replace(/^(?=[^\/])/, "/");
18359
18360       this.send('navigateAway');
18361       this.send('unroutePath', path);
18362
18363       routableState = get(this, 'currentState');
18364       while (routableState && !routableState.get('isRoutable')) {
18365         routableState = get(routableState, 'parentState');
18366       }
18367       var currentURL = routableState ? routableState.absoluteRoute(this) : '';
18368       var rest = path.substr(currentURL.length);
18369
18370       this.send('routePath', rest);
18371     } finally {
18372       set(this, 'isRouting', false);
18373     }
18374
18375     routableState = get(this, 'currentState');
18376     while (routableState && !routableState.get('isRoutable')) {
18377       routableState = get(routableState, 'parentState');
18378     }
18379
18380     if (routableState) {
18381       routableState.updateRoute(this, get(this, 'location'));
18382     }
18383   },
18384
18385   urlFor: function(path, hash) {
18386     var currentState = get(this, 'currentState') || this,
18387         state = this.findStateByPath(currentState, path);
18388
18389     Ember.assert(Ember.String.fmt("Could not find route with path '%@'", [path]), !!state);
18390     Ember.assert("To get a URL for a state, it must have a `route` property.", !!get(state, 'routeMatcher'));
18391
18392     var location = get(this, 'location'),
18393         absoluteRoute = state.absoluteRoute(this, hash);
18394
18395     return location.formatURL(absoluteRoute);
18396   },
18397
18398   urlForEvent: function(eventName) {
18399     var contexts = Array.prototype.slice.call(arguments, 1);
18400     var currentState = get(this, 'currentState');
18401     var targetStateName = currentState.lookupEventTransition(eventName);
18402
18403     Ember.assert(Ember.String.fmt("You must specify a target state for event '%@' in order to link to it in the current state '%@'.", [eventName, get(currentState, 'path')]), !!targetStateName);
18404
18405     var targetState = this.findStateByPath(currentState, targetStateName);
18406
18407     Ember.assert("Your target state name " + targetStateName + " for event " + eventName + " did not resolve to a state", !!targetState);
18408
18409     var hash = this.serializeRecursively(targetState, contexts, {});
18410
18411     return this.urlFor(targetStateName, hash);
18412   },
18413
18414   serializeRecursively: function(state, contexts, hash) {
18415     var parentState,
18416         context = get(state, 'hasContext') ? contexts.pop() : null;
18417     merge(hash, state.serialize(this, context));
18418     parentState = state.get("parentState");
18419     if (parentState && parentState instanceof Ember.Route) {
18420       return this.serializeRecursively(parentState, contexts, hash);
18421     } else {
18422       return hash;
18423     }
18424   },
18425
18426   abortRoutingPromises: function() {
18427     if (this._routingPromises) {
18428       this._routingPromises.abort();
18429       this._routingPromises = null;
18430     }
18431   },
18432
18433   handleStatePromises: function(states, complete) {
18434     this.abortRoutingPromises();
18435
18436     this.set('isLocked', true);
18437
18438     var manager = this;
18439
18440     this._routingPromises = Ember._PromiseChain.create({
18441       promises: states.slice(),
18442
18443       successCallback: function() {
18444         manager.set('isLocked', false);
18445         complete();
18446       },
18447
18448       failureCallback: function() {
18449         throw "Unable to load object";
18450       },
18451
18452       promiseSuccessCallback: function(item, args) {
18453         set(item, 'object', args[0]);
18454       },
18455
18456       abortCallback: function() {
18457         manager.set('isLocked', false);
18458       }
18459     }).start();
18460   },
18461
18462   init: function() {
18463     this._super();
18464
18465     var location = get(this, 'location'),
18466         rootURL = get(this, 'rootURL');
18467
18468     if ('string' === typeof location) {
18469       set(this, 'location', Ember.Location.create({
18470         implementation: location,
18471         rootURL: rootURL
18472       }));
18473     }
18474
18475     this.assignRouter(this, this);
18476   },
18477
18478   assignRouter: function(state, router) {
18479     state.router = router;
18480
18481     var childStates = state.states;
18482
18483     if (childStates) {
18484       for (var stateName in childStates) {
18485         if (!childStates.hasOwnProperty(stateName)) { continue; }
18486         this.assignRouter(childStates[stateName], router);
18487       }
18488     }
18489   },
18490
18491   willDestroy: function() {
18492     get(this, 'location').destroy();
18493   }
18494 });
18495
18496 })();
18497
18498
18499
18500 (function() {
18501 /**
18502 Ember Routing
18503
18504 @module ember
18505 @submodule ember-routing
18506 @requires ember-states
18507 */
18508
18509 })();
18510
18511 (function() {
18512 // ==========================================================================
18513 // Project:   metamorph
18514 // Copyright: Â©2011 My Company Inc. All rights reserved.
18515 // ==========================================================================
18516
18517 (function(window) {
18518
18519   var K = function(){},
18520       guid = 0,
18521       document = window.document,
18522
18523       // Feature-detect the W3C range API, the extended check is for IE9 which only partially supports ranges
18524       supportsRange = ('createRange' in document) && (typeof Range !== 'undefined') && Range.prototype.createContextualFragment,
18525
18526       // Internet Explorer prior to 9 does not allow setting innerHTML if the first element
18527       // is a "zero-scope" element. This problem can be worked around by making
18528       // the first node an invisible text node. We, like Modernizr, use &shy;
18529       needsShy = (function(){
18530         var testEl = document.createElement('div');
18531         testEl.innerHTML = "<div></div>";
18532         testEl.firstChild.innerHTML = "<script></script>";
18533         return testEl.firstChild.innerHTML === '';
18534       })();
18535
18536   // Constructor that supports either Metamorph('foo') or new
18537   // Metamorph('foo');
18538   //
18539   // Takes a string of HTML as the argument.
18540
18541   var Metamorph = function(html) {
18542     var self;
18543
18544     if (this instanceof Metamorph) {
18545       self = this;
18546     } else {
18547       self = new K();
18548     }
18549
18550     self.innerHTML = html;
18551     var myGuid = 'metamorph-'+(guid++);
18552     self.start = myGuid + '-start';
18553     self.end = myGuid + '-end';
18554
18555     return self;
18556   };
18557
18558   K.prototype = Metamorph.prototype;
18559
18560   var rangeFor, htmlFunc, removeFunc, outerHTMLFunc, appendToFunc, afterFunc, prependFunc, startTagFunc, endTagFunc;
18561
18562   outerHTMLFunc = function() {
18563     return this.startTag() + this.innerHTML + this.endTag();
18564   };
18565
18566   startTagFunc = function() {
18567     return "<script id='" + this.start + "' type='text/x-placeholder'></script>";
18568   };
18569
18570   endTagFunc = function() {
18571     return "<script id='" + this.end + "' type='text/x-placeholder'></script>";
18572   };
18573
18574   // If we have the W3C range API, this process is relatively straight forward.
18575   if (supportsRange) {
18576
18577     // Get a range for the current morph. Optionally include the starting and
18578     // ending placeholders.
18579     rangeFor = function(morph, outerToo) {
18580       var range = document.createRange();
18581       var before = document.getElementById(morph.start);
18582       var after = document.getElementById(morph.end);
18583
18584       if (outerToo) {
18585         range.setStartBefore(before);
18586         range.setEndAfter(after);
18587       } else {
18588         range.setStartAfter(before);
18589         range.setEndBefore(after);
18590       }
18591
18592       return range;
18593     };
18594
18595     htmlFunc = function(html, outerToo) {
18596       // get a range for the current metamorph object
18597       var range = rangeFor(this, outerToo);
18598
18599       // delete the contents of the range, which will be the
18600       // nodes between the starting and ending placeholder.
18601       range.deleteContents();
18602
18603       // create a new document fragment for the HTML
18604       var fragment = range.createContextualFragment(html);
18605
18606       // insert the fragment into the range
18607       range.insertNode(fragment);
18608     };
18609
18610     removeFunc = function() {
18611       // get a range for the current metamorph object including
18612       // the starting and ending placeholders.
18613       var range = rangeFor(this, true);
18614
18615       // delete the entire range.
18616       range.deleteContents();
18617     };
18618
18619     appendToFunc = function(node) {
18620       var range = document.createRange();
18621       range.setStart(node);
18622       range.collapse(false);
18623       var frag = range.createContextualFragment(this.outerHTML());
18624       node.appendChild(frag);
18625     };
18626
18627     afterFunc = function(html) {
18628       var range = document.createRange();
18629       var after = document.getElementById(this.end);
18630
18631       range.setStartAfter(after);
18632       range.setEndAfter(after);
18633
18634       var fragment = range.createContextualFragment(html);
18635       range.insertNode(fragment);
18636     };
18637
18638     prependFunc = function(html) {
18639       var range = document.createRange();
18640       var start = document.getElementById(this.start);
18641
18642       range.setStartAfter(start);
18643       range.setEndAfter(start);
18644
18645       var fragment = range.createContextualFragment(html);
18646       range.insertNode(fragment);
18647     };
18648
18649   } else {
18650     /**
18651      * This code is mostly taken from jQuery, with one exception. In jQuery's case, we
18652      * have some HTML and we need to figure out how to convert it into some nodes.
18653      *
18654      * In this case, jQuery needs to scan the HTML looking for an opening tag and use
18655      * that as the key for the wrap map. In our case, we know the parent node, and
18656      * can use its type as the key for the wrap map.
18657      **/
18658     var wrapMap = {
18659       select: [ 1, "<select multiple='multiple'>", "</select>" ],
18660       fieldset: [ 1, "<fieldset>", "</fieldset>" ],
18661       table: [ 1, "<table>", "</table>" ],
18662       tbody: [ 2, "<table><tbody>", "</tbody></table>" ],
18663       tr: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
18664       colgroup: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
18665       map: [ 1, "<map>", "</map>" ],
18666       _default: [ 0, "", "" ]
18667     };
18668
18669     /**
18670      * Given a parent node and some HTML, generate a set of nodes. Return the first
18671      * node, which will allow us to traverse the rest using nextSibling.
18672      *
18673      * We need to do this because innerHTML in IE does not really parse the nodes.
18674      **/
18675     var firstNodeFor = function(parentNode, html) {
18676       var arr = wrapMap[parentNode.tagName.toLowerCase()] || wrapMap._default;
18677       var depth = arr[0], start = arr[1], end = arr[2];
18678
18679       if (needsShy) { html = '&shy;'+html; }
18680
18681       var element = document.createElement('div');
18682       element.innerHTML = start + html + end;
18683
18684       for (var i=0; i<=depth; i++) {
18685         element = element.firstChild;
18686       }
18687
18688       // Look for &shy; to remove it.
18689       if (needsShy) {
18690         var shyElement = element;
18691
18692         // Sometimes we get nameless elements with the shy inside
18693         while (shyElement.nodeType === 1 && !shyElement.nodeName) {
18694           shyElement = shyElement.firstChild;
18695         }
18696
18697         // At this point it's the actual unicode character.
18698         if (shyElement.nodeType === 3 && shyElement.nodeValue.charAt(0) === "\u00AD") {
18699           shyElement.nodeValue = shyElement.nodeValue.slice(1);
18700         }
18701       }
18702
18703       return element;
18704     };
18705
18706     /**
18707      * In some cases, Internet Explorer can create an anonymous node in
18708      * the hierarchy with no tagName. You can create this scenario via:
18709      *
18710      *     div = document.createElement("div");
18711      *     div.innerHTML = "<table>&shy<script></script><tr><td>hi</td></tr></table>";
18712      *     div.firstChild.firstChild.tagName //=> ""
18713      *
18714      * If our script markers are inside such a node, we need to find that
18715      * node and use *it* as the marker.
18716      **/
18717     var realNode = function(start) {
18718       while (start.parentNode.tagName === "") {
18719         start = start.parentNode;
18720       }
18721
18722       return start;
18723     };
18724
18725     /**
18726      * When automatically adding a tbody, Internet Explorer inserts the
18727      * tbody immediately before the first <tr>. Other browsers create it
18728      * before the first node, no matter what.
18729      *
18730      * This means the the following code:
18731      *
18732      *     div = document.createElement("div");
18733      *     div.innerHTML = "<table><script id='first'></script><tr><td>hi</td></tr><script id='last'></script></table>
18734      *
18735      * Generates the following DOM in IE:
18736      *
18737      *     + div
18738      *       + table
18739      *         - script id='first'
18740      *         + tbody
18741      *           + tr
18742      *             + td
18743      *               - "hi"
18744      *           - script id='last'
18745      *
18746      * Which means that the two script tags, even though they were
18747      * inserted at the same point in the hierarchy in the original
18748      * HTML, now have different parents.
18749      *
18750      * This code reparents the first script tag by making it the tbody's
18751      * first child.
18752      **/
18753     var fixParentage = function(start, end) {
18754       if (start.parentNode !== end.parentNode) {
18755         end.parentNode.insertBefore(start, end.parentNode.firstChild);
18756       }
18757     };
18758
18759     htmlFunc = function(html, outerToo) {
18760       // get the real starting node. see realNode for details.
18761       var start = realNode(document.getElementById(this.start));
18762       var end = document.getElementById(this.end);
18763       var parentNode = end.parentNode;
18764       var node, nextSibling, last;
18765
18766       // make sure that the start and end nodes share the same
18767       // parent. If not, fix it.
18768       fixParentage(start, end);
18769
18770       // remove all of the nodes after the starting placeholder and
18771       // before the ending placeholder.
18772       node = start.nextSibling;
18773       while (node) {
18774         nextSibling = node.nextSibling;
18775         last = node === end;
18776
18777         // if this is the last node, and we want to remove it as well,
18778         // set the `end` node to the next sibling. This is because
18779         // for the rest of the function, we insert the new nodes
18780         // before the end (note that insertBefore(node, null) is
18781         // the same as appendChild(node)).
18782         //
18783         // if we do not want to remove it, just break.
18784         if (last) {
18785           if (outerToo) { end = node.nextSibling; } else { break; }
18786         }
18787
18788         node.parentNode.removeChild(node);
18789
18790         // if this is the last node and we didn't break before
18791         // (because we wanted to remove the outer nodes), break
18792         // now.
18793         if (last) { break; }
18794
18795         node = nextSibling;
18796       }
18797
18798       // get the first node for the HTML string, even in cases like
18799       // tables and lists where a simple innerHTML on a div would
18800       // swallow some of the content.
18801       node = firstNodeFor(start.parentNode, html);
18802
18803       // copy the nodes for the HTML between the starting and ending
18804       // placeholder.
18805       while (node) {
18806         nextSibling = node.nextSibling;
18807         parentNode.insertBefore(node, end);
18808         node = nextSibling;
18809       }
18810     };
18811
18812     // remove the nodes in the DOM representing this metamorph.
18813     //
18814     // this includes the starting and ending placeholders.
18815     removeFunc = function() {
18816       var start = realNode(document.getElementById(this.start));
18817       var end = document.getElementById(this.end);
18818
18819       this.html('');
18820       start.parentNode.removeChild(start);
18821       end.parentNode.removeChild(end);
18822     };
18823
18824     appendToFunc = function(parentNode) {
18825       var node = firstNodeFor(parentNode, this.outerHTML());
18826
18827       while (node) {
18828         nextSibling = node.nextSibling;
18829         parentNode.appendChild(node);
18830         node = nextSibling;
18831       }
18832     };
18833
18834     afterFunc = function(html) {
18835       // get the real starting node. see realNode for details.
18836       var end = document.getElementById(this.end);
18837       var insertBefore = end.nextSibling;
18838       var parentNode = end.parentNode;
18839       var nextSibling;
18840       var node;
18841
18842       // get the first node for the HTML string, even in cases like
18843       // tables and lists where a simple innerHTML on a div would
18844       // swallow some of the content.
18845       node = firstNodeFor(parentNode, html);
18846
18847       // copy the nodes for the HTML between the starting and ending
18848       // placeholder.
18849       while (node) {
18850         nextSibling = node.nextSibling;
18851         parentNode.insertBefore(node, insertBefore);
18852         node = nextSibling;
18853       }
18854     };
18855
18856     prependFunc = function(html) {
18857       var start = document.getElementById(this.start);
18858       var parentNode = start.parentNode;
18859       var nextSibling;
18860       var node;
18861
18862       node = firstNodeFor(parentNode, html);
18863       var insertBefore = start.nextSibling;
18864
18865       while (node) {
18866         nextSibling = node.nextSibling;
18867         parentNode.insertBefore(node, insertBefore);
18868         node = nextSibling;
18869       }
18870     }
18871   }
18872
18873   Metamorph.prototype.html = function(html) {
18874     this.checkRemoved();
18875     if (html === undefined) { return this.innerHTML; }
18876
18877     htmlFunc.call(this, html);
18878
18879     this.innerHTML = html;
18880   };
18881
18882   Metamorph.prototype.replaceWith = function(html) {
18883     this.checkRemoved();
18884     htmlFunc.call(this, html, true);
18885   };
18886
18887   Metamorph.prototype.remove = removeFunc;
18888   Metamorph.prototype.outerHTML = outerHTMLFunc;
18889   Metamorph.prototype.appendTo = appendToFunc;
18890   Metamorph.prototype.after = afterFunc;
18891   Metamorph.prototype.prepend = prependFunc;
18892   Metamorph.prototype.startTag = startTagFunc;
18893   Metamorph.prototype.endTag = endTagFunc;
18894
18895   Metamorph.prototype.isRemoved = function() {
18896     var before = document.getElementById(this.start);
18897     var after = document.getElementById(this.end);
18898
18899     return !before || !after;
18900   };
18901
18902   Metamorph.prototype.checkRemoved = function() {
18903     if (this.isRemoved()) {
18904       throw new Error("Cannot perform operations on a Metamorph that is not in the DOM.");
18905     }
18906   };
18907
18908   window.Metamorph = Metamorph;
18909 })(this);
18910
18911
18912 })();
18913
18914 (function() {
18915 /*globals Handlebars */
18916 /**
18917 @module ember
18918 @submodule ember-handlebars
18919 */
18920
18921 var objectCreate = Ember.create;
18922
18923
18924 Ember.assert("Ember Handlebars requires Handlebars 1.0.beta.5 or greater", window.Handlebars && window.Handlebars.VERSION.match(/^1\.0\.beta\.[56789]$|^1\.0\.rc\.[123456789]+/));
18925
18926 /**
18927   Prepares the Handlebars templating library for use inside Ember's view
18928   system.
18929
18930   The Ember.Handlebars object is the standard Handlebars library, extended to use
18931   Ember's get() method instead of direct property access, which allows
18932   computed properties to be used inside templates.
18933
18934   To create an Ember.Handlebars template, call Ember.Handlebars.compile().  This will
18935   return a function that can be used by Ember.View for rendering.
18936
18937   @class Handlebars
18938   @namespace Ember
18939 */
18940 Ember.Handlebars = objectCreate(Handlebars);
18941
18942 /**
18943 @class helpers
18944 @namespace Ember.Handlebars
18945 */
18946 Ember.Handlebars.helpers = objectCreate(Handlebars.helpers);
18947
18948 /**
18949   Override the the opcode compiler and JavaScript compiler for Handlebars.
18950
18951   @class Compiler
18952   @namespace Ember.Handlebars
18953   @private
18954   @constructor
18955 */
18956 Ember.Handlebars.Compiler = function() {};
18957
18958 // Handlebars.Compiler doesn't exist in runtime-only
18959 if (Handlebars.Compiler) {
18960   Ember.Handlebars.Compiler.prototype = objectCreate(Handlebars.Compiler.prototype);
18961 }
18962
18963 Ember.Handlebars.Compiler.prototype.compiler = Ember.Handlebars.Compiler;
18964
18965 /**
18966   @class JavaScriptCompiler
18967   @namespace Ember.Handlebars
18968   @private
18969   @constructor
18970 */
18971 Ember.Handlebars.JavaScriptCompiler = function() {};
18972
18973 // Handlebars.JavaScriptCompiler doesn't exist in runtime-only
18974 if (Handlebars.JavaScriptCompiler) {
18975   Ember.Handlebars.JavaScriptCompiler.prototype = objectCreate(Handlebars.JavaScriptCompiler.prototype);
18976   Ember.Handlebars.JavaScriptCompiler.prototype.compiler = Ember.Handlebars.JavaScriptCompiler;
18977 }
18978
18979
18980 Ember.Handlebars.JavaScriptCompiler.prototype.namespace = "Ember.Handlebars";
18981
18982
18983 Ember.Handlebars.JavaScriptCompiler.prototype.initializeBuffer = function() {
18984   return "''";
18985 };
18986
18987 /**
18988   @private
18989
18990   Override the default buffer for Ember Handlebars. By default, Handlebars creates
18991   an empty String at the beginning of each invocation and appends to it. Ember's
18992   Handlebars overrides this to append to a single shared buffer.
18993
18994   @method appendToBuffer
18995   @param string {String}
18996 */
18997 Ember.Handlebars.JavaScriptCompiler.prototype.appendToBuffer = function(string) {
18998   return "data.buffer.push("+string+");";
18999 };
19000
19001 /**
19002   @private
19003
19004   Rewrite simple mustaches from `{{foo}}` to `{{bind "foo"}}`. This means that all simple
19005   mustaches in Ember's Handlebars will also set up an observer to keep the DOM
19006   up to date when the underlying property changes.
19007
19008   @method mustache
19009   @for Ember.Handlebars.Compiler
19010   @param mustache
19011 */
19012 Ember.Handlebars.Compiler.prototype.mustache = function(mustache) {
19013   if (mustache.params.length || mustache.hash) {
19014     return Handlebars.Compiler.prototype.mustache.call(this, mustache);
19015   } else {
19016     var id = new Handlebars.AST.IdNode(['_triageMustache']);
19017
19018     // Update the mustache node to include a hash value indicating whether the original node
19019     // was escaped. This will allow us to properly escape values when the underlying value
19020     // changes and we need to re-render the value.
19021     if(!mustache.escaped) {
19022       mustache.hash = mustache.hash || new Handlebars.AST.HashNode([]);
19023       mustache.hash.pairs.push(["unescaped", new Handlebars.AST.StringNode("true")]);
19024     }
19025     mustache = new Handlebars.AST.MustacheNode([id].concat([mustache.id]), mustache.hash, !mustache.escaped);
19026     return Handlebars.Compiler.prototype.mustache.call(this, mustache);
19027   }
19028 };
19029
19030 /**
19031   Used for precompilation of Ember Handlebars templates. This will not be used during normal
19032   app execution.
19033
19034   @method precompile
19035   @for Ember.Handlebars
19036   @static
19037   @param {String} string The template to precompile
19038 */
19039 Ember.Handlebars.precompile = function(string) {
19040   var ast = Handlebars.parse(string);
19041
19042   var options = {
19043     knownHelpers: {
19044       action: true,
19045       unbound: true,
19046       bindAttr: true,
19047       template: true,
19048       view: true,
19049       _triageMustache: true
19050     },
19051     data: true,
19052     stringParams: true
19053   };
19054
19055   var environment = new Ember.Handlebars.Compiler().compile(ast, options);
19056   return new Ember.Handlebars.JavaScriptCompiler().compile(environment, options, undefined, true);
19057 };
19058
19059 // We don't support this for Handlebars runtime-only
19060 if (Handlebars.compile) {
19061   /**
19062     The entry point for Ember Handlebars. This replaces the default Handlebars.compile and turns on
19063     template-local data and String parameters.
19064
19065     @method compile
19066     @for Ember.Handlebars
19067     @static
19068     @param {String} string The template to compile
19069     @return {Function}
19070   */
19071   Ember.Handlebars.compile = function(string) {
19072     var ast = Handlebars.parse(string);
19073     var options = { data: true, stringParams: true };
19074     var environment = new Ember.Handlebars.Compiler().compile(ast, options);
19075     var templateSpec = new Ember.Handlebars.JavaScriptCompiler().compile(environment, options, undefined, true);
19076
19077     return Handlebars.template(templateSpec);
19078   };
19079 }
19080
19081 /**
19082   @private
19083
19084   If a path starts with a reserved keyword, returns the root
19085   that should be used.
19086
19087   @method normalizePath
19088   @for Ember
19089   @param root {Object}
19090   @param path {String}
19091   @param data {Hash}
19092 */
19093 var normalizePath = Ember.Handlebars.normalizePath = function(root, path, data) {
19094   var keywords = (data && data.keywords) || {},
19095       keyword, isKeyword;
19096
19097   // Get the first segment of the path. For example, if the
19098   // path is "foo.bar.baz", returns "foo".
19099   keyword = path.split('.', 1)[0];
19100
19101   // Test to see if the first path is a keyword that has been
19102   // passed along in the view's data hash. If so, we will treat
19103   // that object as the new root.
19104   if (keywords.hasOwnProperty(keyword)) {
19105     // Look up the value in the template's data hash.
19106     root = keywords[keyword];
19107     isKeyword = true;
19108
19109     // Handle cases where the entire path is the reserved
19110     // word. In that case, return the object itself.
19111     if (path === keyword) {
19112       path = '';
19113     } else {
19114       // Strip the keyword from the path and look up
19115       // the remainder from the newly found root.
19116       path = path.substr(keyword.length+1);
19117     }
19118   }
19119
19120   return { root: root, path: path, isKeyword: isKeyword };
19121 };
19122
19123
19124 /**
19125   Lookup both on root and on window. If the path starts with
19126   a keyword, the corresponding object will be looked up in the
19127   template's data hash and used to resolve the path.
19128
19129   @method getPath
19130   @for Ember.Handlebars
19131   @param {Object} root The object to look up the property on
19132   @param {String} path The path to be lookedup
19133   @param {Object} options The template's option hash
19134 */
19135 Ember.Handlebars.getPath = function(root, path, options) {
19136   var data = options && options.data,
19137       normalizedPath = normalizePath(root, path, data),
19138       value;
19139
19140   // In cases where the path begins with a keyword, change the
19141   // root to the value represented by that keyword, and ensure
19142   // the path is relative to it.
19143   root = normalizedPath.root;
19144   path = normalizedPath.path;
19145
19146   value = Ember.get(root, path);
19147
19148   if (value === undefined && root !== window && Ember.isGlobalPath(path)) {
19149     value = Ember.get(window, path);
19150   }
19151   return value;
19152 };
19153
19154 /**
19155   @private
19156
19157   Registers a helper in Handlebars that will be called if no property with the
19158   given name can be found on the current context object, and no helper with
19159   that name is registered.
19160
19161   This throws an exception with a more helpful error message so the user can
19162   track down where the problem is happening.
19163
19164   @method helperMissing
19165   @for Ember.Handlebars.helpers
19166   @param {String} path
19167   @param {Hash} options
19168 */
19169 Ember.Handlebars.registerHelper('helperMissing', function(path, options) {
19170   var error, view = "";
19171
19172   error = "%@ Handlebars error: Could not find property '%@' on object %@.";
19173   if (options.data){
19174     view = options.data.view;
19175   }
19176   throw new Ember.Error(Ember.String.fmt(error, [view, path, this]));
19177 });
19178
19179
19180 })();
19181
19182
19183
19184 (function() {
19185 /**
19186   @method htmlSafe
19187   @for Ember.String
19188   @static
19189 */
19190 Ember.String.htmlSafe = function(str) {
19191   return new Handlebars.SafeString(str);
19192 };
19193
19194 var htmlSafe = Ember.String.htmlSafe;
19195
19196 if (Ember.EXTEND_PROTOTYPES) {
19197
19198   /**
19199     See {{#crossLink "Ember.String/htmlSafe"}}{{/crossLink}}
19200
19201     @method htmlSafe
19202     @for String
19203   */
19204   String.prototype.htmlSafe = function() {
19205     return htmlSafe(this);
19206   };
19207
19208 }
19209
19210 })();
19211
19212
19213
19214 (function() {
19215 /*jshint newcap:false*/
19216 /**
19217 @module ember
19218 @submodule ember-handlebars
19219 */
19220
19221 var set = Ember.set, get = Ember.get;
19222
19223 // DOMManager should just abstract dom manipulation between jquery and metamorph
19224 var DOMManager = {
19225   remove: function(view) {
19226     view.morph.remove();
19227   },
19228
19229   prepend: function(view, html) {
19230     view.morph.prepend(html);
19231   },
19232
19233   after: function(view, html) {
19234     view.morph.after(html);
19235   },
19236
19237   html: function(view, html) {
19238     view.morph.html(html);
19239   },
19240
19241   // This is messed up.
19242   replace: function(view) {
19243     var morph = view.morph;
19244
19245     view.transitionTo('preRender');
19246     view.clearRenderedChildren();
19247     var buffer = view.renderToBuffer();
19248
19249     Ember.run.schedule('render', this, function() {
19250       if (get(view, 'isDestroyed')) { return; }
19251       view.invalidateRecursively('element');
19252       view._notifyWillInsertElement();
19253       morph.replaceWith(buffer.string());
19254       view.transitionTo('inDOM');
19255       view._notifyDidInsertElement();
19256     });
19257   },
19258
19259   empty: function(view) {
19260     view.morph.html("");
19261   }
19262 };
19263
19264 // The `morph` and `outerHTML` properties are internal only
19265 // and not observable.
19266
19267 /**
19268   @class _Metamorph
19269   @namespace Ember
19270   @extends Ember.Mixin
19271   @private
19272 */
19273 Ember._Metamorph = Ember.Mixin.create({
19274   isVirtual: true,
19275   tagName: '',
19276
19277   init: function() {
19278     this._super();
19279     this.morph = Metamorph();
19280   },
19281
19282   beforeRender: function(buffer) {
19283     buffer.push(this.morph.startTag());
19284   },
19285
19286   afterRender: function(buffer) {
19287     buffer.push(this.morph.endTag());
19288   },
19289
19290   createElement: function() {
19291     var buffer = this.renderToBuffer();
19292     this.outerHTML = buffer.string();
19293     this.clearBuffer();
19294   },
19295
19296   domManager: DOMManager
19297 });
19298
19299 /**
19300   @class _MetamorphView
19301   @namespace Ember
19302   @extends Ember.View
19303   @uses Ember._Metamorph
19304   @private
19305 */
19306 Ember._MetamorphView = Ember.View.extend(Ember._Metamorph);
19307
19308
19309 })();
19310
19311
19312
19313 (function() {
19314 /*globals Handlebars */
19315
19316 /**
19317 @module ember
19318 @submodule ember-handlebars
19319 */
19320
19321 var get = Ember.get, set = Ember.set, getPath = Ember.Handlebars.getPath;
19322 /**
19323   Ember._HandlebarsBoundView is a private view created by the Handlebars `{{bind}}`
19324   helpers that is used to keep track of bound properties.
19325
19326   Every time a property is bound using a `{{mustache}}`, an anonymous subclass
19327   of Ember._HandlebarsBoundView is created with the appropriate sub-template and
19328   context set up. When the associated property changes, just the template for
19329   this view will re-render.
19330
19331   @class _HandlebarsBoundView
19332   @namespace Ember
19333   @extends Ember._MetamorphView
19334   @private
19335 */
19336 Ember._HandlebarsBoundView = Ember._MetamorphView.extend({
19337
19338   /**
19339     The function used to determine if the `displayTemplate` or
19340     `inverseTemplate` should be rendered. This should be a function that takes
19341     a value and returns a Boolean.
19342
19343     @property shouldDisplayFunc
19344     @type Function
19345     @default null
19346   */
19347   shouldDisplayFunc: null,
19348
19349   /**
19350     Whether the template rendered by this view gets passed the context object
19351     of its parent template, or gets passed the value of retrieving `path`
19352     from the `pathRoot`.
19353
19354     For example, this is true when using the `{{#if}}` helper, because the
19355     template inside the helper should look up properties relative to the same
19356     object as outside the block. This would be false when used with `{{#with
19357     foo}}` because the template should receive the object found by evaluating
19358     `foo`.
19359
19360     @property preserveContext
19361     @type Boolean
19362     @default false
19363   */
19364   preserveContext: false,
19365
19366   /**
19367     If `preserveContext` is true, this is the object that will be used
19368     to render the template.
19369
19370     @property previousContext
19371     @type Object
19372   */
19373   previousContext: null,
19374
19375   /**
19376     The template to render when `shouldDisplayFunc` evaluates to true.
19377
19378     @property displayTemplate
19379     @type Function
19380     @default null
19381   */
19382   displayTemplate: null,
19383
19384   /**
19385     The template to render when `shouldDisplayFunc` evaluates to false.
19386
19387     @property inverseTemplate
19388     @type Function
19389     @default null
19390   */
19391   inverseTemplate: null,
19392
19393
19394   /**
19395     The path to look up on `pathRoot` that is passed to
19396     `shouldDisplayFunc` to determine which template to render.
19397
19398     In addition, if `preserveContext` is false, the object at this path will
19399     be passed to the template when rendering.
19400
19401     @property path
19402     @type String
19403     @default null
19404   */
19405   path: null,
19406
19407   /**
19408     The object from which the `path` will be looked up. Sometimes this is the
19409     same as the `previousContext`, but in cases where this view has been generated
19410     for paths that start with a keyword such as `view` or `controller`, the
19411     path root will be that resolved object.
19412
19413     @property pathRoot
19414     @type Object
19415   */
19416   pathRoot: null,
19417
19418   normalizedValue: Ember.computed(function() {
19419     var path = get(this, 'path'),
19420         pathRoot  = get(this, 'pathRoot'),
19421         valueNormalizer = get(this, 'valueNormalizerFunc'),
19422         result, templateData;
19423
19424     // Use the pathRoot as the result if no path is provided. This
19425     // happens if the path is `this`, which gets normalized into
19426     // a `pathRoot` of the current Handlebars context and a path
19427     // of `''`.
19428     if (path === '') {
19429       result = pathRoot;
19430     } else {
19431       templateData = get(this, 'templateData');
19432       result = getPath(pathRoot, path, { data: templateData });
19433     }
19434
19435     return valueNormalizer ? valueNormalizer(result) : result;
19436   }).property('path', 'pathRoot', 'valueNormalizerFunc').volatile(),
19437
19438   rerenderIfNeeded: function() {
19439     if (!get(this, 'isDestroyed') && get(this, 'normalizedValue') !== this._lastNormalizedValue) {
19440       this.rerender();
19441     }
19442   },
19443
19444   /**
19445     Determines which template to invoke, sets up the correct state based on
19446     that logic, then invokes the default Ember.View `render` implementation.
19447
19448     This method will first look up the `path` key on `pathRoot`,
19449     then pass that value to the `shouldDisplayFunc` function. If that returns
19450     true, the `displayTemplate` function will be rendered to DOM. Otherwise,
19451     `inverseTemplate`, if specified, will be rendered.
19452
19453     For example, if this Ember._HandlebarsBoundView represented the `{{#with foo}}`
19454     helper, it would look up the `foo` property of its context, and
19455     `shouldDisplayFunc` would always return true. The object found by looking
19456     up `foo` would be passed to `displayTemplate`.
19457
19458     @method render
19459     @param {Ember.RenderBuffer} buffer
19460   */
19461   render: function(buffer) {
19462     // If not invoked via a triple-mustache ({{{foo}}}), escape
19463     // the content of the template.
19464     var escape = get(this, 'isEscaped');
19465
19466     var shouldDisplay = get(this, 'shouldDisplayFunc'),
19467         preserveContext = get(this, 'preserveContext'),
19468         context = get(this, 'previousContext');
19469
19470     var inverseTemplate = get(this, 'inverseTemplate'),
19471         displayTemplate = get(this, 'displayTemplate');
19472
19473     var result = get(this, 'normalizedValue');
19474     this._lastNormalizedValue = result;
19475
19476     // First, test the conditional to see if we should
19477     // render the template or not.
19478     if (shouldDisplay(result)) {
19479       set(this, 'template', displayTemplate);
19480
19481       // If we are preserving the context (for example, if this
19482       // is an #if block, call the template with the same object.
19483       if (preserveContext) {
19484         set(this, '_context', context);
19485       } else {
19486       // Otherwise, determine if this is a block bind or not.
19487       // If so, pass the specified object to the template
19488         if (displayTemplate) {
19489           set(this, '_context', result);
19490         } else {
19491         // This is not a bind block, just push the result of the
19492         // expression to the render context and return.
19493           if (result === null || result === undefined) {
19494             result = "";
19495           } else if (!(result instanceof Handlebars.SafeString)) {
19496             result = String(result);
19497           }
19498
19499           if (escape) { result = Handlebars.Utils.escapeExpression(result); }
19500           buffer.push(result);
19501           return;
19502         }
19503       }
19504     } else if (inverseTemplate) {
19505       set(this, 'template', inverseTemplate);
19506
19507       if (preserveContext) {
19508         set(this, '_context', context);
19509       } else {
19510         set(this, '_context', result);
19511       }
19512     } else {
19513       set(this, 'template', function() { return ''; });
19514     }
19515
19516     return this._super(buffer);
19517   }
19518 });
19519
19520 })();
19521
19522
19523
19524 (function() {
19525 /**
19526 @module ember
19527 @submodule ember-handlebars
19528 */
19529
19530 var get = Ember.get, set = Ember.set, fmt = Ember.String.fmt;
19531 var getPath = Ember.Handlebars.getPath, normalizePath = Ember.Handlebars.normalizePath;
19532 var forEach = Ember.ArrayPolyfills.forEach;
19533
19534 var EmberHandlebars = Ember.Handlebars, helpers = EmberHandlebars.helpers;
19535
19536 // Binds a property into the DOM. This will create a hook in DOM that the
19537 // KVO system will look for and update if the property changes.
19538 function bind(property, options, preserveContext, shouldDisplay, valueNormalizer) {
19539   var data = options.data,
19540       fn = options.fn,
19541       inverse = options.inverse,
19542       view = data.view,
19543       currentContext = this,
19544       pathRoot, path, normalized;
19545
19546   normalized = normalizePath(currentContext, property, data);
19547
19548   pathRoot = normalized.root;
19549   path = normalized.path;
19550
19551   // Set up observers for observable objects
19552   if ('object' === typeof this) {
19553     // Create the view that will wrap the output of this template/property
19554     // and add it to the nearest view's childViews array.
19555     // See the documentation of Ember._HandlebarsBoundView for more.
19556     var bindView = view.createChildView(Ember._HandlebarsBoundView, {
19557       preserveContext: preserveContext,
19558       shouldDisplayFunc: shouldDisplay,
19559       valueNormalizerFunc: valueNormalizer,
19560       displayTemplate: fn,
19561       inverseTemplate: inverse,
19562       path: path,
19563       pathRoot: pathRoot,
19564       previousContext: currentContext,
19565       isEscaped: !options.hash.unescaped,
19566       templateData: options.data
19567     });
19568
19569     view.appendChild(bindView);
19570
19571     var observer = function() {
19572       Ember.run.scheduleOnce('render', bindView, 'rerenderIfNeeded');
19573     };
19574
19575     // Observes the given property on the context and
19576     // tells the Ember._HandlebarsBoundView to re-render. If property
19577     // is an empty string, we are printing the current context
19578     // object ({{this}}) so updating it is not our responsibility.
19579     if (path !== '') {
19580       Ember.addObserver(pathRoot, path, observer);
19581     }
19582   } else {
19583     // The object is not observable, so just render it out and
19584     // be done with it.
19585     data.buffer.push(getPath(pathRoot, path, options));
19586   }
19587 }
19588
19589 /**
19590   @private
19591
19592   '_triageMustache' is used internally select between a binding and helper for
19593   the given context. Until this point, it would be hard to determine if the
19594   mustache is a property reference or a regular helper reference. This triage
19595   helper resolves that.
19596
19597   This would not be typically invoked by directly.
19598
19599   @method _triageMustache
19600   @for Ember.Handlebars.helpers
19601   @param {String} property Property/helperID to triage
19602   @param {Function} fn Context to provide for rendering
19603   @return {String} HTML string
19604 */
19605 EmberHandlebars.registerHelper('_triageMustache', function(property, fn) {
19606   Ember.assert("You cannot pass more than one argument to the _triageMustache helper", arguments.length <= 2);
19607   if (helpers[property]) {
19608     return helpers[property].call(this, fn);
19609   }
19610   else {
19611     return helpers.bind.apply(this, arguments);
19612   }
19613 });
19614
19615 /**
19616   @private
19617
19618   `bind` can be used to display a value, then update that value if it
19619   changes. For example, if you wanted to print the `title` property of
19620   `content`:
19621
19622   ``` handlebars
19623   {{bind "content.title"}}
19624   ```
19625
19626   This will return the `title` property as a string, then create a new
19627   observer at the specified path. If it changes, it will update the value in
19628   DOM. Note that if you need to support IE7 and IE8 you must modify the
19629   model objects properties using Ember.get() and Ember.set() for this to work as
19630   it relies on Ember's KVO system.  For all other browsers this will be handled
19631   for you automatically.
19632
19633   @method bind
19634   @for Ember.Handlebars.helpers
19635   @param {String} property Property to bind
19636   @param {Function} fn Context to provide for rendering
19637   @return {String} HTML string
19638 */
19639 EmberHandlebars.registerHelper('bind', function(property, fn) {
19640   Ember.assert("You cannot pass more than one argument to the bind helper", arguments.length <= 2);
19641
19642   var context = (fn.contexts && fn.contexts[0]) || this;
19643
19644   return bind.call(context, property, fn, false, function(result) {
19645     return !Ember.none(result);
19646   });
19647 });
19648
19649 /**
19650   @private
19651
19652   Use the `boundIf` helper to create a conditional that re-evaluates
19653   whenever the bound value changes.
19654
19655   ``` handlebars
19656   {{#boundIf "content.shouldDisplayTitle"}}
19657     {{content.title}}
19658   {{/boundIf}}
19659   ```
19660
19661   @method boundIf
19662   @for Ember.Handlebars.helpers
19663   @param {String} property Property to bind
19664   @param {Function} fn Context to provide for rendering
19665   @return {String} HTML string
19666 */
19667 EmberHandlebars.registerHelper('boundIf', function(property, fn) {
19668   var context = (fn.contexts && fn.contexts[0]) || this;
19669   var func = function(result) {
19670     if (Ember.typeOf(result) === 'array') {
19671       return get(result, 'length') !== 0;
19672     } else {
19673       return !!result;
19674     }
19675   };
19676
19677   return bind.call(context, property, fn, true, func, func);
19678 });
19679
19680 /**
19681   @method with
19682   @for Ember.Handlebars.helpers
19683   @param {Function} context
19684   @param {Hash} options
19685   @return {String} HTML string
19686 */
19687 EmberHandlebars.registerHelper('with', function(context, options) {
19688   if (arguments.length === 4) {
19689     var keywordName, path, rootPath, normalized;
19690
19691     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");
19692     options = arguments[3];
19693     keywordName = arguments[2];
19694     path = arguments[0];
19695
19696     Ember.assert("You must pass a block to the with helper", options.fn && options.fn !== Handlebars.VM.noop);
19697
19698     if (Ember.isGlobalPath(path)) {
19699       Ember.bind(options.data.keywords, keywordName, path);
19700     } else {
19701       normalized = normalizePath(this, path, options.data);
19702       path = normalized.path;
19703       rootPath = normalized.root;
19704
19705       // This is a workaround for the fact that you cannot bind separate objects
19706       // together. When we implement that functionality, we should use it here.
19707       var contextKey = Ember.$.expando + Ember.guidFor(rootPath);
19708       options.data.keywords[contextKey] = rootPath;
19709
19710       // if the path is '' ("this"), just bind directly to the current context
19711       var contextPath = path ? contextKey + '.' + path : contextKey;
19712       Ember.bind(options.data.keywords, keywordName, contextPath);
19713     }
19714
19715     return bind.call(this, path, options, true, function(result) {
19716       return !Ember.none(result);
19717     });
19718   } else {
19719     Ember.assert("You must pass exactly one argument to the with helper", arguments.length === 2);
19720     Ember.assert("You must pass a block to the with helper", options.fn && options.fn !== Handlebars.VM.noop);
19721     return helpers.bind.call(options.contexts[0], context, options);
19722   }
19723 });
19724
19725
19726 /**
19727   @method if
19728   @for Ember.Handlebars.helpers
19729   @param {Function} context
19730   @param {Hash} options
19731   @return {String} HTML string
19732 */
19733 EmberHandlebars.registerHelper('if', function(context, options) {
19734   Ember.assert("You must pass exactly one argument to the if helper", arguments.length === 2);
19735   Ember.assert("You must pass a block to the if helper", options.fn && options.fn !== Handlebars.VM.noop);
19736
19737   return helpers.boundIf.call(options.contexts[0], context, options);
19738 });
19739
19740 /**
19741   @method unless
19742   @for Ember.Handlebars.helpers
19743   @param {Function} context
19744   @param {Hash} options
19745   @return {String} HTML string
19746 */
19747 EmberHandlebars.registerHelper('unless', function(context, options) {
19748   Ember.assert("You must pass exactly one argument to the unless helper", arguments.length === 2);
19749   Ember.assert("You must pass a block to the unless helper", options.fn && options.fn !== Handlebars.VM.noop);
19750
19751   var fn = options.fn, inverse = options.inverse;
19752
19753   options.fn = inverse;
19754   options.inverse = fn;
19755
19756   return helpers.boundIf.call(options.contexts[0], context, options);
19757 });
19758
19759 /**
19760   `bindAttr` allows you to create a binding between DOM element attributes and
19761   Ember objects. For example:
19762
19763   ``` handlebars
19764   <img {{bindAttr src="imageUrl" alt="imageTitle"}}>
19765   ```
19766
19767   @method bindAttr
19768   @for Ember.Handlebars.helpers
19769   @param {Hash} options
19770   @return {String} HTML string
19771 */
19772 EmberHandlebars.registerHelper('bindAttr', function(options) {
19773
19774   var attrs = options.hash;
19775
19776   Ember.assert("You must specify at least one hash argument to bindAttr", !!Ember.keys(attrs).length);
19777
19778   var view = options.data.view;
19779   var ret = [];
19780   var ctx = this;
19781
19782   // Generate a unique id for this element. This will be added as a
19783   // data attribute to the element so it can be looked up when
19784   // the bound property changes.
19785   var dataId = ++Ember.$.uuid;
19786
19787   // Handle classes differently, as we can bind multiple classes
19788   var classBindings = attrs['class'];
19789   if (classBindings !== null && classBindings !== undefined) {
19790     var classResults = EmberHandlebars.bindClasses(this, classBindings, view, dataId, options);
19791     ret.push('class="' + Handlebars.Utils.escapeExpression(classResults.join(' ')) + '"');
19792     delete attrs['class'];
19793   }
19794
19795   var attrKeys = Ember.keys(attrs);
19796
19797   // For each attribute passed, create an observer and emit the
19798   // current value of the property as an attribute.
19799   forEach.call(attrKeys, function(attr) {
19800     var path = attrs[attr],
19801         pathRoot, normalized;
19802
19803     Ember.assert(fmt("You must provide a String for a bound attribute, not %@", [path]), typeof path === 'string');
19804
19805     normalized = normalizePath(ctx, path, options.data);
19806
19807     pathRoot = normalized.root;
19808     path = normalized.path;
19809
19810     var value = (path === 'this') ? pathRoot : getPath(pathRoot, path, options),
19811         type = Ember.typeOf(value);
19812
19813     Ember.assert(fmt("Attributes must be numbers, strings or booleans, not %@", [value]), value === null || value === undefined || type === 'number' || type === 'string' || type === 'boolean');
19814
19815     var observer, invoker;
19816
19817     observer = function observer() {
19818       var result = getPath(pathRoot, path, options);
19819
19820       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');
19821
19822       var elem = view.$("[data-bindattr-" + dataId + "='" + dataId + "']");
19823
19824       // If we aren't able to find the element, it means the element
19825       // to which we were bound has been removed from the view.
19826       // In that case, we can assume the template has been re-rendered
19827       // and we need to clean up the observer.
19828       if (!elem || elem.length === 0) {
19829         Ember.removeObserver(pathRoot, path, invoker);
19830         return;
19831       }
19832
19833       Ember.View.applyAttributeBindings(elem, attr, result);
19834     };
19835
19836     invoker = function() {
19837       Ember.run.scheduleOnce('render', observer);
19838     };
19839
19840     // Add an observer to the view for when the property changes.
19841     // When the observer fires, find the element using the
19842     // unique data id and update the attribute to the new value.
19843     if (path !== 'this') {
19844       Ember.addObserver(pathRoot, path, invoker);
19845     }
19846
19847     // if this changes, also change the logic in ember-views/lib/views/view.js
19848     if ((type === 'string' || (type === 'number' && !isNaN(value)))) {
19849       ret.push(attr + '="' + Handlebars.Utils.escapeExpression(value) + '"');
19850     } else if (value && type === 'boolean') {
19851       // The developer controls the attr name, so it should always be safe
19852       ret.push(attr + '="' + attr + '"');
19853     }
19854   }, this);
19855
19856   // Add the unique identifier
19857   // NOTE: We use all lower-case since Firefox has problems with mixed case in SVG
19858   ret.push('data-bindattr-' + dataId + '="' + dataId + '"');
19859   return new EmberHandlebars.SafeString(ret.join(' '));
19860 });
19861
19862 /**
19863   @private
19864
19865   Helper that, given a space-separated string of property paths and a context,
19866   returns an array of class names. Calling this method also has the side
19867   effect of setting up observers at those property paths, such that if they
19868   change, the correct class name will be reapplied to the DOM element.
19869
19870   For example, if you pass the string "fooBar", it will first look up the
19871   "fooBar" value of the context. If that value is true, it will add the
19872   "foo-bar" class to the current element (i.e., the dasherized form of
19873   "fooBar"). If the value is a string, it will add that string as the class.
19874   Otherwise, it will not add any new class name.
19875
19876   @method bindClasses
19877   @for Ember.Handlebars
19878   @param {Ember.Object} context The context from which to lookup properties
19879   @param {String} classBindings A string, space-separated, of class bindings to use
19880   @param {Ember.View} view The view in which observers should look for the element to update
19881   @param {Srting} bindAttrId Optional bindAttr id used to lookup elements
19882   @return {Array} An array of class names to add
19883 */
19884 EmberHandlebars.bindClasses = function(context, classBindings, view, bindAttrId, options) {
19885   var ret = [], newClass, value, elem;
19886
19887   // Helper method to retrieve the property from the context and
19888   // determine which class string to return, based on whether it is
19889   // a Boolean or not.
19890   var classStringForPath = function(root, parsedPath, options) {
19891     var val,
19892         path = parsedPath.path;
19893
19894     if (path === 'this') {
19895       val = root;
19896     } else if (path === '') {
19897       val = true;
19898     } else {
19899       val = getPath(root, path, options);
19900     }
19901
19902     return Ember.View._classStringForValue(path, val, parsedPath.className, parsedPath.falsyClassName);
19903   };
19904
19905   // For each property passed, loop through and setup
19906   // an observer.
19907   forEach.call(classBindings.split(' '), function(binding) {
19908
19909     // Variable in which the old class value is saved. The observer function
19910     // closes over this variable, so it knows which string to remove when
19911     // the property changes.
19912     var oldClass;
19913
19914     var observer, invoker;
19915
19916     var parsedPath = Ember.View._parsePropertyPath(binding),
19917         path = parsedPath.path,
19918         pathRoot = context,
19919         normalized;
19920
19921     if (path !== '' && path !== 'this') {
19922       normalized = normalizePath(context, path, options.data);
19923
19924       pathRoot = normalized.root;
19925       path = normalized.path;
19926     }
19927
19928     // Set up an observer on the context. If the property changes, toggle the
19929     // class name.
19930     observer = function() {
19931       // Get the current value of the property
19932       newClass = classStringForPath(pathRoot, parsedPath, options);
19933       elem = bindAttrId ? view.$("[data-bindattr-" + bindAttrId + "='" + bindAttrId + "']") : view.$();
19934
19935       // If we can't find the element anymore, a parent template has been
19936       // re-rendered and we've been nuked. Remove the observer.
19937       if (!elem || elem.length === 0) {
19938         Ember.removeObserver(pathRoot, path, invoker);
19939       } else {
19940         // If we had previously added a class to the element, remove it.
19941         if (oldClass) {
19942           elem.removeClass(oldClass);
19943         }
19944
19945         // If necessary, add a new class. Make sure we keep track of it so
19946         // it can be removed in the future.
19947         if (newClass) {
19948           elem.addClass(newClass);
19949           oldClass = newClass;
19950         } else {
19951           oldClass = null;
19952         }
19953       }
19954     };
19955
19956     invoker = function() {
19957       Ember.run.scheduleOnce('render', observer);
19958     };
19959
19960     if (path !== '' && path !== 'this') {
19961       Ember.addObserver(pathRoot, path, invoker);
19962     }
19963
19964     // We've already setup the observer; now we just need to figure out the
19965     // correct behavior right now on the first pass through.
19966     value = classStringForPath(pathRoot, parsedPath, options);
19967
19968     if (value) {
19969       ret.push(value);
19970
19971       // Make sure we save the current value so that it can be removed if the
19972       // observer fires.
19973       oldClass = value;
19974     }
19975   });
19976
19977   return ret;
19978 };
19979
19980
19981 })();
19982
19983
19984
19985 (function() {
19986 /*globals Handlebars */
19987
19988 // TODO: Don't require the entire module
19989 /**
19990 @module ember
19991 @submodule ember-handlebars
19992 */
19993
19994 var get = Ember.get, set = Ember.set;
19995 var PARENT_VIEW_PATH = /^parentView\./;
19996 var EmberHandlebars = Ember.Handlebars;
19997 var VIEW_PRESERVES_CONTEXT = Ember.VIEW_PRESERVES_CONTEXT;
19998
19999 EmberHandlebars.ViewHelper = Ember.Object.create({
20000
20001   propertiesFromHTMLOptions: function(options, thisContext) {
20002     var hash = options.hash, data = options.data;
20003     var extensions = {},
20004         classes = hash['class'],
20005         dup = false;
20006
20007     if (hash.id) {
20008       extensions.elementId = hash.id;
20009       dup = true;
20010     }
20011
20012     if (classes) {
20013       classes = classes.split(' ');
20014       extensions.classNames = classes;
20015       dup = true;
20016     }
20017
20018     if (hash.classBinding) {
20019       extensions.classNameBindings = hash.classBinding.split(' ');
20020       dup = true;
20021     }
20022
20023     if (hash.classNameBindings) {
20024       if (extensions.classNameBindings === undefined) extensions.classNameBindings = [];
20025       extensions.classNameBindings = extensions.classNameBindings.concat(hash.classNameBindings.split(' '));
20026       dup = true;
20027     }
20028
20029     if (hash.attributeBindings) {
20030       Ember.assert("Setting 'attributeBindings' via Handlebars is not allowed. Please subclass Ember.View and set it there instead.");
20031       extensions.attributeBindings = null;
20032       dup = true;
20033     }
20034
20035     if (dup) {
20036       hash = Ember.$.extend({}, hash);
20037       delete hash.id;
20038       delete hash['class'];
20039       delete hash.classBinding;
20040     }
20041
20042     // Set the proper context for all bindings passed to the helper. This applies to regular attribute bindings
20043     // as well as class name bindings. If the bindings are local, make them relative to the current context
20044     // instead of the view.
20045     var path;
20046
20047     // Evaluate the context of regular attribute bindings:
20048     for (var prop in hash) {
20049       if (!hash.hasOwnProperty(prop)) { continue; }
20050
20051       // Test if the property ends in "Binding"
20052       if (Ember.IS_BINDING.test(prop) && typeof hash[prop] === 'string') {
20053         path = this.contextualizeBindingPath(hash[prop], data);
20054         if (path) { hash[prop] = path; }
20055       }
20056     }
20057
20058     // Evaluate the context of class name bindings:
20059     if (extensions.classNameBindings) {
20060       for (var b in extensions.classNameBindings) {
20061         var full = extensions.classNameBindings[b];
20062         if (typeof full === 'string') {
20063           // Contextualize the path of classNameBinding so this:
20064           //
20065           //     classNameBinding="isGreen:green"
20066           //
20067           // is converted to this:
20068           //
20069           //     classNameBinding="bindingContext.isGreen:green"
20070           var parsedPath = Ember.View._parsePropertyPath(full);
20071           path = this.contextualizeBindingPath(parsedPath.path, data);
20072           if (path) { extensions.classNameBindings[b] = path + parsedPath.classNames; }
20073         }
20074       }
20075     }
20076
20077     // Make the current template context available to the view
20078     // for the bindings set up above.
20079     extensions.bindingContext = thisContext;
20080
20081     return Ember.$.extend(hash, extensions);
20082   },
20083
20084   // Transform bindings from the current context to a context that can be evaluated within the view.
20085   // Returns null if the path shouldn't be changed.
20086   //
20087   // TODO: consider the addition of a prefix that would allow this method to return `path`.
20088   contextualizeBindingPath: function(path, data) {
20089     var normalized = Ember.Handlebars.normalizePath(null, path, data);
20090     if (normalized.isKeyword) {
20091       return 'templateData.keywords.' + path;
20092     } else if (Ember.isGlobalPath(path)) {
20093       return null;
20094     } else if (path === 'this') {
20095       return 'bindingContext';
20096     } else {
20097       return 'bindingContext.' + path;
20098     }
20099   },
20100
20101   helper: function(thisContext, path, options) {
20102     var inverse = options.inverse,
20103         data = options.data,
20104         view = data.view,
20105         fn = options.fn,
20106         hash = options.hash,
20107         newView;
20108
20109     if ('string' === typeof path) {
20110       newView = EmberHandlebars.getPath(thisContext, path, options);
20111       Ember.assert("Unable to find view at path '" + path + "'", !!newView);
20112     } else {
20113       newView = path;
20114     }
20115
20116     Ember.assert(Ember.String.fmt('You must pass a view class to the #view helper, not %@ (%@)', [path, newView]), Ember.View.detect(newView));
20117
20118     var viewOptions = this.propertiesFromHTMLOptions(options, thisContext);
20119     var currentView = data.view;
20120     viewOptions.templateData = options.data;
20121
20122     if (fn) {
20123       Ember.assert("You cannot provide a template block if you also specified a templateName", !get(viewOptions, 'templateName') && !get(newView.proto(), 'templateName'));
20124       viewOptions.template = fn;
20125     }
20126
20127     // We only want to override the `_context` computed property if there is
20128     // no specified controller. See View#_context for more information.
20129     if (VIEW_PRESERVES_CONTEXT && !newView.proto().controller && !newView.proto().controllerBinding && !viewOptions.controller && !viewOptions.controllerBinding) {
20130       viewOptions._context = thisContext;
20131     }
20132
20133     currentView.appendChild(newView, viewOptions);
20134   }
20135 });
20136
20137 /**
20138   `{{view}}` inserts a new instance of `Ember.View` into a template passing its options
20139   to the `Ember.View`'s `create` method and using the supplied block as the view's own template.
20140
20141   An empty `<body>` and the following template:
20142
20143   ``` handlebars
20144   <script type="text/x-handlebars">
20145     A span:
20146     {{#view tagName="span"}}
20147       hello.
20148     {{/view}}
20149   </script>
20150   ```
20151
20152   Will result in HTML structure:
20153
20154   ``` html
20155   <body>
20156     <!-- Note: the handlebars template script 
20157          also results in a rendered Ember.View
20158          which is the outer <div> here -->
20159
20160     <div class="ember-view">
20161       A span:
20162       <span id="ember1" class="ember-view">
20163         Hello.
20164       </span>
20165     </div>
20166   </body>
20167   ```
20168
20169   ### parentView setting
20170
20171   The `parentView` property of the new `Ember.View` instance created through `{{view}}`
20172   will be set to the `Ember.View` instance of the template where `{{view}}` was called.
20173
20174   ``` javascript
20175   aView = Ember.View.create({
20176     template: Ember.Handlebars.compile("{{#view}} my parent: {{parentView.elementId}} {{/view}}")
20177   });
20178
20179   aView.appendTo('body');
20180   ```
20181     
20182   Will result in HTML structure:
20183
20184   ``` html
20185   <div id="ember1" class="ember-view">
20186     <div id="ember2" class="ember-view">
20187       my parent: ember1
20188     </div>
20189   </div>
20190   ```
20191
20192   ### Setting CSS id and class attributes
20193
20194   The HTML `id` attribute can be set on the `{{view}}`'s resulting element with the `id` option.
20195   This option will _not_ be passed to `Ember.View.create`.
20196
20197   ``` handlebars
20198   <script type="text/x-handlebars">
20199     {{#view tagName="span" id="a-custom-id"}}
20200       hello.
20201     {{/view}}
20202   </script>
20203   ```
20204
20205   Results in the following HTML structure:
20206
20207   ``` html
20208   <div class="ember-view">
20209     <span id="a-custom-id" class="ember-view">
20210       hello.
20211     </span>
20212   </div>
20213   ```
20214
20215   The HTML `class` attribute can be set on the `{{view}}`'s resulting element with
20216   the `class` or `classNameBindings` options. The `class` option
20217   will directly set the CSS `class` attribute and will not be passed to
20218   `Ember.View.create`. `classNameBindings` will be passed to `create` and use
20219   `Ember.View`'s class name binding functionality:
20220
20221   ``` handlebars
20222   <script type="text/x-handlebars">
20223     {{#view tagName="span" class="a-custom-class"}}
20224       hello.
20225     {{/view}}
20226   </script>
20227   ```
20228
20229   Results in the following HTML structure:
20230
20231   ``` html
20232   <div class="ember-view">
20233     <span id="ember2" class="ember-view a-custom-class">
20234       hello.
20235     </span>
20236   </div>
20237   ```
20238
20239   ### Supplying a different view class
20240
20241   `{{view}}` can take an optional first argument before its supplied options to specify a
20242   path to a custom view class.
20243
20244   ``` handlebars
20245   <script type="text/x-handlebars">
20246     {{#view "MyApp.CustomView"}}
20247       hello.
20248     {{/view}}
20249   </script>
20250   ```
20251
20252   The first argument can also be a relative path. Ember will search for the view class
20253   starting at the `Ember.View` of the template where `{{view}}` was used as the root object:
20254
20255   ``` javascript
20256   MyApp = Ember.Application.create({});
20257   MyApp.OuterView = Ember.View.extend({
20258     innerViewClass: Ember.View.extend({
20259       classNames: ['a-custom-view-class-as-property']
20260     }),
20261     template: Ember.Handlebars.compile('{{#view "innerViewClass"}} hi {{/view}}')
20262   });
20263
20264   MyApp.OuterView.create().appendTo('body');
20265   ```
20266
20267   Will result in the following HTML:
20268
20269   ``` html
20270   <div id="ember1" class="ember-view">
20271     <div id="ember2" class="ember-view a-custom-view-class-as-property"> 
20272       hi
20273     </div>
20274   </div>
20275   ```
20276
20277   ### Blockless use
20278
20279   If you supply a custom `Ember.View` subclass that specifies its own template
20280   or provide a `templateName` option to `{{view}}` it can be used without supplying a block.
20281   Attempts to use both a `templateName` option and supply a block will throw an error.
20282
20283   ``` handlebars
20284   <script type="text/x-handlebars">
20285     {{view "MyApp.ViewWithATemplateDefined"}}
20286   </script>
20287   ```
20288
20289   ### viewName property
20290
20291   You can supply a `viewName` option to `{{view}}`. The `Ember.View` instance will
20292   be referenced as a property of its parent view by this name.
20293
20294   ``` javascript
20295   aView = Ember.View.create({
20296     template: Ember.Handlebars.compile('{{#view viewName="aChildByName"}} hi {{/view}}')
20297   });
20298
20299   aView.appendTo('body');
20300   aView.get('aChildByName') // the instance of Ember.View created by {{view}} helper
20301   ```
20302
20303   @method view
20304   @for Ember.Handlebars.helpers
20305   @param {String} path
20306   @param {Hash} options
20307   @return {String} HTML string
20308 */
20309 EmberHandlebars.registerHelper('view', function(path, options) {
20310   Ember.assert("The view helper only takes a single argument", arguments.length <= 2);
20311
20312   // If no path is provided, treat path param as options.
20313   if (path && path.data && path.data.isRenderData) {
20314     options = path;
20315     path = "Ember.View";
20316   }
20317
20318   return EmberHandlebars.ViewHelper.helper(this, path, options);
20319 });
20320
20321
20322 })();
20323
20324
20325
20326 (function() {
20327 /*globals Handlebars */
20328
20329 // TODO: Don't require all of this module
20330 /**
20331 @module ember
20332 @submodule ember-handlebars
20333 */
20334
20335 var get = Ember.get, getPath = Ember.Handlebars.getPath, fmt = Ember.String.fmt;
20336
20337 /**
20338   `{{collection}}` is a `Ember.Handlebars` helper for adding instances of
20339   `Ember.CollectionView` to a template.  See `Ember.CollectionView` for additional
20340   information on how a `CollectionView` functions.
20341
20342   `{{collection}}`'s primary use is as a block helper with a `contentBinding` option
20343   pointing towards an `Ember.Array`-compatible object.  An `Ember.View` instance will
20344   be created for each item in its `content` property. Each view will have its own
20345   `content` property set to the appropriate item in the collection.
20346
20347   The provided block will be applied as the template for each item's view.
20348
20349   Given an empty `<body>` the following template:
20350
20351   ``` handlebars
20352   <script type="text/x-handlebars">
20353     {{#collection contentBinding="App.items"}}
20354       Hi {{view.content.name}}
20355     {{/collection}}
20356   </script>
20357   ```
20358
20359   And the following application code
20360
20361   ``` javascript
20362   App = Ember.Application.create()
20363   App.items = [
20364     Ember.Object.create({name: 'Dave'}),
20365     Ember.Object.create({name: 'Mary'}),
20366     Ember.Object.create({name: 'Sara'})
20367   ]
20368   ```
20369
20370   Will result in the HTML structure below
20371
20372   ``` html
20373   <div class="ember-view">
20374     <div class="ember-view">Hi Dave</div>
20375     <div class="ember-view">Hi Mary</div>
20376     <div class="ember-view">Hi Sara</div>
20377   </div>
20378   ```
20379
20380   ### Blockless Use
20381   If you provide an `itemViewClass` option that has its own `template` you can omit
20382   the block.
20383
20384   The following template:
20385
20386   ``` handlebars
20387   <script type="text/x-handlebars">
20388     {{collection contentBinding="App.items" itemViewClass="App.AnItemView"}}
20389   </script>
20390   ```
20391
20392   And application code
20393
20394   ``` javascript
20395   App = Ember.Application.create();
20396   App.items = [
20397     Ember.Object.create({name: 'Dave'}),
20398     Ember.Object.create({name: 'Mary'}),
20399     Ember.Object.create({name: 'Sara'})
20400   ];
20401
20402   App.AnItemView = Ember.View.extend({
20403     template: Ember.Handlebars.compile("Greetings {{view.content.name}}")
20404   });
20405   ```
20406
20407   Will result in the HTML structure below
20408
20409   ``` html
20410   <div class="ember-view">
20411     <div class="ember-view">Greetings Dave</div>
20412     <div class="ember-view">Greetings Mary</div>
20413     <div class="ember-view">Greetings Sara</div>
20414   </div>
20415   ```
20416
20417   ### Specifying a CollectionView subclass
20418
20419   By default the `{{collection}}` helper will create an instance of `Ember.CollectionView`.
20420   You can supply a `Ember.CollectionView` subclass to the helper by passing it
20421   as the first argument:
20422
20423   ``` handlebars
20424   <script type="text/x-handlebars">
20425     {{#collection App.MyCustomCollectionClass contentBinding="App.items"}}
20426       Hi {{view.content.name}}
20427     {{/collection}}
20428   </script>
20429   ```
20430
20431
20432   ### Forwarded `item.*`-named Options
20433
20434   As with the `{{view}}`, helper options passed to the `{{collection}}` will be set on
20435   the resulting `Ember.CollectionView` as properties. Additionally, options prefixed with
20436   `item` will be applied to the views rendered for each item (note the camelcasing):
20437
20438   ``` handlebars
20439   <script type="text/x-handlebars">
20440     {{#collection contentBinding="App.items"
20441                   itemTagName="p"
20442                   itemClassNames="greeting"}}
20443       Howdy {{view.content.name}}
20444     {{/collection}}
20445   </script>
20446   ```
20447
20448   Will result in the following HTML structure:
20449
20450   ``` html
20451   <div class="ember-view">
20452     <p class="ember-view greeting">Howdy Dave</p>
20453     <p class="ember-view greeting">Howdy Mary</p>
20454     <p class="ember-view greeting">Howdy Sara</p>
20455   </div>
20456   ```
20457
20458   @method collection
20459   @for Ember.Handlebars.helpers
20460   @param {String} path
20461   @param {Hash} options
20462   @return {String} HTML string
20463 */
20464 Ember.Handlebars.registerHelper('collection', function(path, options) {
20465   // If no path is provided, treat path param as options.
20466   if (path && path.data && path.data.isRenderData) {
20467     options = path;
20468     path = undefined;
20469     Ember.assert("You cannot pass more than one argument to the collection helper", arguments.length === 1);
20470   } else {
20471     Ember.assert("You cannot pass more than one argument to the collection helper", arguments.length === 2);
20472   }
20473
20474   var fn = options.fn;
20475   var data = options.data;
20476   var inverse = options.inverse;
20477
20478   // If passed a path string, convert that into an object.
20479   // Otherwise, just default to the standard class.
20480   var collectionClass;
20481   collectionClass = path ? getPath(this, path, options) : Ember.CollectionView;
20482   Ember.assert(fmt("%@ #collection: Could not find collection class %@", [data.view, path]), !!collectionClass);
20483
20484   var hash = options.hash, itemHash = {}, match;
20485
20486   // Extract item view class if provided else default to the standard class
20487   var itemViewClass, itemViewPath = hash.itemViewClass;
20488   var collectionPrototype = collectionClass.proto();
20489   delete hash.itemViewClass;
20490   itemViewClass = itemViewPath ? getPath(collectionPrototype, itemViewPath, options) : collectionPrototype.itemViewClass;
20491   Ember.assert(fmt("%@ #collection: Could not find itemViewClass %@", [data.view, itemViewPath]), !!itemViewClass);
20492
20493   // Go through options passed to the {{collection}} helper and extract options
20494   // that configure item views instead of the collection itself.
20495   for (var prop in hash) {
20496     if (hash.hasOwnProperty(prop)) {
20497       match = prop.match(/^item(.)(.*)$/);
20498
20499       if(match) {
20500         // Convert itemShouldFoo -> shouldFoo
20501         itemHash[match[1].toLowerCase() + match[2]] = hash[prop];
20502         // Delete from hash as this will end up getting passed to the
20503         // {{view}} helper method.
20504         delete hash[prop];
20505       }
20506     }
20507   }
20508
20509   var tagName = hash.tagName || collectionPrototype.tagName;
20510
20511   if (fn) {
20512     itemHash.template = fn;
20513     delete options.fn;
20514   }
20515
20516   var emptyViewClass;
20517   if (inverse && inverse !== Handlebars.VM.noop) {
20518     emptyViewClass = get(collectionPrototype, 'emptyViewClass');
20519     emptyViewClass = emptyViewClass.extend({
20520           template: inverse,
20521           tagName: itemHash.tagName
20522     });
20523   } else if (hash.emptyViewClass) {
20524     emptyViewClass = getPath(this, hash.emptyViewClass, options);
20525   }
20526   hash.emptyView = emptyViewClass;
20527
20528   if (hash.eachHelper === 'each') {
20529     itemHash._context = Ember.computed(function() {
20530       return get(this, 'content');
20531     }).property('content');
20532     delete hash.eachHelper;
20533   }
20534
20535   var viewOptions = Ember.Handlebars.ViewHelper.propertiesFromHTMLOptions({ data: data, hash: itemHash }, this);
20536   hash.itemViewClass = itemViewClass.extend(viewOptions);
20537
20538   return Ember.Handlebars.helpers.view.call(this, collectionClass, options);
20539 });
20540
20541
20542 })();
20543
20544
20545
20546 (function() {
20547 /*globals Handlebars */
20548 /**
20549 @module ember
20550 @submodule ember-handlebars
20551 */
20552
20553 var getPath = Ember.Handlebars.getPath;
20554
20555 /**
20556   `unbound` allows you to output a property without binding. *Important:* The
20557   output will not be updated if the property changes. Use with caution.
20558
20559   ``` handlebars
20560   <div>{{unbound somePropertyThatDoesntChange}}</div>
20561   ```
20562
20563   @method unbound
20564   @for Ember.Handlebars.helpers
20565   @param {String} property
20566   @return {String} HTML string
20567 */
20568 Ember.Handlebars.registerHelper('unbound', function(property, fn) {
20569   var context = (fn.contexts && fn.contexts[0]) || this;
20570   return getPath(context, property, fn);
20571 });
20572
20573 })();
20574
20575
20576
20577 (function() {
20578 /*jshint debug:true*/
20579 /**
20580 @module ember
20581 @submodule ember-handlebars
20582 */
20583
20584 var getPath = Ember.Handlebars.getPath, normalizePath = Ember.Handlebars.normalizePath;
20585
20586 /**
20587   `log` allows you to output the value of a value in the current rendering
20588   context.
20589
20590   ``` handlebars
20591   {{log myVariable}}
20592   ```
20593
20594   @method log
20595   @for Ember.Handlebars.helpers
20596   @param {String} property
20597 */
20598 Ember.Handlebars.registerHelper('log', function(property, options) {
20599   var context = (options.contexts && options.contexts[0]) || this,
20600       normalized = normalizePath(context, property, options.data),
20601       pathRoot = normalized.root,
20602       path = normalized.path,
20603       value = (path === 'this') ? pathRoot : getPath(pathRoot, path, options);
20604   Ember.Logger.log(value);
20605 });
20606
20607 /**
20608   The `debugger` helper executes the `debugger` statement in the current
20609   context.
20610
20611   ``` handlebars
20612   {{debugger}}
20613   ```
20614
20615   @method debugger
20616   @for Ember.Handlebars.helpers
20617   @param {String} property
20618 */
20619 Ember.Handlebars.registerHelper('debugger', function() {
20620   debugger;
20621 });
20622
20623 })();
20624
20625
20626
20627 (function() {
20628 /**
20629 @module ember
20630 @submodule ember-handlebars
20631 */
20632
20633 var get = Ember.get, set = Ember.set;
20634
20635 Ember.Handlebars.EachView = Ember.CollectionView.extend(Ember._Metamorph, {
20636   itemViewClass: Ember._MetamorphView,
20637   emptyViewClass: Ember._MetamorphView,
20638
20639   createChildView: function(view, attrs) {
20640     view = this._super(view, attrs);
20641
20642     // At the moment, if a container view subclass wants
20643     // to insert keywords, it is responsible for cloning
20644     // the keywords hash. This will be fixed momentarily.
20645     var keyword = get(this, 'keyword');
20646
20647     if (keyword) {
20648       var data = get(view, 'templateData');
20649
20650       data = Ember.copy(data);
20651       data.keywords = view.cloneKeywords();
20652       set(view, 'templateData', data);
20653
20654       var content = get(view, 'content');
20655
20656       // In this case, we do not bind, because the `content` of
20657       // a #each item cannot change.
20658       data.keywords[keyword] = content;
20659     }
20660
20661     return view;
20662   }
20663 });
20664
20665 /**
20666   The `{{#each}}` helper loops over elements in a collection, rendering its block once for each item:
20667
20668   ``` javascript
20669   Developers = [{name: 'Yehuda'},{name: 'Tom'}, {name: 'Paul'}];
20670   ```
20671
20672   ``` handlebars
20673   {{#each Developers}}
20674     {{name}}
20675   {{/each}}
20676   ```
20677
20678   `{{each}}` supports an alternative syntax with element naming:
20679
20680   ``` handlebars
20681   {{#each person in Developers}}
20682     {{person.name}}
20683   {{/each}}
20684   ```
20685
20686   When looping over objects that do not have properties, `{{this}}` can be used to render the object:
20687
20688   ``` javascript
20689   DeveloperNames = ['Yehuda', 'Tom', 'Paul']
20690   ```
20691
20692   ``` handlebars
20693   {{#each DeveloperNames}}
20694     {{this}}
20695   {{/each}}
20696   ```
20697
20698   ### Blockless Use
20699
20700   If you provide an `itemViewClass` option that has its own `template` you can omit
20701   the block in a similar way to how it can be done with the collection helper.
20702
20703   The following template:
20704
20705   ``` handlebars
20706   <script type="text/x-handlebars">
20707     {{#view App.MyView }}
20708       {{each view.items itemViewClass="App.AnItemView"}} 
20709     {{/view}}
20710   </script>
20711   ```
20712
20713   And application code
20714
20715   ``` javascript
20716   App = Ember.Application.create({
20717     MyView: Ember.View.extend({
20718       items: [
20719         Ember.Object.create({name: 'Dave'}),
20720         Ember.Object.create({name: 'Mary'}),
20721         Ember.Object.create({name: 'Sara'})
20722       ]
20723     })
20724   });
20725
20726   App.AnItemView = Ember.View.extend({
20727     template: Ember.Handlebars.compile("Greetings {{name}}")
20728   });
20729       
20730   App.initialize();
20731   ```
20732       
20733   Will result in the HTML structure below
20734
20735   ``` html
20736   <div class="ember-view">
20737     <div class="ember-view">Greetings Dave</div>
20738     <div class="ember-view">Greetings Mary</div>
20739     <div class="ember-view">Greetings Sara</div>
20740   </div>
20741   ```
20742
20743
20744   @method each
20745   @for Ember.Handlebars.helpers
20746   @param [name] {String} name for item (used with `in`)
20747   @param path {String} path
20748 */
20749 Ember.Handlebars.registerHelper('each', function(path, options) {
20750   if (arguments.length === 4) {
20751     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");
20752
20753     var keywordName = arguments[0];
20754
20755     options = arguments[3];
20756     path = arguments[2];
20757     if (path === '') { path = "this"; }
20758
20759     options.hash.keyword = keywordName;
20760   } else {
20761     options.hash.eachHelper = 'each';
20762   }
20763
20764   options.hash.contentBinding = path;
20765   // Set up emptyView as a metamorph with no tag
20766   //options.hash.emptyViewClass = Ember._MetamorphView;
20767
20768   return Ember.Handlebars.helpers.collection.call(this, 'Ember.Handlebars.EachView', options);
20769 });
20770
20771 })();
20772
20773
20774
20775 (function() {
20776 /**
20777 @module ember
20778 @submodule ember-handlebars
20779 */
20780
20781 /**
20782   `template` allows you to render a template from inside another template.
20783   This allows you to re-use the same template in multiple places. For example:
20784
20785   ``` handlebars
20786   <script type="text/x-handlebars">
20787     {{#with loggedInUser}}
20788       Last Login: {{lastLogin}}
20789       User Info: {{template "user_info"}}
20790     {{/with}}
20791   </script>
20792
20793   <script type="text/x-handlebars" data-template-name="user_info">
20794     Name: <em>{{name}}</em>
20795     Karma: <em>{{karma}}</em>
20796   </script>
20797   ```
20798
20799   This helper looks for templates in the global Ember.TEMPLATES hash. If you
20800   add &lt;script&gt; tags to your page with the `data-template-name` attribute set,
20801   they will be compiled and placed in this hash automatically.
20802
20803   You can also manually register templates by adding them to the hash:
20804
20805   ``` javascript
20806   Ember.TEMPLATES["my_cool_template"] = Ember.Handlebars.compile('<b>{{user}}</b>');
20807   ```
20808
20809   @method template
20810   @for Ember.Handlebars.helpers
20811   @param {String} templateName the template to render
20812 */
20813
20814 Ember.Handlebars.registerHelper('template', function(name, options) {
20815   var template = Ember.TEMPLATES[name];
20816
20817   Ember.assert("Unable to find template with name '"+name+"'.", !!template);
20818
20819   Ember.TEMPLATES[name](this, { data: options.data });
20820 });
20821
20822 })();
20823
20824
20825
20826 (function() {
20827 /**
20828 @module ember
20829 @submodule ember-handlebars
20830 */
20831
20832 var EmberHandlebars = Ember.Handlebars,
20833     getPath = EmberHandlebars.getPath,
20834     get = Ember.get,
20835     a_slice = Array.prototype.slice;
20836
20837 var ActionHelper = EmberHandlebars.ActionHelper = {
20838   registeredActions: {}
20839 };
20840
20841 ActionHelper.registerAction = function(actionName, options) {
20842   var actionId = (++Ember.$.uuid).toString();
20843
20844   ActionHelper.registeredActions[actionId] = {
20845     eventName: options.eventName,
20846     handler: function(event) {
20847       var modifier = event.shiftKey || event.metaKey || event.altKey || event.ctrlKey,
20848           secondaryClick = event.which > 1, // IE9 may return undefined
20849           nonStandard = modifier || secondaryClick;
20850
20851       if (options.link && nonStandard) {
20852         // Allow the browser to handle special link clicks normally
20853         return;
20854       }
20855
20856       event.preventDefault();
20857
20858       event.view = options.view;
20859
20860       if (options.hasOwnProperty('context')) {
20861         event.context = options.context;
20862       }
20863
20864       if (options.hasOwnProperty('contexts')) {
20865         event.contexts = options.contexts;
20866       }
20867
20868       var target = options.target;
20869
20870       // Check for StateManager (or compatible object)
20871       if (target.isState && typeof target.send === 'function') {
20872         return target.send(actionName, event);
20873       } else {
20874         Ember.assert(Ember.String.fmt('Target %@ does not have action %@', [target, actionName]), target[actionName]);
20875         return target[actionName].call(target, event);
20876       }
20877     }
20878   };
20879
20880   options.view.on('willRerender', function() {
20881     delete ActionHelper.registeredActions[actionId];
20882   });
20883
20884   return actionId;
20885 };
20886
20887 /**
20888   The `{{action}}` helper registers an HTML element within a template for
20889   DOM event handling and forwards that interaction to the Application's router,
20890   the template's `Ember.View` instance, or supplied `target` option (see 'Specifying a Target').
20891   
20892   User interaction with that element will invoke the supplied action name on
20893   the appropriate target.
20894
20895   Given the following Handlebars template on the page
20896
20897   ``` handlebars
20898   <script type="text/x-handlebars" data-template-name='a-template'>
20899     <div {{action anActionName}}>
20900       click me
20901     </div>
20902   </script>
20903   ```
20904
20905   And application code
20906
20907   ``` javascript
20908   AView = Ember.View.extend({
20909     templateName; 'a-template',
20910     anActionName: function(event){}
20911   });
20912
20913   aView = AView.create();
20914   aView.appendTo('body');
20915   ```
20916
20917   Will results in the following rendered HTML
20918
20919   ``` html
20920   <div class="ember-view">
20921     <div data-ember-action="1">
20922       click me
20923     </div>
20924   </div>
20925   ```
20926
20927   Clicking "click me" will trigger the `anActionName` method of the `aView`
20928   object with a  `jQuery.Event` object as its argument. The `jQuery.Event`
20929   object will be extended to include a `view` property that is set to the
20930   original view interacted with (in this case the `aView` object).
20931
20932   ### Event Propagation
20933
20934   Events triggered through the action helper will automatically have
20935   `.preventDefault()` called on them. You do not need to do so in your event
20936   handlers. To stop propagation of the event, simply return `false` from your
20937   handler.
20938
20939   If you need the default handler to trigger you should either register your
20940   own event handler, or use event methods on your view class. See Ember.View
20941   'Responding to Browser Events' for more information.
20942   
20943   ### Specifying DOM event type
20944
20945   By default the `{{action}}` helper registers for DOM `click` events. You can
20946   supply an `on` option to the helper to specify a different DOM event name:
20947
20948   ``` handlebars
20949   <script type="text/x-handlebars" data-template-name='a-template'>
20950     <div {{action anActionName on="doubleClick"}}>
20951       click me
20952     </div>
20953   </script>
20954   ```
20955
20956   See Ember.View 'Responding to Browser Events' for a list of
20957   acceptable DOM event names.
20958
20959   Because `{{action}}` depends on Ember's event dispatch system it will only
20960   function if an `Ember.EventDispatcher` instance is available. An
20961   `Ember.EventDispatcher` instance will be created when a new
20962   `Ember.Application` is created. Having an instance of `Ember.Application`
20963   will satisfy this requirement.
20964   
20965   
20966   ### Specifying a Target
20967   There are several possible target objects for `{{action}}` helpers:
20968   
20969   In a typical `Ember.Router`-backed Application where views are managed
20970   through use of the `{{outlet}}` helper, actions will be forwarded to the
20971   current state of the Applications's Router. See Ember.Router 'Responding
20972   to User-initiated Events' for more information.
20973   
20974   If you manually set the `target` property on the controller of a template's
20975   `Ember.View` instance, the specifed `controller.target` will become the target
20976   for any actions. Likely custom values for a controller's `target` are the
20977   controller itself or a StateManager other than the Application's Router.
20978   
20979   If the templates's view lacks a controller property the view itself is the target.
20980   
20981   Finally, a `target` option can be provided to the helper to change which object
20982   will receive the method call. This option must be a string representing a
20983   path to an object:
20984
20985   ``` handlebars
20986   <script type="text/x-handlebars" data-template-name='a-template'>
20987     <div {{action anActionName target="MyApplication.someObject"}}>
20988       click me
20989     </div>
20990   </script>
20991   ```
20992
20993   Clicking "click me" in the rendered HTML of the above template will trigger
20994   the  `anActionName` method of the object at `MyApplication.someObject`.
20995   The first argument to this method will be a `jQuery.Event` extended to
20996   include a `view` property that is set to the original view interacted with.
20997
20998   A path relative to the template's `Ember.View` instance can also be used as
20999   a target:
21000
21001   ``` handlebars
21002   <script type="text/x-handlebars" data-template-name='a-template'>
21003     <div {{action anActionName target="parentView"}}>
21004       click me
21005     </div>
21006   </script>
21007   ```
21008
21009   Clicking "click me" in the rendered HTML of the above template will trigger
21010   the `anActionName` method of the view's parent view.
21011
21012   The `{{action}}` helper is `Ember.StateManager` aware. If the target of the
21013   action is an `Ember.StateManager` instance `{{action}}` will use the `send`
21014   functionality of StateManagers. The documentation for `Ember.StateManager`
21015   has additional information about this use.
21016
21017   If an action's target does not implement a method that matches the supplied
21018   action name an error will be thrown.
21019
21020   ``` handlebars
21021   <script type="text/x-handlebars" data-template-name='a-template'>
21022     <div {{action aMethodNameThatIsMissing}}>
21023       click me
21024     </div>
21025   </script>
21026   ```
21027
21028   With the following application code
21029
21030   ``` javascript
21031   AView = Ember.View.extend({
21032     templateName; 'a-template',
21033     // note: no method 'aMethodNameThatIsMissing'
21034     anActionName: function(event){}
21035   });
21036
21037   aView = AView.create();
21038   aView.appendTo('body');
21039   ```
21040
21041   Will throw `Uncaught TypeError: Cannot call method 'call' of undefined` when
21042   "click me" is clicked.
21043   
21044   ### Specifying a context
21045
21046   By default the `{{action}}` helper passes the current Handlebars context
21047   along in the `jQuery.Event` object. You may specify an alternate object to
21048   pass as the context by providing a property path:
21049
21050   ``` handlebars
21051   <script type="text/x-handlebars" data-template-name='a-template'>
21052     {{#each person in people}}
21053       <div {{action edit person}}>
21054         click me
21055       </div>
21056     {{/each}}
21057   </script>
21058   ```
21059
21060   @method action
21061   @for Ember.Handlebars.helpers
21062   @param {String} actionName
21063   @param {Object...} contexts
21064   @param {Hash} options
21065 */
21066 EmberHandlebars.registerHelper('action', function(actionName) {
21067   var options = arguments[arguments.length - 1],
21068       contexts = a_slice.call(arguments, 1, -1);
21069
21070   var hash = options.hash,
21071       view = options.data.view,
21072       target, controller, link;
21073
21074   // create a hash to pass along to registerAction
21075   var action = {
21076     eventName: hash.on || "click"
21077   };
21078
21079   action.view = view = get(view, 'concreteView');
21080
21081   if (hash.target) {
21082     target = getPath(this, hash.target, options);
21083   } else if (controller = options.data.keywords.controller) {
21084     target = get(controller, 'target');
21085   }
21086
21087   action.target = target = target || view;
21088
21089   if (contexts.length) {
21090     action.contexts = contexts = Ember.EnumerableUtils.map(contexts, function(context) {
21091       return getPath(this, context, options);
21092     }, this);
21093     action.context = contexts[0];
21094   }
21095
21096   var output = [], url;
21097
21098   if (hash.href && target.urlForEvent) {
21099     url = target.urlForEvent.apply(target, [actionName].concat(contexts));
21100     output.push('href="' + url + '"');
21101     action.link = true;
21102   }
21103
21104   var actionId = ActionHelper.registerAction(actionName, action);
21105   output.push('data-ember-action="' + actionId + '"');
21106
21107   return new EmberHandlebars.SafeString(output.join(" "));
21108 });
21109
21110 })();
21111
21112
21113
21114 (function() {
21115 /**
21116 @module ember
21117 @submodule ember-handlebars
21118 */
21119
21120 var get = Ember.get, set = Ember.set;
21121
21122 /**
21123
21124   When used in a Handlebars template that is assigned to an `Ember.View` instance's
21125   `layout` property Ember will render the layout template first, inserting the view's
21126   own rendered output at the `{{ yield }}` location.
21127
21128   An empty `<body>` and the following application code:
21129
21130   ``` javascript
21131   AView = Ember.View.extend({
21132     classNames: ['a-view-with-layout'],
21133     layout: Ember.Handlebars.compile('<div class="wrapper">{{ yield }}</div>'),
21134     template: Ember.Handlebars.compile('<span>I am wrapped</span>')
21135   });
21136
21137   aView = AView.create();
21138   aView.appendTo('body');
21139   ```
21140
21141   Will result in the following HTML output:
21142
21143   ``` html
21144   <body>
21145     <div class='ember-view a-view-with-layout'>
21146       <div class="wrapper">
21147         <span>I am wrapped</span>
21148       </div>
21149     </div>
21150   </body>
21151   ```
21152
21153   The yield helper cannot be used outside of a template assigned to an `Ember.View`'s `layout` property
21154   and will throw an error if attempted.
21155
21156   ``` javascript
21157   BView = Ember.View.extend({
21158     classNames: ['a-view-with-layout'],
21159     template: Ember.Handlebars.compile('{{yield}}')
21160   });
21161
21162   bView = BView.create();
21163   bView.appendTo('body');
21164
21165   // throws
21166   // Uncaught Error: assertion failed: You called yield in a template that was not a layout
21167   ```
21168
21169   @method yield
21170   @for Ember.Handlebars.helpers
21171   @param {Hash} options
21172   @return {String} HTML string
21173 */
21174 Ember.Handlebars.registerHelper('yield', function(options) {
21175   var view = options.data.view, template;
21176
21177   while (view && !get(view, 'layout')) {
21178     view = get(view, 'parentView');
21179   }
21180
21181   Ember.assert("You called yield in a template that was not a layout", !!view);
21182
21183   template = get(view, 'template');
21184
21185   if (template) { template(this, options); }
21186 });
21187
21188 })();
21189
21190
21191
21192 (function() {
21193 /**
21194 @module ember
21195 @submodule ember-handlebars
21196 */
21197
21198 Ember.Handlebars.OutletView = Ember.ContainerView.extend(Ember._Metamorph);
21199
21200 /**
21201   The `outlet` helper allows you to specify that the current
21202   view's controller will fill in the view for a given area.
21203
21204   ``` handlebars
21205   {{outlet}}
21206   ```
21207
21208   By default, when the the current controller's `view`
21209   property changes, the outlet will replace its current
21210   view with the new view.
21211
21212   ``` javascript
21213   controller.set('view', someView);
21214   ```
21215
21216   You can also specify a particular name, other than view:
21217
21218   ``` handlebars
21219   {{outlet masterView}}
21220   {{outlet detailView}}
21221   ```
21222
21223   Then, you can control several outlets from a single
21224   controller:
21225
21226   ``` javascript
21227   controller.set('masterView', postsView);
21228   controller.set('detailView', postView);
21229   ```
21230
21231   @method outlet
21232   @for Ember.Handlebars.helpers
21233   @param {String} property the property on the controller
21234     that holds the view for this outlet
21235 */
21236 Ember.Handlebars.registerHelper('outlet', function(property, options) {
21237   if (property && property.data && property.data.isRenderData) {
21238     options = property;
21239     property = 'view';
21240   }
21241
21242   options.hash.currentViewBinding = "controller." + property;
21243
21244   return Ember.Handlebars.helpers.view.call(this, Ember.Handlebars.OutletView, options);
21245 });
21246
21247 })();
21248
21249
21250
21251 (function() {
21252
21253 })();
21254
21255
21256
21257 (function() {
21258
21259 })();
21260
21261
21262
21263 (function() {
21264 /**
21265 @module ember
21266 @submodule ember-handlebars
21267 */
21268
21269 var set = Ember.set, get = Ember.get;
21270
21271 /**
21272   The `Ember.Checkbox` view class renders a checkbox [input](https://developer.mozilla.org/en/HTML/Element/Input) 
21273   element. It allows for binding an Ember property (`checked`) to the status of the checkbox.
21274
21275   Example:
21276
21277   ``` handlebars
21278   {{view Ember.Checkbox checkedBinding="receiveEmail"}}
21279   ```
21280
21281   You can add a `label` tag yourself in the template where the Ember.Checkbox is being used.
21282
21283   ``` html
21284   <label>        
21285     {{view Ember.Checkbox classNames="applicaton-specific-checkbox"}}
21286     Some Title
21287   </label>
21288   ```
21289
21290
21291   The `checked` attribute of an Ember.Checkbox object should always be set
21292   through the Ember object or by interacting with its rendered element representation
21293   via the mouse, keyboard, or touch.  Updating the value of the checkbox via jQuery will
21294   result in the checked value of the object and its element losing synchronization.
21295
21296   ## Layout and LayoutName properties
21297   Because HTML `input` elements are self closing `layout` and `layoutName` properties will
21298   not be applied. See `Ember.View`'s layout section for more information.
21299
21300   @class Checkbox
21301   @namespace Ember
21302   @extends Ember.View
21303 */
21304 Ember.Checkbox = Ember.View.extend({
21305   classNames: ['ember-checkbox'],
21306
21307   tagName: 'input',
21308
21309   attributeBindings: ['type', 'checked', 'disabled', 'tabindex'],
21310
21311   type: "checkbox",
21312   checked: false,
21313   disabled: false,
21314
21315   init: function() {
21316     this._super();
21317     this.on("change", this, this._updateElementValue);
21318   },
21319
21320   _updateElementValue: function() {
21321     set(this, 'checked', this.$().prop('checked'));
21322   }
21323 });
21324
21325 })();
21326
21327
21328
21329 (function() {
21330 /**
21331 @module ember
21332 @submodule ember-handlebars
21333 */
21334
21335 var get = Ember.get, set = Ember.set;
21336
21337 /**
21338   Shared mixin used by Ember.TextField and Ember.TextArea.
21339
21340   @class TextSupport
21341   @namespace Ember
21342   @extends Ember.Mixin
21343   @private
21344 */
21345 Ember.TextSupport = Ember.Mixin.create({
21346   value: "",
21347
21348   attributeBindings: ['placeholder', 'disabled', 'maxlength', 'tabindex'],
21349   placeholder: null,
21350   disabled: false,
21351   maxlength: null,
21352
21353   insertNewline: Ember.K,
21354   cancel: Ember.K,
21355
21356   init: function() {
21357     this._super();
21358     this.on("focusOut", this, this._elementValueDidChange);
21359     this.on("change", this, this._elementValueDidChange);
21360     this.on("keyUp", this, this.interpretKeyEvents);
21361   },
21362
21363   interpretKeyEvents: function(event) {
21364     var map = Ember.TextSupport.KEY_EVENTS;
21365     var method = map[event.keyCode];
21366
21367     this._elementValueDidChange();
21368     if (method) { return this[method](event); }
21369   },
21370
21371   _elementValueDidChange: function() {
21372     set(this, 'value', this.$().val());
21373   }
21374
21375 });
21376
21377 Ember.TextSupport.KEY_EVENTS = {
21378   13: 'insertNewline',
21379   27: 'cancel'
21380 };
21381
21382 })();
21383
21384
21385
21386 (function() {
21387 /**
21388 @module ember
21389 @submodule ember-handlebars
21390 */
21391
21392 var get = Ember.get, set = Ember.set;
21393
21394 /**
21395   The `Ember.TextField` view class renders a text
21396   [input](https://developer.mozilla.org/en/HTML/Element/Input) element. It
21397   allows for binding Ember properties to the text field contents (`value`),
21398   live-updating as the user inputs text.
21399
21400   Example:
21401
21402   ``` handlebars
21403   {{view Ember.TextField valueBinding="firstName"}}
21404   ```
21405
21406   ## Layout and LayoutName properties
21407   Because HTML `input` elements are self closing `layout` and `layoutName` properties will
21408   not be applied. See `Ember.View`'s layout section for more information.
21409
21410   @class TextField
21411   @namespace Ember
21412   @extends Ember.View
21413   @uses Ember.TextSupport
21414 */
21415 Ember.TextField = Ember.View.extend(Ember.TextSupport,
21416   /** @scope Ember.TextField.prototype */ {
21417
21418   classNames: ['ember-text-field'],
21419   tagName: "input",
21420   attributeBindings: ['type', 'value', 'size'],
21421
21422   /**
21423     The value attribute of the input element. As the user inputs text, this
21424     property is updated live.
21425
21426     @property value
21427     @type String
21428     @default ""
21429   */
21430   value: "",
21431
21432   /**
21433     The type attribute of the input element.
21434
21435     @property type
21436     @type String
21437     @default "text"
21438   */
21439   type: "text",
21440
21441   /**
21442     The size of the text field in characters.
21443
21444     @property size
21445     @type String
21446     @default null
21447   */
21448   size: null
21449 });
21450
21451 })();
21452
21453
21454
21455 (function() {
21456 /**
21457 @module ember
21458 @submodule ember-handlebars
21459 */
21460
21461 var get = Ember.get, set = Ember.set;
21462
21463 /**
21464   @class Button
21465   @namespace Ember
21466   @extends Ember.View
21467   @uses Ember.TargetActionSupport
21468   @deprecated
21469 */
21470 Ember.Button = Ember.View.extend(Ember.TargetActionSupport, {
21471   classNames: ['ember-button'],
21472   classNameBindings: ['isActive'],
21473
21474   tagName: 'button',
21475
21476   propagateEvents: false,
21477
21478   attributeBindings: ['type', 'disabled', 'href', 'tabindex'],
21479
21480   /**
21481     @private
21482
21483     Overrides TargetActionSupport's targetObject computed
21484     property to use Handlebars-specific path resolution.
21485
21486     @property targetObject
21487   */
21488   targetObject: Ember.computed(function() {
21489     var target = get(this, 'target'),
21490         root = get(this, 'context'),
21491         data = get(this, 'templateData');
21492
21493     if (typeof target !== 'string') { return target; }
21494
21495     return Ember.Handlebars.getPath(root, target, { data: data });
21496   }).property('target').cacheable(),
21497
21498   // Defaults to 'button' if tagName is 'input' or 'button'
21499   type: Ember.computed(function(key, value) {
21500     var tagName = this.get('tagName');
21501     if (value !== undefined) { this._type = value; }
21502     if (this._type !== undefined) { return this._type; }
21503     if (tagName === 'input' || tagName === 'button') { return 'button'; }
21504   }).property('tagName').cacheable(),
21505
21506   disabled: false,
21507
21508   // Allow 'a' tags to act like buttons
21509   href: Ember.computed(function() {
21510     return this.get('tagName') === 'a' ? '#' : null;
21511   }).property('tagName').cacheable(),
21512
21513   mouseDown: function() {
21514     if (!get(this, 'disabled')) {
21515       set(this, 'isActive', true);
21516       this._mouseDown = true;
21517       this._mouseEntered = true;
21518     }
21519     return get(this, 'propagateEvents');
21520   },
21521
21522   mouseLeave: function() {
21523     if (this._mouseDown) {
21524       set(this, 'isActive', false);
21525       this._mouseEntered = false;
21526     }
21527   },
21528
21529   mouseEnter: function() {
21530     if (this._mouseDown) {
21531       set(this, 'isActive', true);
21532       this._mouseEntered = true;
21533     }
21534   },
21535
21536   mouseUp: function(event) {
21537     if (get(this, 'isActive')) {
21538       // Actually invoke the button's target and action.
21539       // This method comes from the Ember.TargetActionSupport mixin.
21540       this.triggerAction();
21541       set(this, 'isActive', false);
21542     }
21543
21544     this._mouseDown = false;
21545     this._mouseEntered = false;
21546     return get(this, 'propagateEvents');
21547   },
21548
21549   keyDown: function(event) {
21550     // Handle space or enter
21551     if (event.keyCode === 13 || event.keyCode === 32) {
21552       this.mouseDown();
21553     }
21554   },
21555
21556   keyUp: function(event) {
21557     // Handle space or enter
21558     if (event.keyCode === 13 || event.keyCode === 32) {
21559       this.mouseUp();
21560     }
21561   },
21562
21563   // TODO: Handle proper touch behavior.  Including should make inactive when
21564   // finger moves more than 20x outside of the edge of the button (vs mouse
21565   // which goes inactive as soon as mouse goes out of edges.)
21566
21567   touchStart: function(touch) {
21568     return this.mouseDown(touch);
21569   },
21570
21571   touchEnd: function(touch) {
21572     return this.mouseUp(touch);
21573   },
21574
21575   init: function() {
21576     Ember.deprecate("Ember.Button is deprecated and will be removed from future releases. Consider using the `{{action}}` helper.");
21577     this._super();
21578   }
21579 });
21580
21581 })();
21582
21583
21584
21585 (function() {
21586 /**
21587 @module ember
21588 @submodule ember-handlebars
21589 */
21590
21591 var get = Ember.get, set = Ember.set;
21592
21593 /**
21594   The `Ember.TextArea` view class renders a
21595   [textarea](https://developer.mozilla.org/en/HTML/Element/textarea) element.
21596   It allows for binding Ember properties to the text area contents (`value`),
21597   live-updating as the user inputs text.
21598
21599   ## Layout and LayoutName properties
21600
21601   Because HTML `textarea` elements do not contain inner HTML the `layout` and `layoutName` 
21602   properties will not be applied. See `Ember.View`'s layout section for more information.
21603
21604   @class TextArea
21605   @namespace Ember
21606   @extends Ember.View
21607   @uses Ember.TextSupport
21608 */
21609 Ember.TextArea = Ember.View.extend(Ember.TextSupport, {
21610   classNames: ['ember-text-area'],
21611
21612   tagName: "textarea",
21613   attributeBindings: ['rows', 'cols'],
21614   rows: null,
21615   cols: null,
21616
21617   _updateElementValue: Ember.observer(function() {
21618     // We do this check so cursor position doesn't get affected in IE
21619     var value = get(this, 'value'),
21620         $el = this.$();
21621     if ($el && value !== $el.val()) {
21622       $el.val(value);
21623     }
21624   }, 'value'),
21625
21626   init: function() {
21627     this._super();
21628     this.on("didInsertElement", this, this._updateElementValue);
21629   }
21630
21631 });
21632
21633 })();
21634
21635
21636
21637 (function() {
21638 /**
21639 @module ember
21640 @submodule ember-handlebars
21641 */
21642
21643 /**
21644 @class TabContainerView
21645 @namespace Ember
21646 @deprecated
21647 @extends Ember.View
21648 */
21649 Ember.TabContainerView = Ember.View.extend({
21650   init: function() {
21651     Ember.deprecate("Ember.TabContainerView is deprecated and will be removed from future releases.");
21652     this._super();
21653   }
21654 });
21655
21656 })();
21657
21658
21659
21660 (function() {
21661 /**
21662 @module ember
21663 @submodule ember-handlebars
21664 */
21665
21666 var get = Ember.get;
21667
21668 /**
21669   @class TabPaneView
21670   @namespace Ember
21671   @extends Ember.View
21672   @deprecated
21673 */
21674 Ember.TabPaneView = Ember.View.extend({
21675   tabsContainer: Ember.computed(function() {
21676     return this.nearestInstanceOf(Ember.TabContainerView);
21677   }).property().volatile(),
21678
21679   isVisible: Ember.computed(function() {
21680     return get(this, 'viewName') === get(this, 'tabsContainer.currentView');
21681   }).property('tabsContainer.currentView').volatile(),
21682
21683   init: function() {
21684     Ember.deprecate("Ember.TabPaneView is deprecated and will be removed from future releases.");
21685     this._super();
21686   }
21687 });
21688
21689 })();
21690
21691
21692
21693 (function() {
21694 /**
21695 @module ember
21696 @submodule ember-handlebars
21697 */
21698
21699 var get = Ember.get, setPath = Ember.setPath;
21700
21701 /**
21702 @class TabView
21703 @namespace Ember
21704 @extends Ember.View
21705 @deprecated
21706 */
21707 Ember.TabView = Ember.View.extend({
21708   tabsContainer: Ember.computed(function() {
21709     return this.nearestInstanceOf(Ember.TabContainerView);
21710   }).property().volatile(),
21711
21712   mouseUp: function() {
21713     setPath(this, 'tabsContainer.currentView', get(this, 'value'));
21714   },
21715
21716   init: function() {
21717     Ember.deprecate("Ember.TabView is deprecated and will be removed from future releases.");
21718     this._super();
21719   }
21720 });
21721
21722 })();
21723
21724
21725
21726 (function() {
21727
21728 })();
21729
21730
21731
21732 (function() {
21733 /*jshint eqeqeq:false */
21734
21735 /**
21736 @module ember
21737 @submodule ember-handlebars
21738 */
21739
21740 var set = Ember.set, get = Ember.get;
21741 var indexOf = Ember.EnumerableUtils.indexOf, indexesOf = Ember.EnumerableUtils.indexesOf;
21742
21743 /**
21744   The Ember.Select view class renders a
21745   [select](https://developer.mozilla.org/en/HTML/Element/select) HTML element,
21746   allowing the user to choose from a list of options. 
21747
21748   The text and `value` property of each `<option>` element within the `<select>` element
21749   are populated from the objects in the Element.Select's `content` property. The
21750   underlying data object of the selected `<option>` is stored in the
21751   Element.Select's `value` property.
21752
21753   ### `content` as an array of Strings
21754   The simplest version of an Ember.Select takes an array of strings as its `content` property.
21755   The string will be used as both the `value` property and the inner text of each `<option>`
21756   element inside the rendered `<select>`.
21757
21758   Example:
21759
21760   ``` javascript
21761   App.Names = ["Yehuda", "Tom"];
21762   ```
21763
21764   ``` handlebars
21765   {{view Ember.Select contentBinding="App.Names"}}
21766   ```
21767
21768   Would result in the following HTML:
21769
21770   ``` html
21771   <select class="ember-select">
21772     <option value="Yehuda">Yehuda</option>
21773     <option value="Tom">Tom</option>
21774   </select>
21775   ```
21776
21777   You can control which `<option>` is selected through the Ember.Select's
21778   `value` property directly or as a binding:
21779
21780   ``` javascript
21781   App.Names = Ember.Object.create({
21782     selected: 'Tom',
21783     content: ["Yehuda", "Tom"]
21784   });
21785   ```
21786
21787   ``` handlebars
21788   {{view Ember.Select
21789          contentBinding="App.controller.content"
21790          valueBinding="App.controller.selected"
21791   }}
21792   ```
21793
21794   Would result in the following HTML with the `<option>` for 'Tom' selected:
21795
21796   ``` html
21797   <select class="ember-select">
21798     <option value="Yehuda">Yehuda</option>
21799     <option value="Tom" selected="selected">Tom</option>
21800   </select>
21801   ```
21802
21803   A user interacting with the rendered `<select>` to choose "Yehuda" would update
21804   the value of `App.controller.selected` to "Yehuda". 
21805
21806   ### `content` as an Array of Objects
21807   An Ember.Select can also take an array of JavaScript or Ember objects
21808   as its `content` property.
21809
21810   When using objects you need to tell the Ember.Select which property should be
21811   accessed on each object to supply the `value` attribute of the `<option>`
21812   and which property should be used to supply the element text.
21813
21814   The `optionValuePath` option is used to specify the path on each object to
21815   the desired property for the `value` attribute.  The `optionLabelPath` 
21816   specifies the path on each object to the desired property for the 
21817   element's text. Both paths must reference each object itself as 'content':
21818
21819   ``` javascript
21820   App.Programmers = [
21821       Ember.Object.create({firstName: "Yehuda", id: 1}),
21822       Ember.Object.create({firstName: "Tom",    id: 2})
21823     ];
21824   ```
21825
21826   ``` handlebars
21827   {{view Ember.Select
21828          contentBinding="App.Programmers"
21829          optionValuePath="content.id"
21830          optionLabelPath="content.firstName"}}
21831   ```
21832
21833   Would result in the following HTML:
21834
21835   ``` html
21836   <select class="ember-select">
21837     <option value>Please Select</option>
21838     <option value="1">Yehuda</option>
21839     <option value="2">Tom</option>
21840   </select>
21841   ```
21842
21843
21844   The `value` attribute of the selected `<option>` within an Ember.Select
21845   can be bound to a property on another object by providing a
21846   `valueBinding` option:
21847
21848   ``` javascript
21849   App.Programmers = [
21850       Ember.Object.create({firstName: "Yehuda", id: 1}),
21851       Ember.Object.create({firstName: "Tom",    id: 2})
21852     ];
21853
21854   App.currentProgrammer = Ember.Object.create({
21855     id: 2
21856   });
21857   ```
21858
21859   ``` handlebars
21860   {{view Ember.Select
21861          contentBinding="App.controller.content"
21862          optionValuePath="content.id"
21863          optionLabelPath="content.firstName"
21864          valueBinding="App.currentProgrammer.id"}}
21865   ```
21866
21867   Would result in the following HTML with a selected option:
21868
21869   ``` html
21870   <select class="ember-select">
21871     <option value>Please Select</option>
21872     <option value="1">Yehuda</option>
21873     <option value="2" selected="selected">Tom</option>
21874   </select>
21875   ```
21876
21877   Interacting with the rendered element by selecting the first option
21878   ('Yehuda') will update the `id` value of `App.currentProgrammer`
21879   to match the `value` property of the newly selected `<option>`.
21880
21881   Alternatively, you can control selection through the underlying objects
21882   used to render each object providing a `selectionBinding`. When the selected
21883   `<option>` is changed, the property path provided to `selectionBinding`
21884   will be updated to match the content object of the rendered `<option>`
21885   element: 
21886
21887   ``` javascript
21888   App.controller = Ember.Object.create({
21889     selectedPerson: null,
21890     content: [
21891       Ember.Object.create({firstName: "Yehuda", id: 1}),
21892       Ember.Object.create({firstName: "Tom",    id: 2})
21893     ]
21894   });
21895   ```
21896
21897   ``` handlebars
21898   {{view Ember.Select
21899          contentBinding="App.controller.content"
21900          optionValuePath="content.id"
21901          optionLabelPath="content.firstName"
21902          selectionBinding="App.controller.selectedPerson"}}
21903   ```
21904
21905   Would result in the following HTML with a selected option:
21906
21907   ``` html
21908   <select class="ember-select">
21909     <option value>Please Select</option>
21910     <option value="1">Yehuda</option>
21911     <option value="2" selected="selected">Tom</option>
21912   </select>
21913   ```
21914
21915
21916   Interacting with the rendered element by selecting the first option
21917   ('Yehuda') will update the `selectedPerson` value of `App.controller`
21918   to match the content object of the newly selected `<option>`. In this
21919   case it is the first object in the `App.content.content` 
21920
21921   ### Supplying a Prompt
21922
21923   A `null` value for the Ember.Select's `value` or `selection` property
21924   results in there being no `<option>` with a `selected` attribute:
21925
21926   ``` javascript
21927   App.controller = Ember.Object.create({
21928     selected: null,
21929     content: [
21930       "Yehuda",
21931       "Tom"
21932     ]
21933   });
21934   ```
21935
21936   ``` handlebars
21937   {{view Ember.Select
21938          contentBinding="App.controller.content"
21939          valueBinding="App.controller.selected"
21940   }}
21941   ```
21942
21943   Would result in the following HTML:
21944
21945   ``` html
21946   <select class="ember-select">
21947     <option value="Yehuda">Yehuda</option>
21948     <option value="Tom">Tom</option>
21949   </select>
21950   ```
21951
21952   Although `App.controller.selected` is `null` and no `<option>`
21953   has a `selected` attribute the rendered HTML will display the
21954   first item as though it were selected. You can supply a string
21955   value for the Ember.Select to display when there is no selection
21956   with the `prompt` option:
21957
21958   ``` javascript
21959   App.controller = Ember.Object.create({
21960     selected: null,
21961     content: [
21962       "Yehuda",
21963       "Tom"
21964     ]
21965   });
21966   ```
21967
21968   ``` handlebars
21969   {{view Ember.Select
21970          contentBinding="App.controller.content"
21971          valueBinding="App.controller.selected"
21972          prompt="Please select a name"
21973   }}
21974   ```
21975
21976   Would result in the following HTML:
21977
21978   ``` html
21979   <select class="ember-select">
21980     <option>Please select a name</option>
21981     <option value="Yehuda">Yehuda</option>
21982     <option value="Tom">Tom</option>
21983   </select>
21984   ```
21985
21986   @class Select
21987   @namespace Ember
21988   @extends Ember.View
21989 */
21990 Ember.Select = Ember.View.extend(
21991   /** @scope Ember.Select.prototype */ {
21992
21993   tagName: 'select',
21994   classNames: ['ember-select'],
21995   defaultTemplate: Ember.Handlebars.compile('{{#if view.prompt}}<option value>{{view.prompt}}</option>{{/if}}{{#each view.content}}{{view Ember.SelectOption contentBinding="this"}}{{/each}}'),
21996   attributeBindings: ['multiple', 'tabindex'],
21997
21998   /**
21999     The `multiple` attribute of the select element. Indicates whether multiple
22000     options can be selected.
22001
22002     @property multiple
22003     @type Boolean
22004     @default false
22005   */
22006   multiple: false,
22007
22008   /**
22009     The list of options.
22010
22011     If `optionLabelPath` and `optionValuePath` are not overridden, this should
22012     be a list of strings, which will serve simultaneously as labels and values.
22013
22014     Otherwise, this should be a list of objects. For instance:
22015
22016         content: Ember.A([
22017             { id: 1, firstName: 'Yehuda' },
22018             { id: 2, firstName: 'Tom' }
22019           ]),
22020         optionLabelPath: 'content.firstName',
22021         optionValuePath: 'content.id'
22022
22023     @property content
22024     @type Array
22025     @default null
22026   */
22027   content: null,
22028
22029   /**
22030     When `multiple` is false, the element of `content` that is currently
22031     selected, if any.
22032
22033     When `multiple` is true, an array of such elements.
22034
22035     @property selection
22036     @type Object or Array
22037     @default null
22038   */
22039   selection: null,
22040
22041   /**
22042     In single selection mode (when `multiple` is false), value can be used to get
22043     the current selection's value or set the selection by it's value.
22044
22045     It is not currently supported in multiple selection mode.
22046
22047     @property value
22048     @type String
22049     @default null
22050   */
22051   value: Ember.computed(function(key, value) {
22052     if (arguments.length === 2) { return value; }
22053
22054     var valuePath = get(this, 'optionValuePath').replace(/^content\.?/, '');
22055     return valuePath ? get(this, 'selection.' + valuePath) : get(this, 'selection');
22056   }).property('selection').cacheable(),
22057
22058   /**
22059     If given, a top-most dummy option will be rendered to serve as a user
22060     prompt.
22061
22062     @property prompt
22063     @type String
22064     @default null
22065   */
22066   prompt: null,
22067
22068   /**
22069     The path of the option labels. See `content`.
22070
22071     @property optionLabelPath
22072     @type String
22073     @default 'content'
22074   */
22075   optionLabelPath: 'content',
22076
22077   /**
22078     The path of the option values. See `content`.
22079
22080     @property optionValuePath
22081     @type String
22082     @default 'content'
22083   */
22084   optionValuePath: 'content',
22085
22086   _change: function() {
22087     if (get(this, 'multiple')) {
22088       this._changeMultiple();
22089     } else {
22090       this._changeSingle();
22091     }
22092   },
22093
22094   selectionDidChange: Ember.observer(function() {
22095     var selection = get(this, 'selection'),
22096         isArray = Ember.isArray(selection);
22097     if (get(this, 'multiple')) {
22098       if (!isArray) {
22099         set(this, 'selection', Ember.A([selection]));
22100         return;
22101       }
22102       this._selectionDidChangeMultiple();
22103     } else {
22104       this._selectionDidChangeSingle();
22105     }
22106   }, 'selection'),
22107
22108   valueDidChange: Ember.observer(function() {
22109     var content = get(this, 'content'),
22110         value = get(this, 'value'),
22111         valuePath = get(this, 'optionValuePath').replace(/^content\.?/, ''),
22112         selectedValue = (valuePath ? get(this, 'selection.' + valuePath) : get(this, 'selection')),
22113         selection;
22114
22115     if (value !== selectedValue) {
22116       selection = content.find(function(obj) {
22117         return value === (valuePath ? get(obj, valuePath) : obj);
22118       });
22119
22120       this.set('selection', selection);
22121     }
22122   }, 'value'),
22123
22124
22125   _triggerChange: function() {
22126     var selection = get(this, 'selection');
22127     var value = get(this, 'value');
22128
22129     if (selection) { this.selectionDidChange(); }
22130     if (value) { this.valueDidChange(); }
22131
22132     this._change();
22133   },
22134
22135   _changeSingle: function() {
22136     var selectedIndex = this.$()[0].selectedIndex,
22137         content = get(this, 'content'),
22138         prompt = get(this, 'prompt');
22139
22140     if (!content) { return; }
22141     if (prompt && selectedIndex === 0) { set(this, 'selection', null); return; }
22142
22143     if (prompt) { selectedIndex -= 1; }
22144     set(this, 'selection', content.objectAt(selectedIndex));
22145   },
22146
22147   _changeMultiple: function() {
22148     var options = this.$('option:selected'),
22149         prompt = get(this, 'prompt'),
22150         offset = prompt ? 1 : 0,
22151         content = get(this, 'content');
22152
22153     if (!content){ return; }
22154     if (options) {
22155       var selectedIndexes = options.map(function(){
22156         return this.index - offset;
22157       }).toArray();
22158       set(this, 'selection', content.objectsAt(selectedIndexes));
22159     }
22160   },
22161
22162   _selectionDidChangeSingle: function() {
22163     var el = this.get('element');
22164     if (!el) { return; }
22165
22166     var content = get(this, 'content'),
22167         selection = get(this, 'selection'),
22168         selectionIndex = content ? indexOf(content, selection) : -1,
22169         prompt = get(this, 'prompt');
22170
22171     if (prompt) { selectionIndex += 1; }
22172     if (el) { el.selectedIndex = selectionIndex; }
22173   },
22174
22175   _selectionDidChangeMultiple: function() {
22176     var content = get(this, 'content'),
22177         selection = get(this, 'selection'),
22178         selectedIndexes = content ? indexesOf(content, selection) : [-1],
22179         prompt = get(this, 'prompt'),
22180         offset = prompt ? 1 : 0,
22181         options = this.$('option'),
22182         adjusted;
22183
22184     if (options) {
22185       options.each(function() {
22186         adjusted = this.index > -1 ? this.index - offset : -1;
22187         this.selected = indexOf(selectedIndexes, adjusted) > -1;
22188       });
22189     }
22190   },
22191
22192   init: function() {
22193     this._super();
22194     this.on("didInsertElement", this, this._triggerChange);
22195     this.on("change", this, this._change);
22196   }
22197 });
22198
22199 Ember.SelectOption = Ember.View.extend({
22200   tagName: 'option',
22201   attributeBindings: ['value', 'selected'],
22202
22203   defaultTemplate: function(context, options) {
22204     options = { data: options.data, hash: {} };
22205     Ember.Handlebars.helpers.bind.call(context, "view.label", options);
22206   },
22207
22208   init: function() {
22209     this.labelPathDidChange();
22210     this.valuePathDidChange();
22211
22212     this._super();
22213   },
22214
22215   selected: Ember.computed(function() {
22216     var content = get(this, 'content'),
22217         selection = get(this, 'parentView.selection');
22218     if (get(this, 'parentView.multiple')) {
22219       return selection && indexOf(selection, content.valueOf()) > -1;
22220     } else {
22221       // Primitives get passed through bindings as objects... since
22222       // `new Number(4) !== 4`, we use `==` below
22223       return content == selection;
22224     }
22225   }).property('content', 'parentView.selection').volatile(),
22226
22227   labelPathDidChange: Ember.observer(function() {
22228     var labelPath = get(this, 'parentView.optionLabelPath');
22229
22230     if (!labelPath) { return; }
22231
22232     Ember.defineProperty(this, 'label', Ember.computed(function() {
22233       return get(this, labelPath);
22234     }).property(labelPath).cacheable());
22235   }, 'parentView.optionLabelPath'),
22236
22237   valuePathDidChange: Ember.observer(function() {
22238     var valuePath = get(this, 'parentView.optionValuePath');
22239
22240     if (!valuePath) { return; }
22241
22242     Ember.defineProperty(this, 'value', Ember.computed(function() {
22243       return get(this, valuePath);
22244     }).property(valuePath).cacheable());
22245   }, 'parentView.optionValuePath')
22246 });
22247
22248 })();
22249
22250
22251
22252 (function() {
22253
22254 })();
22255
22256
22257
22258 (function() {
22259 /*globals Handlebars */
22260 /**
22261 @module ember
22262 @submodule ember-handlebars
22263 */
22264
22265 /**
22266   @private
22267
22268   Find templates stored in the head tag as script tags and make them available
22269   to Ember.CoreView in the global Ember.TEMPLATES object. This will be run as as
22270   jQuery DOM-ready callback.
22271
22272   Script tags with "text/x-handlebars" will be compiled
22273   with Ember's Handlebars and are suitable for use as a view's template.
22274   Those with type="text/x-raw-handlebars" will be compiled with regular
22275   Handlebars and are suitable for use in views' computed properties.
22276
22277   @method bootstrap
22278   @for Ember.Handlebars
22279   @static
22280   @param ctx
22281 */
22282 Ember.Handlebars.bootstrap = function(ctx) {
22283   var selectors = 'script[type="text/x-handlebars"], script[type="text/x-raw-handlebars"]';
22284
22285   Ember.$(selectors, ctx)
22286     .each(function() {
22287     // Get a reference to the script tag
22288     var script = Ember.$(this),
22289         type   = script.attr('type');
22290
22291     var compile = (script.attr('type') === 'text/x-raw-handlebars') ?
22292                   Ember.$.proxy(Handlebars.compile, Handlebars) :
22293                   Ember.$.proxy(Ember.Handlebars.compile, Ember.Handlebars),
22294       // Get the name of the script, used by Ember.View's templateName property.
22295       // First look for data-template-name attribute, then fall back to its
22296       // id if no name is found.
22297       templateName = script.attr('data-template-name') || script.attr('id') || 'application',
22298       template = compile(script.html());
22299
22300     // For templates which have a name, we save them and then remove them from the DOM
22301     Ember.TEMPLATES[templateName] = template;
22302
22303     // Remove script tag from DOM
22304     script.remove();
22305   });
22306 };
22307
22308 function bootstrap() {
22309   Ember.Handlebars.bootstrap( Ember.$(document) );
22310 }
22311
22312 /*
22313   We tie this to application.load to ensure that we've at least
22314   attempted to bootstrap at the point that the application is loaded.
22315
22316   We also tie this to document ready since we're guaranteed that all
22317   the inline templates are present at this point.
22318
22319   There's no harm to running this twice, since we remove the templates
22320   from the DOM after processing.
22321 */
22322
22323 Ember.onLoad('application', bootstrap);
22324
22325 })();
22326
22327
22328
22329 (function() {
22330 /**
22331 Ember Handlebars
22332
22333 @module ember
22334 @submodule ember-handlebars
22335 @requires ember-views
22336 */
22337
22338 })();
22339
22340 // Version: v1.0.pre-160-g7d62790
22341 // Last commit: 7d62790 (2012-09-26 15:59:36 -0700)
22342
22343
22344 (function() {
22345 /**
22346 Ember
22347
22348 @module ember
22349 */
22350
22351 })();
22352