Add Intel copyright header.
[profile/ivi/cowhide.git] / examples / calf / lib / ember-1.0.0-pre.2.js
1 // Version: v1.0.0-pre.2-1-gd1a2e84
2 // Last commit: d1a2e84 (2012-10-25 13:51:08 -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.0-pre.2-1-gd1a2e84
144 // Last commit: d1a2e84 (2012-10-25 13:51:08 -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.0-pre.2
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 // Default imports, exports and lookup to the global object;
183 var imports = Ember.imports = Ember.imports || this;
184 var exports = Ember.exports = Ember.exports || this;
185 var lookup  = Ember.lookup  = Ember.lookup  || this;
186
187 // aliases needed to keep minifiers from removing the global context
188 exports.Em = exports.Ember = Em = Ember;
189
190 // Make sure these are set whether Ember was already defined or not
191
192 Ember.isNamespace = true;
193
194 Ember.toString = function() { return "Ember"; };
195
196
197 /**
198   @property VERSION
199   @type String
200   @default '1.0.0-pre.2'
201   @final
202 */
203 Ember.VERSION = '1.0.0-pre.2';
204
205 /**
206   Standard environmental variables.  You can define these in a global `ENV`
207   variable before loading Ember to control various configuration
208   settings.
209
210   @property ENV
211   @type Hash
212 */
213 Ember.ENV = Ember.ENV || ('undefined' === typeof ENV ? {} : ENV);
214
215 Ember.config = Ember.config || {};
216
217 // ..........................................................
218 // BOOTSTRAP
219 //
220
221 /**
222   Determines whether Ember should enhances some built-in object
223   prototypes to provide a more friendly API.  If enabled, a few methods
224   will be added to Function, String, and Array.  Object.prototype will not be
225   enhanced, which is the one that causes most trouble for people.
226
227   In general we recommend leaving this option set to true since it rarely
228   conflicts with other code.  If you need to turn it off however, you can
229   define an ENV.EXTEND_PROTOTYPES config to disable it.
230
231   @property EXTEND_PROTOTYPES
232   @type Boolean
233   @default true
234 */
235 Ember.EXTEND_PROTOTYPES = Ember.ENV.EXTEND_PROTOTYPES;
236
237 if (typeof Ember.EXTEND_PROTOTYPES === 'undefined') {
238   Ember.EXTEND_PROTOTYPES = true;
239 }
240
241 /**
242   Determines whether Ember logs a full stack trace during deprecation warnings
243
244   @property LOG_STACKTRACE_ON_DEPRECATION
245   @type Boolean
246   @default true
247 */
248 Ember.LOG_STACKTRACE_ON_DEPRECATION = (Ember.ENV.LOG_STACKTRACE_ON_DEPRECATION !== false);
249
250 /**
251   Determines whether Ember should add ECMAScript 5 shims to older browsers.
252
253   @property SHIM_ES5
254   @type Boolean
255   @default Ember.EXTEND_PROTOTYPES
256 */
257 Ember.SHIM_ES5 = (Ember.ENV.SHIM_ES5 === false) ? false : Ember.EXTEND_PROTOTYPES;
258
259 /**
260   Empty function.  Useful for some operations.
261
262   @method K
263   @private
264   @return {Object}
265 */
266 Ember.K = function() { return this; };
267
268
269 // Stub out the methods defined by the ember-debug package in case it's not loaded
270
271 if ('undefined' === typeof Ember.assert) { Ember.assert = Ember.K; }
272 if ('undefined' === typeof Ember.warn) { Ember.warn = Ember.K; }
273 if ('undefined' === typeof Ember.deprecate) { Ember.deprecate = Ember.K; }
274 if ('undefined' === typeof Ember.deprecateFunc) {
275   Ember.deprecateFunc = function(_, func) { return func; };
276 }
277
278 // These are deprecated but still supported
279
280 if ('undefined' === typeof ember_assert) { exports.ember_assert = Ember.K; }
281 if ('undefined' === typeof ember_warn) { exports.ember_warn = Ember.K; }
282 if ('undefined' === typeof ember_deprecate) { exports.ember_deprecate = Ember.K; }
283 if ('undefined' === typeof ember_deprecateFunc) {
284   exports.ember_deprecateFunc = function(_, func) { return func; };
285 }
286
287 /**
288   Previously we used `Ember.$.uuid`, however `$.uuid` has been removed from jQuery master.
289   We'll just bootstrap our own uuid now.
290
291   @property uuid
292   @type Number
293   @private
294 */
295 Ember.uuid = 0;
296
297 // ..........................................................
298 // LOGGER
299 //
300
301 /**
302   Inside Ember-Metal, simply uses the imports.console object.
303   Override this to provide more robust logging functionality.
304
305   @class Logger
306   @namespace Ember
307 */
308 Ember.Logger = imports.console || { log: Ember.K, warn: Ember.K, error: Ember.K, info: Ember.K, debug: Ember.K };
309
310
311 // ..........................................................
312 // ERROR HANDLING
313 //
314
315 /**
316   A function may be assigned to `Ember.onerror` to be called when Ember internals encounter an error.
317   This is useful for specialized error handling and reporting code.
318
319   @event onerror
320   @for Ember
321   @param {Exception} error the error object
322 */
323 Ember.onerror = null;
324
325 /**
326   @private
327
328   Wrap code block in a try/catch if {{#crossLink "Ember/onerror"}}{{/crossLink}} is set.
329
330   @method handleErrors
331   @for Ember
332   @param {Function} func
333   @param [context]
334 */
335 Ember.handleErrors = function(func, context) {
336   // Unfortunately in some browsers we lose the backtrace if we rethrow the existing error,
337   // so in the event that we don't have an `onerror` handler we don't wrap in a try/catch
338   if ('function' === typeof Ember.onerror) {
339     try {
340       return func.apply(context || this);
341     } catch (error) {
342       Ember.onerror(error);
343     }
344   } else {
345     return func.apply(context || this);
346   }
347 };
348
349 })();
350
351
352
353 (function() {
354 /**
355   The purpose of the Ember Instrumentation module is
356   to provide efficient, general-purpose instrumentation
357   for Ember.
358
359   Subscribe to a listener by using `Ember.subscribe`:
360
361       Ember.subscribe("render", {
362         before: function(name, timestamp, payload) {
363
364         },
365
366         after: function(name, timestamp, payload) {
367
368         }
369       });
370
371   If you return a value from the `before` callback, that same
372   value will be passed as a fourth parameter to the `after`
373   callback.
374
375   Instrument a block of code by using `Ember.instrument`:
376
377       Ember.instrument("render.handlebars", payload, function() {
378         // rendering logic
379       }, binding);
380
381   Event names passed to `Ember.instrument` are namespaced
382   by periods, from more general to more specific. Subscribers
383   can listen for events by whatever level of granularity they
384   are interested in.
385
386   In the above example, the event is `render.handlebars`,
387   and the subscriber listened for all events beginning with
388   `render`. It would receive callbacks for events named
389   `render`, `render.handlebars`, `render.container`, or
390   even `render.handlebars.layout`.
391
392   @class Instrumentation
393   @namespace Ember
394   @static
395 */
396 Ember.Instrumentation = {};
397
398 var subscribers = [], cache = {};
399
400 var populateListeners = function(name) {
401   var listeners = [], subscriber;
402
403   for (var i=0, l=subscribers.length; i<l; i++) {
404     subscriber = subscribers[i];
405     if (subscriber.regex.test(name)) {
406       listeners.push(subscriber.object);
407     }
408   }
409
410   cache[name] = listeners;
411   return listeners;
412 };
413
414 var time = (function() {
415         var perf = window.performance || {};
416         var fn = perf.now || perf.mozNow || perf.webkitNow || perf.msNow || perf.oNow;
417         // fn.bind will be available in all the browsers that support the advanced window.performance... ;-)
418         return fn ? fn.bind(perf) : function() { return +new Date(); };
419 })();
420
421
422 Ember.Instrumentation.instrument = function(name, payload, callback, binding) {
423   var listeners = cache[name];
424
425   if (!listeners) {
426     listeners = populateListeners(name);
427   }
428
429   if (listeners.length === 0) { return callback.call(binding); }
430
431   var beforeValues = [], listener, ret, i, l;
432
433   try {
434     for (i=0, l=listeners.length; i<l; i++) {
435       listener = listeners[i];
436       beforeValues[i] = listener.before(name, time(), payload);
437     }
438
439     ret = callback.call(binding);
440   } catch(e) {
441     payload = payload || {};
442     payload.exception = e;
443   } finally {
444     for (i=0, l=listeners.length; i<l; i++) {
445       listener = listeners[i];
446       listener.after(name, time(), payload, beforeValues[i]);
447     }
448   }
449
450   return ret;
451 };
452
453 Ember.Instrumentation.subscribe = function(pattern, object) {
454   var paths = pattern.split("."), path, regex = [];
455
456   for (var i=0, l=paths.length; i<l; i++) {
457     path = paths[i];
458     if (path === "*") {
459       regex.push("[^\\.]*");
460     } else {
461       regex.push(path);
462     }
463   }
464
465   regex = regex.join("\\.");
466   regex = regex + "(\\..*)?";
467
468   var subscriber = {
469     pattern: pattern,
470     regex: new RegExp("^" + regex + "$"),
471     object: object
472   };
473
474   subscribers.push(subscriber);
475   cache = {};
476
477   return subscriber;
478 };
479
480 Ember.Instrumentation.unsubscribe = function(subscriber) {
481   var index;
482
483   for (var i=0, l=subscribers.length; i<l; i++) {
484     if (subscribers[i] === subscriber) {
485       index = i;
486     }
487   }
488
489   subscribers.splice(index, 1);
490   cache = {};
491 };
492
493 Ember.Instrumentation.reset = function() {
494   subscribers = [];
495   cache = {};
496 };
497
498 Ember.instrument = Ember.Instrumentation.instrument;
499 Ember.subscribe = Ember.Instrumentation.subscribe;
500
501 })();
502
503
504
505 (function() {
506 /*jshint newcap:false*/
507
508 /**
509 @module ember-metal
510 */
511
512 // NOTE: There is a bug in jshint that doesn't recognize `Object()` without `new`
513 // as being ok unless both `newcap:false` and not `use strict`.
514 // https://github.com/jshint/jshint/issues/392
515
516 // Testing this is not ideal, but we want to use native functions
517 // if available, but not to use versions created by libraries like Prototype
518 var isNativeFunc = function(func) {
519   // This should probably work in all browsers likely to have ES5 array methods
520   return func && Function.prototype.toString.call(func).indexOf('[native code]') > -1;
521 };
522
523 // From: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/map
524 var arrayMap = isNativeFunc(Array.prototype.map) ? Array.prototype.map : function(fun /*, thisp */) {
525   //"use strict";
526
527   if (this === void 0 || this === null) {
528     throw new TypeError();
529   }
530
531   var t = Object(this);
532   var len = t.length >>> 0;
533   if (typeof fun !== "function") {
534     throw new TypeError();
535   }
536
537   var res = new Array(len);
538   var thisp = arguments[1];
539   for (var i = 0; i < len; i++) {
540     if (i in t) {
541       res[i] = fun.call(thisp, t[i], i, t);
542     }
543   }
544
545   return res;
546 };
547
548 // From: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/foreach
549 var arrayForEach = isNativeFunc(Array.prototype.forEach) ? Array.prototype.forEach : function(fun /*, thisp */) {
550   //"use strict";
551
552   if (this === void 0 || this === null) {
553     throw new TypeError();
554   }
555
556   var t = Object(this);
557   var len = t.length >>> 0;
558   if (typeof fun !== "function") {
559     throw new TypeError();
560   }
561
562   var thisp = arguments[1];
563   for (var i = 0; i < len; i++) {
564     if (i in t) {
565       fun.call(thisp, t[i], i, t);
566     }
567   }
568 };
569
570 var arrayIndexOf = isNativeFunc(Array.prototype.indexOf) ? Array.prototype.indexOf : function (obj, fromIndex) {
571   if (fromIndex === null || fromIndex === undefined) { fromIndex = 0; }
572   else if (fromIndex < 0) { fromIndex = Math.max(0, this.length + fromIndex); }
573   for (var i = fromIndex, j = this.length; i < j; i++) {
574     if (this[i] === obj) { return i; }
575   }
576   return -1;
577 };
578
579 Ember.ArrayPolyfills = {
580   map: arrayMap,
581   forEach: arrayForEach,
582   indexOf: arrayIndexOf
583 };
584
585 var utils = Ember.EnumerableUtils = {
586   map: function(obj, callback, thisArg) {
587     return obj.map ? obj.map.call(obj, callback, thisArg) : arrayMap.call(obj, callback, thisArg);
588   },
589
590   forEach: function(obj, callback, thisArg) {
591     return obj.forEach ? obj.forEach.call(obj, callback, thisArg) : arrayForEach.call(obj, callback, thisArg);
592   },
593
594   indexOf: function(obj, element, index) {
595     return obj.indexOf ? obj.indexOf.call(obj, element, index) : arrayIndexOf.call(obj, element, index);
596   },
597
598   indexesOf: function(obj, elements) {
599     return elements === undefined ? [] : utils.map(elements, function(item) {
600       return utils.indexOf(obj, item);
601     });
602   },
603
604   removeObject: function(array, item) {
605     var index = utils.indexOf(array, item);
606     if (index !== -1) { array.splice(index, 1); }
607   },
608
609   replace: function(array, idx, amt, objects) {
610     if (array.replace) {
611       return array.replace(idx, amt, objects);
612     } else {
613       var args = Array.prototype.concat.apply([idx, amt], objects);
614       return array.splice.apply(array, args);
615     }
616   }
617 };
618
619
620 if (Ember.SHIM_ES5) {
621   if (!Array.prototype.map) {
622     Array.prototype.map = arrayMap;
623   }
624
625   if (!Array.prototype.forEach) {
626     Array.prototype.forEach = arrayForEach;
627   }
628
629   if (!Array.prototype.indexOf) {
630     Array.prototype.indexOf = arrayIndexOf;
631   }
632 }
633
634 })();
635
636
637
638 (function() {
639 /*globals Node */
640 /**
641 @module ember-metal
642 */
643
644 /**
645   Platform specific methods and feature detectors needed by the framework.
646
647   @class platform
648   @namespace Ember
649   @static
650 */
651 var platform = Ember.platform = {};
652
653
654 /**
655   Identical to Object.create().  Implements if not available natively.
656   @method create
657   @for Ember
658 */
659 Ember.create = Object.create;
660
661 if (!Ember.create) {
662   var K = function() {};
663
664   Ember.create = function(obj, props) {
665     K.prototype = obj;
666     obj = new K();
667     if (props) {
668       K.prototype = obj;
669       for (var prop in props) {
670         K.prototype[prop] = props[prop].value;
671       }
672       obj = new K();
673     }
674     K.prototype = null;
675
676     return obj;
677   };
678
679   Ember.create.isSimulated = true;
680 }
681
682 var defineProperty = Object.defineProperty;
683 var canRedefineProperties, canDefinePropertyOnDOM;
684
685 // Catch IE8 where Object.defineProperty exists but only works on DOM elements
686 if (defineProperty) {
687   try {
688     defineProperty({}, 'a',{get:function(){}});
689   } catch (e) {
690     defineProperty = null;
691   }
692 }
693
694 if (defineProperty) {
695   // Detects a bug in Android <3.2 where you cannot redefine a property using
696   // Object.defineProperty once accessors have already been set.
697   canRedefineProperties = (function() {
698     var obj = {};
699
700     defineProperty(obj, 'a', {
701       configurable: true,
702       enumerable: true,
703       get: function() { },
704       set: function() { }
705     });
706
707     defineProperty(obj, 'a', {
708       configurable: true,
709       enumerable: true,
710       writable: true,
711       value: true
712     });
713
714     return obj.a === true;
715   })();
716
717   // This is for Safari 5.0, which supports Object.defineProperty, but not
718   // on DOM nodes.
719   canDefinePropertyOnDOM = (function(){
720     try {
721       defineProperty(document.createElement('div'), 'definePropertyOnDOM', {});
722       return true;
723     } catch(e) { }
724
725     return false;
726   })();
727
728   if (!canRedefineProperties) {
729     defineProperty = null;
730   } else if (!canDefinePropertyOnDOM) {
731     defineProperty = function(obj, keyName, desc){
732       var isNode;
733
734       if (typeof Node === "object") {
735         isNode = obj instanceof Node;
736       } else {
737         isNode = typeof obj === "object" && typeof obj.nodeType === "number" && typeof obj.nodeName === "string";
738       }
739
740       if (isNode) {
741         // TODO: Should we have a warning here?
742         return (obj[keyName] = desc.value);
743       } else {
744         return Object.defineProperty(obj, keyName, desc);
745       }
746     };
747   }
748 }
749
750 /**
751 @class platform
752 @namespace Ember
753 */
754
755 /**
756   Identical to Object.defineProperty().  Implements as much functionality
757   as possible if not available natively.
758
759   @method defineProperty
760   @param {Object} obj The object to modify
761   @param {String} keyName property name to modify
762   @param {Object} desc descriptor hash
763   @return {void}
764 */
765 platform.defineProperty = defineProperty;
766
767 /**
768   Set to true if the platform supports native getters and setters.
769
770   @property hasPropertyAccessors
771   @final
772 */
773 platform.hasPropertyAccessors = true;
774
775 if (!platform.defineProperty) {
776   platform.hasPropertyAccessors = false;
777
778   platform.defineProperty = function(obj, keyName, desc) {
779     if (!desc.get) { obj[keyName] = desc.value; }
780   };
781
782   platform.defineProperty.isSimulated = true;
783 }
784
785 if (Ember.ENV.MANDATORY_SETTER && !platform.hasPropertyAccessors) {
786   Ember.ENV.MANDATORY_SETTER = false;
787 }
788
789 })();
790
791
792
793 (function() {
794 /**
795 @module ember-metal
796 */
797
798 var o_defineProperty = Ember.platform.defineProperty,
799     o_create = Ember.create,
800     // Used for guid generation...
801     GUID_KEY = '__ember'+ (+ new Date()),
802     uuid         = 0,
803     numberCache  = [],
804     stringCache  = {};
805
806 var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER;
807
808 /**
809   @private
810
811   A unique key used to assign guids and other private metadata to objects.
812   If you inspect an object in your browser debugger you will often see these.
813   They can be safely ignored.
814
815   On browsers that support it, these properties are added with enumeration
816   disabled so they won't show up when you iterate over your properties.
817
818   @property GUID_KEY
819   @for Ember
820   @type String
821   @final
822 */
823 Ember.GUID_KEY = GUID_KEY;
824
825 var GUID_DESC = {
826   writable:    false,
827   configurable: false,
828   enumerable:  false,
829   value: null
830 };
831
832 /**
833   @private
834
835   Generates a new guid, optionally saving the guid to the object that you
836   pass in.  You will rarely need to use this method.  Instead you should
837   call Ember.guidFor(obj), which return an existing guid if available.
838
839   @method generateGuid
840   @for Ember
841   @param {Object} [obj] Object the guid will be used for.  If passed in, the guid will
842     be saved on the object and reused whenever you pass the same object
843     again.
844
845     If no object is passed, just generate a new guid.
846
847   @param {String} [prefix] Prefix to place in front of the guid.  Useful when you want to
848     separate the guid into separate namespaces.
849
850   @return {String} the guid
851 */
852 Ember.generateGuid = function generateGuid(obj, prefix) {
853   if (!prefix) prefix = 'ember';
854   var ret = (prefix + (uuid++));
855   if (obj) {
856     GUID_DESC.value = ret;
857     o_defineProperty(obj, GUID_KEY, GUID_DESC);
858   }
859   return ret ;
860 };
861
862 /**
863   @private
864
865   Returns a unique id for the object.  If the object does not yet have
866   a guid, one will be assigned to it.  You can call this on any object,
867   Ember.Object-based or not, but be aware that it will add a _guid property.
868
869   You can also use this method on DOM Element objects.
870
871   @method guidFor
872   @for Ember
873   @param obj {Object} any object, string, number, Element, or primitive
874   @return {String} the unique guid for this instance.
875 */
876 Ember.guidFor = function guidFor(obj) {
877
878   // special cases where we don't want to add a key to object
879   if (obj === undefined) return "(undefined)";
880   if (obj === null) return "(null)";
881
882   var cache, ret;
883   var type = typeof obj;
884
885   // Don't allow prototype changes to String etc. to change the guidFor
886   switch(type) {
887     case 'number':
888       ret = numberCache[obj];
889       if (!ret) ret = numberCache[obj] = 'nu'+obj;
890       return ret;
891
892     case 'string':
893       ret = stringCache[obj];
894       if (!ret) ret = stringCache[obj] = 'st'+(uuid++);
895       return ret;
896
897     case 'boolean':
898       return obj ? '(true)' : '(false)';
899
900     default:
901       if (obj[GUID_KEY]) return obj[GUID_KEY];
902       if (obj === Object) return '(Object)';
903       if (obj === Array)  return '(Array)';
904       ret = 'ember'+(uuid++);
905       GUID_DESC.value = ret;
906       o_defineProperty(obj, GUID_KEY, GUID_DESC);
907       return ret;
908   }
909 };
910
911 // ..........................................................
912 // META
913 //
914
915 var META_DESC = {
916   writable:    true,
917   configurable: false,
918   enumerable:  false,
919   value: null
920 };
921
922 var META_KEY = Ember.GUID_KEY+'_meta';
923
924 /**
925   The key used to store meta information on object for property observing.
926
927   @property META_KEY
928   @for Ember
929   @private
930   @final
931   @type String
932 */
933 Ember.META_KEY = META_KEY;
934
935 // Placeholder for non-writable metas.
936 var EMPTY_META = {
937   descs: {},
938   watching: {}
939 };
940
941 if (MANDATORY_SETTER) { EMPTY_META.values = {}; }
942
943 Ember.EMPTY_META = EMPTY_META;
944
945 if (Object.freeze) Object.freeze(EMPTY_META);
946
947 var isDefinePropertySimulated = Ember.platform.defineProperty.isSimulated;
948
949 function Meta(obj) {
950   this.descs = {};
951   this.watching = {};
952   this.cache = {};
953   this.source = obj;
954 }
955
956 if (isDefinePropertySimulated) {
957   // on platforms that don't support enumerable false
958   // make meta fail jQuery.isPlainObject() to hide from
959   // jQuery.extend() by having a property that fails
960   // hasOwnProperty check.
961   Meta.prototype.__preventPlainObject__ = true;
962 }
963
964 /**
965   Retrieves the meta hash for an object.  If 'writable' is true ensures the
966   hash is writable for this object as well.
967
968   The meta object contains information about computed property descriptors as
969   well as any watched properties and other information.  You generally will
970   not access this information directly but instead work with higher level
971   methods that manipulate this hash indirectly.
972
973   @method meta
974   @for Ember
975   @private
976
977   @param {Object} obj The object to retrieve meta for
978
979   @param {Boolean} [writable=true] Pass false if you do not intend to modify
980     the meta hash, allowing the method to avoid making an unnecessary copy.
981
982   @return {Hash}
983 */
984 Ember.meta = function meta(obj, writable) {
985
986   var ret = obj[META_KEY];
987   if (writable===false) return ret || EMPTY_META;
988
989   if (!ret) {
990     if (!isDefinePropertySimulated) o_defineProperty(obj, META_KEY, META_DESC);
991
992     ret = new Meta(obj);
993
994     if (MANDATORY_SETTER) { ret.values = {}; }
995
996     obj[META_KEY] = ret;
997
998     // make sure we don't accidentally try to create constructor like desc
999     ret.descs.constructor = null;
1000
1001   } else if (ret.source !== obj) {
1002     if (!isDefinePropertySimulated) o_defineProperty(obj, META_KEY, META_DESC);
1003
1004     ret = o_create(ret);
1005     ret.descs    = o_create(ret.descs);
1006     ret.watching = o_create(ret.watching);
1007     ret.cache    = {};
1008     ret.source   = obj;
1009
1010     if (MANDATORY_SETTER) { ret.values = o_create(ret.values); }
1011
1012     obj[META_KEY] = ret;
1013   }
1014   return ret;
1015 };
1016
1017 Ember.getMeta = function getMeta(obj, property) {
1018   var meta = Ember.meta(obj, false);
1019   return meta[property];
1020 };
1021
1022 Ember.setMeta = function setMeta(obj, property, value) {
1023   var meta = Ember.meta(obj, true);
1024   meta[property] = value;
1025   return value;
1026 };
1027
1028 /**
1029   @private
1030
1031   In order to store defaults for a class, a prototype may need to create
1032   a default meta object, which will be inherited by any objects instantiated
1033   from the class's constructor.
1034
1035   However, the properties of that meta object are only shallow-cloned,
1036   so if a property is a hash (like the event system's `listeners` hash),
1037   it will by default be shared across all instances of that class.
1038
1039   This method allows extensions to deeply clone a series of nested hashes or
1040   other complex objects. For instance, the event system might pass
1041   ['listeners', 'foo:change', 'ember157'] to `prepareMetaPath`, which will
1042   walk down the keys provided.
1043
1044   For each key, if the key does not exist, it is created. If it already
1045   exists and it was inherited from its constructor, the constructor's
1046   key is cloned.
1047
1048   You can also pass false for `writable`, which will simply return
1049   undefined if `prepareMetaPath` discovers any part of the path that
1050   shared or undefined.
1051
1052   @method metaPath
1053   @for Ember
1054   @param {Object} obj The object whose meta we are examining
1055   @param {Array} path An array of keys to walk down
1056   @param {Boolean} writable whether or not to create a new meta
1057     (or meta property) if one does not already exist or if it's
1058     shared with its constructor
1059 */
1060 Ember.metaPath = function metaPath(obj, path, writable) {
1061   var meta = Ember.meta(obj, writable), keyName, value;
1062
1063   for (var i=0, l=path.length; i<l; i++) {
1064     keyName = path[i];
1065     value = meta[keyName];
1066
1067     if (!value) {
1068       if (!writable) { return undefined; }
1069       value = meta[keyName] = { __ember_source__: obj };
1070     } else if (value.__ember_source__ !== obj) {
1071       if (!writable) { return undefined; }
1072       value = meta[keyName] = o_create(value);
1073       value.__ember_source__ = obj;
1074     }
1075
1076     meta = value;
1077   }
1078
1079   return value;
1080 };
1081
1082 /**
1083   @private
1084
1085   Wraps the passed function so that `this._super` will point to the superFunc
1086   when the function is invoked.  This is the primitive we use to implement
1087   calls to super.
1088
1089   @method wrap
1090   @for Ember
1091   @param {Function} func The function to call
1092   @param {Function} superFunc The super function.
1093   @return {Function} wrapped function.
1094 */
1095 Ember.wrap = function(func, superFunc) {
1096
1097   function K() {}
1098
1099   var newFunc = function() {
1100     var ret, sup = this._super;
1101     this._super = superFunc || K;
1102     ret = func.apply(this, arguments);
1103     this._super = sup;
1104     return ret;
1105   };
1106
1107   newFunc.base = func;
1108   return newFunc;
1109 };
1110
1111 /**
1112   Returns true if the passed object is an array or Array-like.
1113
1114   Ember Array Protocol:
1115
1116     - the object has an objectAt property
1117     - the object is a native Array
1118     - the object is an Object, and has a length property
1119
1120   Unlike Ember.typeOf this method returns true even if the passed object is
1121   not formally array but appears to be array-like (i.e. implements Ember.Array)
1122
1123       Ember.isArray(); // false
1124       Ember.isArray([]); // true
1125       Ember.isArray( Ember.ArrayProxy.create({ content: [] }) ); // true
1126
1127   @method isArray
1128   @for Ember
1129   @param {Object} obj The object to test
1130   @return {Boolean}
1131 */
1132 Ember.isArray = function(obj) {
1133   if (!obj || obj.setInterval) { return false; }
1134   if (Array.isArray && Array.isArray(obj)) { return true; }
1135   if (Ember.Array && Ember.Array.detect(obj)) { return true; }
1136   if ((obj.length !== undefined) && 'object'===typeof obj) { return true; }
1137   return false;
1138 };
1139
1140 /**
1141   Forces the passed object to be part of an array.  If the object is already
1142   an array or array-like, returns the object.  Otherwise adds the object to
1143   an array.  If obj is null or undefined, returns an empty array.
1144
1145       Ember.makeArray();          => []
1146       Ember.makeArray(null);      => []
1147       Ember.makeArray(undefined); => []
1148       Ember.makeArray('lindsay'); => ['lindsay']
1149       Ember.makeArray([1,2,42]);  => [1,2,42]
1150
1151       var controller = Ember.ArrayProxy.create({ content: [] });
1152       Ember.makeArray(controller) === controller;   => true
1153
1154   @method makeArray
1155   @for Ember
1156   @param {Object} obj the object
1157   @return {Array}
1158 */
1159 Ember.makeArray = function(obj) {
1160   if (obj === null || obj === undefined) { return []; }
1161   return Ember.isArray(obj) ? obj : [obj];
1162 };
1163
1164 function canInvoke(obj, methodName) {
1165   return !!(obj && typeof obj[methodName] === 'function');
1166 }
1167
1168 /**
1169   Checks to see if the `methodName` exists on the `obj`.
1170
1171   @method canInvoke
1172   @for Ember
1173   @param {Object} obj The object to check for the method
1174   @param {String} methodName The method name to check for
1175 */
1176 Ember.canInvoke = canInvoke;
1177
1178 /**
1179   Checks to see if the `methodName` exists on the `obj`,
1180   and if it does, invokes it with the arguments passed.
1181
1182   @method tryInvoke
1183   @for Ember
1184   @param {Object} obj The object to check for the method
1185   @param {String} methodName The method name to check for
1186   @param {Array} [args] The arguments to pass to the method
1187   @return {anything} the return value of the invoked method or undefined if it cannot be invoked
1188 */
1189 Ember.tryInvoke = function(obj, methodName, args) {
1190   if (canInvoke(obj, methodName)) {
1191     return obj[methodName].apply(obj, args || []);
1192   }
1193 };
1194
1195 })();
1196
1197
1198
1199 (function() {
1200 /**
1201 @module ember-metal
1202 */
1203
1204 /*
1205   JavaScript (before ES6) does not have a Map implementation. Objects,
1206   which are often used as dictionaries, may only have Strings as keys.
1207
1208   Because Ember has a way to get a unique identifier for every object
1209   via `Ember.guidFor`, we can implement a performant Map with arbitrary
1210   keys. Because it is commonly used in low-level bookkeeping, Map is
1211   implemented as a pure JavaScript object for performance.
1212
1213   This implementation follows the current iteration of the ES6 proposal
1214   for maps (http://wiki.ecmascript.org/doku.php?id=harmony:simple_maps_and_sets),
1215   with two exceptions. First, because we need our implementation to be
1216   pleasant on older browsers, we do not use the `delete` name (using
1217   `remove` instead). Second, as we do not have the luxury of in-VM
1218   iteration, we implement a forEach method for iteration.
1219
1220   Map is mocked out to look like an Ember object, so you can do
1221   `Ember.Map.create()` for symmetry with other Ember classes.
1222 */
1223 var guidFor = Ember.guidFor,
1224     indexOf = Ember.ArrayPolyfills.indexOf;
1225
1226 var copy = function(obj) {
1227   var output = {};
1228
1229   for (var prop in obj) {
1230     if (obj.hasOwnProperty(prop)) { output[prop] = obj[prop]; }
1231   }
1232
1233   return output;
1234 };
1235
1236 var copyMap = function(original, newObject) {
1237   var keys = original.keys.copy(),
1238       values = copy(original.values);
1239
1240   newObject.keys = keys;
1241   newObject.values = values;
1242
1243   return newObject;
1244 };
1245
1246 /**
1247   This class is used internally by Ember.js and Ember Data.
1248   Please do not use it at this time. We plan to clean it up
1249   and add many tests soon.
1250
1251   @class OrderedSet
1252   @namespace Ember
1253   @constructor
1254   @private
1255 */
1256 var OrderedSet = Ember.OrderedSet = function() {
1257   this.clear();
1258 };
1259
1260 /**
1261   @method create
1262   @static
1263   @return {Ember.OrderedSet}
1264 */
1265 OrderedSet.create = function() {
1266   return new OrderedSet();
1267 };
1268
1269
1270 OrderedSet.prototype = {
1271   /**
1272     @method clear
1273   */
1274   clear: function() {
1275     this.presenceSet = {};
1276     this.list = [];
1277   },
1278
1279   /**
1280     @method add
1281     @param obj
1282   */
1283   add: function(obj) {
1284     var guid = guidFor(obj),
1285         presenceSet = this.presenceSet,
1286         list = this.list;
1287
1288     if (guid in presenceSet) { return; }
1289
1290     presenceSet[guid] = true;
1291     list.push(obj);
1292   },
1293
1294   /**
1295     @method remove
1296     @param obj
1297   */
1298   remove: function(obj) {
1299     var guid = guidFor(obj),
1300         presenceSet = this.presenceSet,
1301         list = this.list;
1302
1303     delete presenceSet[guid];
1304
1305     var index = indexOf.call(list, obj);
1306     if (index > -1) {
1307       list.splice(index, 1);
1308     }
1309   },
1310
1311   /**
1312     @method isEmpty
1313     @return {Boolean}
1314   */
1315   isEmpty: function() {
1316     return this.list.length === 0;
1317   },
1318
1319   /**
1320     @method has
1321     @param obj
1322     @return {Boolean}
1323   */
1324   has: function(obj) {
1325     var guid = guidFor(obj),
1326         presenceSet = this.presenceSet;
1327
1328     return guid in presenceSet;
1329   },
1330
1331   /**
1332     @method forEach
1333     @param {Function} function
1334     @param target
1335   */
1336   forEach: function(fn, self) {
1337     // allow mutation during iteration
1338     var list = this.list.slice();
1339
1340     for (var i = 0, j = list.length; i < j; i++) {
1341       fn.call(self, list[i]);
1342     }
1343   },
1344
1345   /**
1346     @method toArray
1347     @return {Array}
1348   */
1349   toArray: function() {
1350     return this.list.slice();
1351   },
1352
1353   /**
1354     @method copy
1355     @return {Ember.OrderedSet}
1356   */
1357   copy: function() {
1358     var set = new OrderedSet();
1359
1360     set.presenceSet = copy(this.presenceSet);
1361     set.list = this.list.slice();
1362
1363     return set;
1364   }
1365 };
1366
1367 /**
1368   A Map stores values indexed by keys. Unlike JavaScript's
1369   default Objects, the keys of a Map can be any JavaScript
1370   object.
1371
1372   Internally, a Map has two data structures:
1373
1374     `keys`: an OrderedSet of all of the existing keys
1375     `values`: a JavaScript Object indexed by the
1376       Ember.guidFor(key)
1377
1378   When a key/value pair is added for the first time, we
1379   add the key to the `keys` OrderedSet, and create or
1380   replace an entry in `values`. When an entry is deleted,
1381   we delete its entry in `keys` and `values`.
1382
1383   @class Map
1384   @namespace Ember
1385   @private
1386   @constructor
1387 */
1388 var Map = Ember.Map = function() {
1389   this.keys = Ember.OrderedSet.create();
1390   this.values = {};
1391 };
1392
1393 /**
1394   @method create
1395   @static
1396 */
1397 Map.create = function() {
1398   return new Map();
1399 };
1400
1401 Map.prototype = {
1402   /**
1403     Retrieve the value associated with a given key.
1404
1405     @method get
1406     @param {anything} key
1407     @return {anything} the value associated with the key, or undefined
1408   */
1409   get: function(key) {
1410     var values = this.values,
1411         guid = guidFor(key);
1412
1413     return values[guid];
1414   },
1415
1416   /**
1417     Adds a value to the map. If a value for the given key has already been
1418     provided, the new value will replace the old value.
1419
1420     @method set
1421     @param {anything} key
1422     @param {anything} value
1423   */
1424   set: function(key, value) {
1425     var keys = this.keys,
1426         values = this.values,
1427         guid = guidFor(key);
1428
1429     keys.add(key);
1430     values[guid] = value;
1431   },
1432
1433   /**
1434     Removes a value from the map for an associated key.
1435
1436     @method remove
1437     @param {anything} key
1438     @return {Boolean} true if an item was removed, false otherwise
1439   */
1440   remove: function(key) {
1441     // don't use ES6 "delete" because it will be annoying
1442     // to use in browsers that are not ES6 friendly;
1443     var keys = this.keys,
1444         values = this.values,
1445         guid = guidFor(key),
1446         value;
1447
1448     if (values.hasOwnProperty(guid)) {
1449       keys.remove(key);
1450       value = values[guid];
1451       delete values[guid];
1452       return true;
1453     } else {
1454       return false;
1455     }
1456   },
1457
1458   /**
1459     Check whether a key is present.
1460
1461     @method has
1462     @param {anything} key
1463     @return {Boolean} true if the item was present, false otherwise
1464   */
1465   has: function(key) {
1466     var values = this.values,
1467         guid = guidFor(key);
1468
1469     return values.hasOwnProperty(guid);
1470   },
1471
1472   /**
1473     Iterate over all the keys and values. Calls the function once
1474     for each key, passing in the key and value, in that order.
1475
1476     The keys are guaranteed to be iterated over in insertion order.
1477
1478     @method forEach
1479     @param {Function} callback
1480     @param {anything} self if passed, the `this` value inside the
1481       callback. By default, `this` is the map.
1482   */
1483   forEach: function(callback, self) {
1484     var keys = this.keys,
1485         values = this.values;
1486
1487     keys.forEach(function(key) {
1488       var guid = guidFor(key);
1489       callback.call(self, key, values[guid]);
1490     });
1491   },
1492
1493   /**
1494     @method copy
1495     @return {Ember.Map}
1496   */
1497   copy: function() {
1498     return copyMap(this, new Map());
1499   }
1500 };
1501
1502 /**
1503   @class MapWithDefault
1504   @namespace Ember
1505   @extends Ember.Map
1506   @private
1507   @constructor
1508   @param [options]
1509     @param {anything} [options.defaultValue]
1510 */
1511 var MapWithDefault = Ember.MapWithDefault = function(options) {
1512   Map.call(this);
1513   this.defaultValue = options.defaultValue;
1514 };
1515
1516 /**
1517   @method create
1518   @static
1519   @param [options]
1520     @param {anything} [options.defaultValue]
1521   @return {Ember.MapWithDefault|Ember.Map} If options are passed, returns Ember.MapWithDefault otherwise returns Ember.Map
1522 */
1523 MapWithDefault.create = function(options) {
1524   if (options) {
1525     return new MapWithDefault(options);
1526   } else {
1527     return new Map();
1528   }
1529 };
1530
1531 MapWithDefault.prototype = Ember.create(Map.prototype);
1532
1533 /**
1534   Retrieve the value associated with a given key.
1535
1536   @method get
1537   @param {anything} key
1538   @return {anything} the value associated with the key, or the default value
1539 */
1540 MapWithDefault.prototype.get = function(key) {
1541   var hasValue = this.has(key);
1542
1543   if (hasValue) {
1544     return Map.prototype.get.call(this, key);
1545   } else {
1546     var defaultValue = this.defaultValue(key);
1547     this.set(key, defaultValue);
1548     return defaultValue;
1549   }
1550 };
1551
1552 /**
1553   @method copy
1554   @return {Ember.MapWithDefault}
1555 */
1556 MapWithDefault.prototype.copy = function() {
1557   return copyMap(this, new MapWithDefault({
1558     defaultValue: this.defaultValue
1559   }));
1560 };
1561
1562 })();
1563
1564
1565
1566 (function() {
1567 /**
1568 @module ember-metal
1569 */
1570
1571 var META_KEY = Ember.META_KEY, get, set;
1572
1573 var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER;
1574
1575 var IS_GLOBAL = /^([A-Z$]|([0-9][A-Z$]))/;
1576 var IS_GLOBAL_PATH = /^([A-Z$]|([0-9][A-Z$])).*[\.\*]/;
1577 var HAS_THIS  = /^this[\.\*]/;
1578 var FIRST_KEY = /^([^\.\*]+)/;
1579
1580 // ..........................................................
1581 // GET AND SET
1582 //
1583 // If we are on a platform that supports accessors we can get use those.
1584 // Otherwise simulate accessors by looking up the property directly on the
1585 // object.
1586
1587 /**
1588   Gets the value of a property on an object.  If the property is computed,
1589   the function will be invoked.  If the property is not defined but the
1590   object implements the unknownProperty() method then that will be invoked.
1591
1592   If you plan to run on IE8 and older browsers then you should use this
1593   method anytime you want to retrieve a property on an object that you don't
1594   know for sure is private.  (My convention only properties beginning with
1595   an underscore '_' are considered private.)
1596
1597   On all newer browsers, you only need to use this method to retrieve
1598   properties if the property might not be defined on the object and you want
1599   to respect the unknownProperty() handler.  Otherwise you can ignore this
1600   method.
1601
1602   Note that if the obj itself is null, this method will simply return
1603   undefined.
1604
1605   @method get
1606   @for Ember
1607   @param {Object} obj The object to retrieve from.
1608   @param {String} keyName The property key to retrieve
1609   @return {Object} the property value or null.
1610 */
1611 get = function get(obj, keyName) {
1612   // Helpers that operate with 'this' within an #each
1613   if (keyName === '') {
1614     return obj;
1615   }
1616
1617   if (!keyName && 'string'===typeof obj) {
1618     keyName = obj;
1619     obj = null;
1620   }
1621
1622   if (!obj || keyName.indexOf('.') !== -1) {
1623     return getPath(obj, keyName);
1624   }
1625
1626   Ember.assert("You need to provide an object and key to `get`.", !!obj && keyName);
1627
1628   var meta = obj[META_KEY], desc = meta && meta.descs[keyName], ret;
1629   if (desc) {
1630     return desc.get(obj, keyName);
1631   } else {
1632     if (MANDATORY_SETTER && meta && meta.watching[keyName] > 0) {
1633       ret = meta.values[keyName];
1634     } else {
1635       ret = obj[keyName];
1636     }
1637
1638     if (ret === undefined &&
1639         'object' === typeof obj && !(keyName in obj) && 'function' === typeof obj.unknownProperty) {
1640       return obj.unknownProperty(keyName);
1641     }
1642
1643     return ret;
1644   }
1645 };
1646
1647 /**
1648   Sets the value of a property on an object, respecting computed properties
1649   and notifying observers and other listeners of the change.  If the
1650   property is not defined but the object implements the unknownProperty()
1651   method then that will be invoked as well.
1652
1653   If you plan to run on IE8 and older browsers then you should use this
1654   method anytime you want to set a property on an object that you don't
1655   know for sure is private.  (My convention only properties beginning with
1656   an underscore '_' are considered private.)
1657
1658   On all newer browsers, you only need to use this method to set
1659   properties if the property might not be defined on the object and you want
1660   to respect the unknownProperty() handler.  Otherwise you can ignore this
1661   method.
1662
1663   @method set
1664   @for Ember
1665   @param {Object} obj The object to modify.
1666   @param {String} keyName The property key to set
1667   @param {Object} value The value to set
1668   @return {Object} the passed value.
1669 */
1670 set = function set(obj, keyName, value, tolerant) {
1671   if (typeof obj === 'string') {
1672     Ember.assert("Path '" + obj + "' must be global if no obj is given.", IS_GLOBAL.test(obj));
1673     value = keyName;
1674     keyName = obj;
1675     obj = null;
1676   }
1677
1678   if (!obj || keyName.indexOf('.') !== -1) {
1679     return setPath(obj, keyName, value, tolerant);
1680   }
1681
1682   Ember.assert("You need to provide an object and key to `set`.", !!obj && keyName !== undefined);
1683   Ember.assert('calling set on destroyed object', !obj.isDestroyed);
1684
1685   var meta = obj[META_KEY], desc = meta && meta.descs[keyName],
1686       isUnknown, currentValue;
1687   if (desc) {
1688     desc.set(obj, keyName, value);
1689   }
1690   else {
1691     isUnknown = 'object' === typeof obj && !(keyName in obj);
1692
1693     // setUnknownProperty is called if `obj` is an object,
1694     // the property does not already exist, and the
1695     // `setUnknownProperty` method exists on the object
1696     if (isUnknown && 'function' === typeof obj.setUnknownProperty) {
1697       obj.setUnknownProperty(keyName, value);
1698     } else if (meta && meta.watching[keyName] > 0) {
1699       if (MANDATORY_SETTER) {
1700         currentValue = meta.values[keyName];
1701       } else {
1702         currentValue = obj[keyName];
1703       }
1704       // only trigger a change if the value has changed
1705       if (value !== currentValue) {
1706         Ember.propertyWillChange(obj, keyName);
1707         if (MANDATORY_SETTER) {
1708           if (currentValue === undefined && !(keyName in obj)) {
1709             Ember.defineProperty(obj, keyName, null, value); // setup mandatory setter
1710           } else {
1711             meta.values[keyName] = value;
1712           }
1713         } else {
1714           obj[keyName] = value;
1715         }
1716         Ember.propertyDidChange(obj, keyName);
1717       }
1718     } else {
1719       obj[keyName] = value;
1720     }
1721   }
1722   return value;
1723 };
1724
1725 // Currently used only by Ember Data tests
1726 if (Ember.config.overrideAccessors) {
1727   Ember.get = get;
1728   Ember.set = set;
1729   Ember.config.overrideAccessors();
1730   get = Ember.get;
1731   set = Ember.set;
1732 }
1733
1734 function firstKey(path) {
1735   return path.match(FIRST_KEY)[0];
1736 }
1737
1738 // assumes path is already normalized
1739 function normalizeTuple(target, path) {
1740   var hasThis  = HAS_THIS.test(path),
1741       isGlobal = !hasThis && IS_GLOBAL_PATH.test(path),
1742       key;
1743
1744   if (!target || isGlobal) target = Ember.lookup;
1745   if (hasThis) path = path.slice(5);
1746
1747   if (target === Ember.lookup) {
1748     key = firstKey(path);
1749     target = get(target, key);
1750     path   = path.slice(key.length+1);
1751   }
1752
1753   // must return some kind of path to be valid else other things will break.
1754   if (!path || path.length===0) throw new Error('Invalid Path');
1755
1756   return [ target, path ];
1757 }
1758
1759 function getPath(root, path) {
1760   var hasThis, parts, tuple, idx, len;
1761
1762   // If there is no root and path is a key name, return that
1763   // property from the global object.
1764   // E.g. get('Ember') -> Ember
1765   if (root === null && path.indexOf('.') === -1) { return get(Ember.lookup, path); }
1766
1767   // detect complicated paths and normalize them
1768   hasThis  = HAS_THIS.test(path);
1769
1770   if (!root || hasThis) {
1771     tuple = normalizeTuple(root, path);
1772     root = tuple[0];
1773     path = tuple[1];
1774     tuple.length = 0;
1775   }
1776
1777   parts = path.split(".");
1778   len = parts.length;
1779   for (idx=0; root && idx<len; idx++) {
1780     root = get(root, parts[idx], true);
1781     if (root && root.isDestroyed) { return undefined; }
1782   }
1783   return root;
1784 }
1785
1786 function setPath(root, path, value, tolerant) {
1787   var keyName;
1788
1789   // get the last part of the path
1790   keyName = path.slice(path.lastIndexOf('.') + 1);
1791
1792   // get the first part of the part
1793   path    = path.slice(0, path.length-(keyName.length+1));
1794
1795   // unless the path is this, look up the first part to
1796   // get the root
1797   if (path !== 'this') {
1798     root = getPath(root, path);
1799   }
1800
1801   if (!keyName || keyName.length === 0) {
1802     throw new Error('You passed an empty path');
1803   }
1804
1805   if (!root) {
1806     if (tolerant) { return; }
1807     else { throw new Error('Object in path '+path+' could not be found or was destroyed.'); }
1808   }
1809
1810   return set(root, keyName, value);
1811 }
1812
1813 /**
1814   @private
1815
1816   Normalizes a target/path pair to reflect that actual target/path that should
1817   be observed, etc.  This takes into account passing in global property
1818   paths (i.e. a path beginning with a captial letter not defined on the
1819   target) and * separators.
1820
1821   @method normalizeTuple
1822   @for Ember
1823   @param {Object} target The current target.  May be null.
1824   @param {String} path A path on the target or a global property path.
1825   @return {Array} a temporary array with the normalized target/path pair.
1826 */
1827 Ember.normalizeTuple = function(target, path) {
1828   return normalizeTuple(target, path);
1829 };
1830
1831 Ember.getWithDefault = function(root, key, defaultValue) {
1832   var value = get(root, key);
1833
1834   if (value === undefined) { return defaultValue; }
1835   return value;
1836 };
1837
1838
1839 Ember.get = get;
1840 Ember.getPath = Ember.deprecateFunc('getPath is deprecated since get now supports paths', Ember.get);
1841
1842 Ember.set = set;
1843 Ember.setPath = Ember.deprecateFunc('setPath is deprecated since set now supports paths', Ember.set);
1844
1845 /**
1846   Error-tolerant form of Ember.set. Will not blow up if any part of the
1847   chain is undefined, null, or destroyed.
1848
1849   This is primarily used when syncing bindings, which may try to update after
1850   an object has been destroyed.
1851
1852   @method trySet
1853   @for Ember
1854   @param {Object} obj The object to modify.
1855   @param {String} keyName The property key to set
1856   @param {Object} value The value to set
1857 */
1858 Ember.trySet = function(root, path, value) {
1859   return set(root, path, value, true);
1860 };
1861 Ember.trySetPath = Ember.deprecateFunc('trySetPath has been renamed to trySet', Ember.trySet);
1862
1863 /**
1864   Returns true if the provided path is global (e.g., "MyApp.fooController.bar")
1865   instead of local ("foo.bar.baz").
1866
1867   @method isGlobalPath
1868   @for Ember
1869   @private
1870   @param {String} path
1871   @return Boolean
1872 */
1873 Ember.isGlobalPath = function(path) {
1874   return IS_GLOBAL.test(path);
1875 };
1876
1877
1878 })();
1879
1880
1881
1882 (function() {
1883 /**
1884 @module ember-metal
1885 */
1886
1887 var GUID_KEY = Ember.GUID_KEY,
1888     META_KEY = Ember.META_KEY,
1889     EMPTY_META = Ember.EMPTY_META,
1890     metaFor = Ember.meta,
1891     o_create = Ember.create,
1892     objectDefineProperty = Ember.platform.defineProperty;
1893
1894 var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER;
1895
1896 // ..........................................................
1897 // DESCRIPTOR
1898 //
1899
1900 /**
1901   Objects of this type can implement an interface to responds requests to
1902   get and set.  The default implementation handles simple properties.
1903
1904   You generally won't need to create or subclass this directly.
1905
1906   @class Descriptor
1907   @namespace Ember
1908   @private
1909   @constructor
1910 */
1911 var Descriptor = Ember.Descriptor = function() {};
1912
1913 // ..........................................................
1914 // DEFINING PROPERTIES API
1915 //
1916
1917 /**
1918   @private
1919
1920   NOTE: This is a low-level method used by other parts of the API.  You almost
1921   never want to call this method directly.  Instead you should use Ember.mixin()
1922   to define new properties.
1923
1924   Defines a property on an object.  This method works much like the ES5
1925   Object.defineProperty() method except that it can also accept computed
1926   properties and other special descriptors.
1927
1928   Normally this method takes only three parameters.  However if you pass an
1929   instance of Ember.Descriptor as the third param then you can pass an optional
1930   value as the fourth parameter.  This is often more efficient than creating
1931   new descriptor hashes for each property.
1932
1933   ## Examples
1934
1935       // ES5 compatible mode
1936       Ember.defineProperty(contact, 'firstName', {
1937         writable: true,
1938         configurable: false,
1939         enumerable: true,
1940         value: 'Charles'
1941       });
1942
1943       // define a simple property
1944       Ember.defineProperty(contact, 'lastName', undefined, 'Jolley');
1945
1946       // define a computed property
1947       Ember.defineProperty(contact, 'fullName', Ember.computed(function() {
1948         return this.firstName+' '+this.lastName;
1949       }).property('firstName', 'lastName'));
1950
1951   @method defineProperty
1952   @for Ember
1953   @param {Object} obj the object to define this property on. This may be a prototype.
1954   @param {String} keyName the name of the property
1955   @param {Ember.Descriptor} [desc] an instance of Ember.Descriptor (typically a
1956     computed property) or an ES5 descriptor.
1957     You must provide this or `data` but not both.
1958   @param {anything} [data] something other than a descriptor, that will
1959     become the explicit value of this property.
1960 */
1961 Ember.defineProperty = function(obj, keyName, desc, data, meta) {
1962   var descs, existingDesc, watching, value;
1963
1964   if (!meta) meta = metaFor(obj);
1965   descs = meta.descs;
1966   existingDesc = meta.descs[keyName];
1967   watching = meta.watching[keyName] > 0;
1968
1969   if (existingDesc instanceof Ember.Descriptor) {
1970     existingDesc.teardown(obj, keyName);
1971   }
1972
1973   if (desc instanceof Ember.Descriptor) {
1974     value = desc;
1975
1976     descs[keyName] = desc;
1977     if (MANDATORY_SETTER && watching) {
1978       objectDefineProperty(obj, keyName, {
1979         configurable: true,
1980         enumerable: true,
1981         writable: true,
1982         value: undefined // make enumerable
1983       });
1984     } else {
1985       obj[keyName] = undefined; // make enumerable
1986     }
1987     desc.setup(obj, keyName);
1988   } else {
1989     descs[keyName] = undefined; // shadow descriptor in proto
1990     if (desc == null) {
1991       value = data;
1992
1993       if (MANDATORY_SETTER && watching) {
1994         meta.values[keyName] = data;
1995         objectDefineProperty(obj, keyName, {
1996           configurable: true,
1997           enumerable: true,
1998           set: function() {
1999             Ember.assert('Must use Ember.set() to access this property', false);
2000           },
2001           get: function() {
2002             var meta = this[META_KEY];
2003             return meta && meta.values[keyName];
2004           }
2005         });
2006       } else {
2007         obj[keyName] = data;
2008       }
2009     } else {
2010       value = desc;
2011
2012       // compatibility with ES5
2013       objectDefineProperty(obj, keyName, desc);
2014     }
2015   }
2016
2017   // if key is being watched, override chains that
2018   // were initialized with the prototype
2019   if (watching) { Ember.overrideChains(obj, keyName, meta); }
2020
2021   // The `value` passed to the `didDefineProperty` hook is
2022   // either the descriptor or data, whichever was passed.
2023   if (obj.didDefineProperty) { obj.didDefineProperty(obj, keyName, value); }
2024
2025   return this;
2026 };
2027
2028
2029 })();
2030
2031
2032
2033 (function() {
2034 /**
2035 @module ember-metal
2036 */
2037
2038 var AFTER_OBSERVERS = ':change';
2039 var BEFORE_OBSERVERS = ':before';
2040
2041 var guidFor = Ember.guidFor;
2042
2043 var deferred = 0;
2044
2045 /*
2046   this.observerSet = {
2047     [senderGuid]: { // variable name: `keySet`
2048       [keyName]: listIndex
2049     }
2050   },
2051   this.observers = [
2052     {
2053       sender: obj,
2054       keyName: keyName,
2055       eventName: eventName,
2056       listeners: {
2057         [targetGuid]: {        // variable name: `actionSet`
2058           [methodGuid]: {      // variable name: `action`
2059             target: [Object object],
2060             method: [Function function]
2061           }
2062         }
2063       }
2064     },
2065     ...
2066   ]
2067 */
2068 function ObserverSet() {
2069   this.clear();
2070 }
2071
2072 ObserverSet.prototype.add = function(sender, keyName, eventName) {
2073   var observerSet = this.observerSet,
2074       observers = this.observers,
2075       senderGuid = Ember.guidFor(sender),
2076       keySet = observerSet[senderGuid],
2077       index;
2078
2079   if (!keySet) {
2080     observerSet[senderGuid] = keySet = {};
2081   }
2082   index = keySet[keyName];
2083   if (index === undefined) {
2084     index = observers.push({
2085       sender: sender,
2086       keyName: keyName,
2087       eventName: eventName,
2088       listeners: {}
2089     }) - 1;
2090     keySet[keyName] = index;
2091   }
2092   return observers[index].listeners;
2093 };
2094
2095 ObserverSet.prototype.flush = function() {
2096   var observers = this.observers, i, len, observer, sender;
2097   this.clear();
2098   for (i=0, len=observers.length; i < len; ++i) {
2099     observer = observers[i];
2100     sender = observer.sender;
2101     if (sender.isDestroyed) { continue; }
2102     Ember.sendEvent(sender, observer.eventName, [sender, observer.keyName], observer.listeners);
2103   }
2104 };
2105
2106 ObserverSet.prototype.clear = function() {
2107   this.observerSet = {};
2108   this.observers = [];
2109 };
2110
2111 var beforeObserverSet = new ObserverSet(), observerSet = new ObserverSet();
2112
2113 /**
2114   @method beginPropertyChanges
2115   @chainable
2116 */
2117 Ember.beginPropertyChanges = function() {
2118   deferred++;
2119 };
2120
2121 /**
2122   @method endPropertyChanges
2123 */
2124 Ember.endPropertyChanges = function() {
2125   deferred--;
2126   if (deferred<=0) {
2127     beforeObserverSet.clear();
2128     observerSet.flush();
2129   }
2130 };
2131
2132 /**
2133   Make a series of property changes together in an
2134   exception-safe way.
2135
2136       Ember.changeProperties(function() {
2137         obj1.set('foo', mayBlowUpWhenSet);
2138         obj2.set('bar', baz);
2139       });
2140
2141   @method changeProperties
2142   @param {Function} callback
2143   @param [binding]
2144 */
2145 Ember.changeProperties = function(cb, binding){
2146   Ember.beginPropertyChanges();
2147   try {
2148     cb.call(binding);
2149   } finally {
2150     Ember.endPropertyChanges();
2151   }
2152 };
2153
2154 /**
2155   Set a list of properties on an object. These properties are set inside
2156   a single `beginPropertyChanges` and `endPropertyChanges` batch, so
2157   observers will be buffered.
2158
2159   @method setProperties
2160   @param target
2161   @param {Hash} properties
2162   @return target
2163 */
2164 Ember.setProperties = function(self, hash) {
2165   Ember.changeProperties(function(){
2166     for(var prop in hash) {
2167       if (hash.hasOwnProperty(prop)) Ember.set(self, prop, hash[prop]);
2168     }
2169   });
2170   return self;
2171 };
2172
2173
2174 function changeEvent(keyName) {
2175   return keyName+AFTER_OBSERVERS;
2176 }
2177
2178 function beforeEvent(keyName) {
2179   return keyName+BEFORE_OBSERVERS;
2180 }
2181
2182 /**
2183   @method addObserver
2184   @param obj
2185   @param {String} path
2186   @param {Object|Function} targetOrMethod
2187   @param {Function|String} [method]
2188 */
2189 Ember.addObserver = function(obj, path, target, method) {
2190   Ember.addListener(obj, changeEvent(path), target, method);
2191   Ember.watch(obj, path);
2192   return this;
2193 };
2194
2195 Ember.observersFor = function(obj, path) {
2196   return Ember.listenersFor(obj, changeEvent(path));
2197 };
2198
2199 /**
2200   @method removeObserver
2201   @param obj
2202   @param {String} path
2203   @param {Object|Function} targetOrMethod
2204   @param {Function|String} [method]
2205 */
2206 Ember.removeObserver = function(obj, path, target, method) {
2207   Ember.unwatch(obj, path);
2208   Ember.removeListener(obj, changeEvent(path), target, method);
2209   return this;
2210 };
2211
2212 /**
2213   @method addBeforeObserver
2214   @param obj
2215   @param {String} path
2216   @param {Object|Function} targetOrMethod
2217   @param {Function|String} [method]
2218 */
2219 Ember.addBeforeObserver = function(obj, path, target, method) {
2220   Ember.addListener(obj, beforeEvent(path), target, method);
2221   Ember.watch(obj, path);
2222   return this;
2223 };
2224
2225 // Suspend observer during callback.
2226 //
2227 // This should only be used by the target of the observer
2228 // while it is setting the observed path.
2229 Ember._suspendBeforeObserver = function(obj, path, target, method, callback) {
2230   return Ember._suspendListener(obj, beforeEvent(path), target, method, callback);
2231 };
2232
2233 Ember._suspendObserver = function(obj, path, target, method, callback) {
2234   return Ember._suspendListener(obj, changeEvent(path), target, method, callback);
2235 };
2236
2237 var map = Ember.ArrayPolyfills.map;
2238
2239 Ember._suspendBeforeObservers = function(obj, paths, target, method, callback) {
2240   var events = map.call(paths, beforeEvent);
2241   return Ember._suspendListeners(obj, events, target, method, callback);
2242 };
2243
2244 Ember._suspendObservers = function(obj, paths, target, method, callback) {
2245   var events = map.call(paths, changeEvent);
2246   return Ember._suspendListeners(obj, events, target, method, callback);
2247 };
2248
2249 Ember.beforeObserversFor = function(obj, path) {
2250   return Ember.listenersFor(obj, beforeEvent(path));
2251 };
2252
2253 /**
2254   @method removeBeforeObserver
2255   @param obj
2256   @param {String} path
2257   @param {Object|Function} targetOrMethod
2258   @param {Function|String} [method]
2259 */
2260 Ember.removeBeforeObserver = function(obj, path, target, method) {
2261   Ember.unwatch(obj, path);
2262   Ember.removeListener(obj, beforeEvent(path), target, method);
2263   return this;
2264 };
2265
2266 Ember.notifyBeforeObservers = function(obj, keyName) {
2267   if (obj.isDestroying) { return; }
2268
2269   var eventName = beforeEvent(keyName), listeners, listenersDiff;
2270   if (deferred) {
2271     listeners = beforeObserverSet.add(obj, keyName, eventName);
2272     listenersDiff = Ember.listenersDiff(obj, eventName, listeners);
2273     Ember.sendEvent(obj, eventName, [obj, keyName], listenersDiff);
2274   } else {
2275     Ember.sendEvent(obj, eventName, [obj, keyName]);
2276   }
2277 };
2278
2279 Ember.notifyObservers = function(obj, keyName) {
2280   if (obj.isDestroying) { return; }
2281
2282   var eventName = changeEvent(keyName), listeners;
2283   if (deferred) {
2284     listeners = observerSet.add(obj, keyName, eventName);
2285     Ember.listenersUnion(obj, eventName, listeners);
2286   } else {
2287     Ember.sendEvent(obj, eventName, [obj, keyName]);
2288   }
2289 };
2290
2291 })();
2292
2293
2294
2295 (function() {
2296 /**
2297 @module ember-metal
2298 */
2299
2300 var guidFor = Ember.guidFor, // utils.js
2301     metaFor = Ember.meta, // utils.js
2302     get = Ember.get, // accessors.js
2303     set = Ember.set, // accessors.js
2304     normalizeTuple = Ember.normalizeTuple, // accessors.js
2305     GUID_KEY = Ember.GUID_KEY, // utils.js
2306     META_KEY = Ember.META_KEY, // utils.js
2307     // circular reference observer depends on Ember.watch
2308     // we should move change events to this file or its own property_events.js
2309     notifyObservers = Ember.notifyObservers, // observer.js
2310     forEach = Ember.ArrayPolyfills.forEach, // array.js
2311     FIRST_KEY = /^([^\.\*]+)/,
2312     IS_PATH = /[\.\*]/;
2313
2314 var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER,
2315 o_defineProperty = Ember.platform.defineProperty;
2316
2317 function firstKey(path) {
2318   return path.match(FIRST_KEY)[0];
2319 }
2320
2321 // returns true if the passed path is just a keyName
2322 function isKeyName(path) {
2323   return path==='*' || !IS_PATH.test(path);
2324 }
2325
2326 // ..........................................................
2327 // DEPENDENT KEYS
2328 //
2329
2330 var DEP_SKIP = { __emberproto__: true }; // skip some keys and toString
2331
2332 function iterDeps(method, obj, depKey, seen, meta) {
2333
2334   var guid = guidFor(obj);
2335   if (!seen[guid]) seen[guid] = {};
2336   if (seen[guid][depKey]) return;
2337   seen[guid][depKey] = true;
2338
2339   var deps = meta.deps;
2340   deps = deps && deps[depKey];
2341   if (deps) {
2342     for(var key in deps) {
2343       if (DEP_SKIP[key]) continue;
2344       var desc = meta.descs[key];
2345       if (desc && desc._suspended === obj) continue;
2346       method(obj, key);
2347     }
2348   }
2349 }
2350
2351
2352 var WILL_SEEN, DID_SEEN;
2353
2354 // called whenever a property is about to change to clear the cache of any dependent keys (and notify those properties of changes, etc...)
2355 function dependentKeysWillChange(obj, depKey, meta) {
2356   if (obj.isDestroying) { return; }
2357
2358   var seen = WILL_SEEN, top = !seen;
2359   if (top) { seen = WILL_SEEN = {}; }
2360   iterDeps(propertyWillChange, obj, depKey, seen, meta);
2361   if (top) { WILL_SEEN = null; }
2362 }
2363
2364 // called whenever a property has just changed to update dependent keys
2365 function dependentKeysDidChange(obj, depKey, meta) {
2366   if (obj.isDestroying) { return; }
2367
2368   var seen = DID_SEEN, top = !seen;
2369   if (top) { seen = DID_SEEN = {}; }
2370   iterDeps(propertyDidChange, obj, depKey, seen, meta);
2371   if (top) { DID_SEEN = null; }
2372 }
2373
2374 // ..........................................................
2375 // CHAIN
2376 //
2377
2378 function addChainWatcher(obj, keyName, node) {
2379   if (!obj || ('object' !== typeof obj)) return; // nothing to do
2380   var m = metaFor(obj);
2381   var nodes = m.chainWatchers;
2382   if (!nodes || nodes.__emberproto__ !== obj) {
2383     nodes = m.chainWatchers = { __emberproto__: obj };
2384   }
2385
2386   if (!nodes[keyName]) { nodes[keyName] = {}; }
2387   nodes[keyName][guidFor(node)] = node;
2388   Ember.watch(obj, keyName);
2389 }
2390
2391 function removeChainWatcher(obj, keyName, node) {
2392   if (!obj || 'object' !== typeof obj) { return; } // nothing to do
2393   var m = metaFor(obj, false),
2394       nodes = m.chainWatchers;
2395   if (!nodes || nodes.__emberproto__ !== obj) { return; } //nothing to do
2396   if (nodes[keyName]) { delete nodes[keyName][guidFor(node)]; }
2397   Ember.unwatch(obj, keyName);
2398 }
2399
2400 var pendingQueue = [];
2401
2402 // attempts to add the pendingQueue chains again.  If some of them end up
2403 // back in the queue and reschedule is true, schedules a timeout to try
2404 // again.
2405 function flushPendingChains() {
2406   if (pendingQueue.length === 0) { return; } // nothing to do
2407
2408   var queue = pendingQueue;
2409   pendingQueue = [];
2410
2411   forEach.call(queue, function(q) { q[0].add(q[1]); });
2412
2413   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);
2414 }
2415
2416 function isProto(pvalue) {
2417   return metaFor(pvalue, false).proto === pvalue;
2418 }
2419
2420 // A ChainNode watches a single key on an object.  If you provide a starting
2421 // value for the key then the node won't actually watch it.  For a root node
2422 // pass null for parent and key and object for value.
2423 var ChainNode = function(parent, key, value, separator) {
2424   var obj;
2425   this._parent = parent;
2426   this._key    = key;
2427
2428   // _watching is true when calling get(this._parent, this._key) will
2429   // return the value of this node.
2430   //
2431   // It is false for the root of a chain (because we have no parent)
2432   // and for global paths (because the parent node is the object with
2433   // the observer on it)
2434   this._watching = value===undefined;
2435
2436   this._value  = value;
2437   this._separator = separator || '.';
2438   this._paths = {};
2439   if (this._watching) {
2440     this._object = parent.value();
2441     if (this._object) { addChainWatcher(this._object, this._key, this); }
2442   }
2443
2444   // Special-case: the EachProxy relies on immediate evaluation to
2445   // establish its observers.
2446   //
2447   // TODO: Replace this with an efficient callback that the EachProxy
2448   // can implement.
2449   if (this._parent && this._parent._key === '@each') {
2450     this.value();
2451   }
2452 };
2453
2454 var ChainNodePrototype = ChainNode.prototype;
2455
2456 ChainNodePrototype.value = function() {
2457   if (this._value === undefined && this._watching) {
2458     var obj = this._parent.value();
2459     this._value = (obj && !isProto(obj)) ? get(obj, this._key) : undefined;
2460   }
2461   return this._value;
2462 };
2463
2464 ChainNodePrototype.destroy = function() {
2465   if (this._watching) {
2466     var obj = this._object;
2467     if (obj) { removeChainWatcher(obj, this._key, this); }
2468     this._watching = false; // so future calls do nothing
2469   }
2470 };
2471
2472 // copies a top level object only
2473 ChainNodePrototype.copy = function(obj) {
2474   var ret = new ChainNode(null, null, obj, this._separator),
2475       paths = this._paths, path;
2476   for (path in paths) {
2477     if (paths[path] <= 0) { continue; } // this check will also catch non-number vals.
2478     ret.add(path);
2479   }
2480   return ret;
2481 };
2482
2483 // called on the root node of a chain to setup watchers on the specified
2484 // path.
2485 ChainNodePrototype.add = function(path) {
2486   var obj, tuple, key, src, separator, paths;
2487
2488   paths = this._paths;
2489   paths[path] = (paths[path] || 0) + 1;
2490
2491   obj = this.value();
2492   tuple = normalizeTuple(obj, path);
2493
2494   // the path was a local path
2495   if (tuple[0] && tuple[0] === obj) {
2496     path = tuple[1];
2497     key  = firstKey(path);
2498     path = path.slice(key.length+1);
2499
2500   // global path, but object does not exist yet.
2501   // put into a queue and try to connect later.
2502   } else if (!tuple[0]) {
2503     pendingQueue.push([this, path]);
2504     tuple.length = 0;
2505     return;
2506
2507   // global path, and object already exists
2508   } else {
2509     src  = tuple[0];
2510     key  = path.slice(0, 0-(tuple[1].length+1));
2511     separator = path.slice(key.length, key.length+1);
2512     path = tuple[1];
2513   }
2514
2515   tuple.length = 0;
2516   this.chain(key, path, src, separator);
2517 };
2518
2519 // called on the root node of a chain to teardown watcher on the specified
2520 // path
2521 ChainNodePrototype.remove = function(path) {
2522   var obj, tuple, key, src, paths;
2523
2524   paths = this._paths;
2525   if (paths[path] > 0) { paths[path]--; }
2526
2527   obj = this.value();
2528   tuple = normalizeTuple(obj, path);
2529   if (tuple[0] === obj) {
2530     path = tuple[1];
2531     key  = firstKey(path);
2532     path = path.slice(key.length+1);
2533   } else {
2534     src  = tuple[0];
2535     key  = path.slice(0, 0-(tuple[1].length+1));
2536     path = tuple[1];
2537   }
2538
2539   tuple.length = 0;
2540   this.unchain(key, path);
2541 };
2542
2543 ChainNodePrototype.count = 0;
2544
2545 ChainNodePrototype.chain = function(key, path, src, separator) {
2546   var chains = this._chains, node;
2547   if (!chains) { chains = this._chains = {}; }
2548
2549   node = chains[key];
2550   if (!node) { node = chains[key] = new ChainNode(this, key, src, separator); }
2551   node.count++; // count chains...
2552
2553   // chain rest of path if there is one
2554   if (path && path.length>0) {
2555     key = firstKey(path);
2556     path = path.slice(key.length+1);
2557     node.chain(key, path); // NOTE: no src means it will observe changes...
2558   }
2559 };
2560
2561 ChainNodePrototype.unchain = function(key, path) {
2562   var chains = this._chains, node = chains[key];
2563
2564   // unchain rest of path first...
2565   if (path && path.length>1) {
2566     key  = firstKey(path);
2567     path = path.slice(key.length+1);
2568     node.unchain(key, path);
2569   }
2570
2571   // delete node if needed.
2572   node.count--;
2573   if (node.count<=0) {
2574     delete chains[node._key];
2575     node.destroy();
2576   }
2577
2578 };
2579
2580 ChainNodePrototype.willChange = function() {
2581   var chains = this._chains;
2582   if (chains) {
2583     for(var key in chains) {
2584       if (!chains.hasOwnProperty(key)) { continue; }
2585       chains[key].willChange();
2586     }
2587   }
2588
2589   if (this._parent) { this._parent.chainWillChange(this, this._key, 1); }
2590 };
2591
2592 ChainNodePrototype.chainWillChange = function(chain, path, depth) {
2593   if (this._key) { path = this._key + this._separator + path; }
2594
2595   if (this._parent) {
2596     this._parent.chainWillChange(this, path, depth+1);
2597   } else {
2598     if (depth > 1) { Ember.propertyWillChange(this.value(), path); }
2599     path = 'this.' + path;
2600     if (this._paths[path] > 0) { Ember.propertyWillChange(this.value(), path); }
2601   }
2602 };
2603
2604 ChainNodePrototype.chainDidChange = function(chain, path, depth) {
2605   if (this._key) { path = this._key + this._separator + path; }
2606   if (this._parent) {
2607     this._parent.chainDidChange(this, path, depth+1);
2608   } else {
2609     if (depth > 1) { Ember.propertyDidChange(this.value(), path); }
2610     path = 'this.' + path;
2611     if (this._paths[path] > 0) { Ember.propertyDidChange(this.value(), path); }
2612   }
2613 };
2614
2615 ChainNodePrototype.didChange = function(suppressEvent) {
2616   // invalidate my own value first.
2617   if (this._watching) {
2618     var obj = this._parent.value();
2619     if (obj !== this._object) {
2620       removeChainWatcher(this._object, this._key, this);
2621       this._object = obj;
2622       addChainWatcher(obj, this._key, this);
2623     }
2624     this._value  = undefined;
2625
2626     // Special-case: the EachProxy relies on immediate evaluation to
2627     // establish its observers.
2628     if (this._parent && this._parent._key === '@each')
2629       this.value();
2630   }
2631
2632   // then notify chains...
2633   var chains = this._chains;
2634   if (chains) {
2635     for(var key in chains) {
2636       if (!chains.hasOwnProperty(key)) { continue; }
2637       chains[key].didChange(suppressEvent);
2638     }
2639   }
2640
2641   if (suppressEvent) { return; }
2642
2643   // and finally tell parent about my path changing...
2644   if (this._parent) { this._parent.chainDidChange(this, this._key, 1); }
2645 };
2646
2647 // get the chains for the current object.  If the current object has
2648 // chains inherited from the proto they will be cloned and reconfigured for
2649 // the current object.
2650 function chainsFor(obj) {
2651   var m = metaFor(obj), ret = m.chains;
2652   if (!ret) {
2653     ret = m.chains = new ChainNode(null, null, obj);
2654   } else if (ret.value() !== obj) {
2655     ret = m.chains = ret.copy(obj);
2656   }
2657   return ret;
2658 }
2659
2660 function notifyChains(obj, m, keyName, methodName, arg) {
2661   var nodes = m.chainWatchers;
2662
2663   if (!nodes || nodes.__emberproto__ !== obj) { return; } // nothing to do
2664
2665   nodes = nodes[keyName];
2666   if (!nodes) { return; }
2667
2668   for(var key in nodes) {
2669     if (!nodes.hasOwnProperty(key)) { continue; }
2670     nodes[key][methodName](arg);
2671   }
2672 }
2673
2674 Ember.overrideChains = function(obj, keyName, m) {
2675   notifyChains(obj, m, keyName, 'didChange', true);
2676 };
2677
2678 function chainsWillChange(obj, keyName, m) {
2679   notifyChains(obj, m, keyName, 'willChange');
2680 }
2681
2682 function chainsDidChange(obj, keyName, m) {
2683   notifyChains(obj, m, keyName, 'didChange');
2684 }
2685
2686 // ..........................................................
2687 // WATCH
2688 //
2689
2690 /**
2691   @private
2692
2693   Starts watching a property on an object.  Whenever the property changes,
2694   invokes Ember.propertyWillChange and Ember.propertyDidChange.  This is the
2695   primitive used by observers and dependent keys; usually you will never call
2696   this method directly but instead use higher level methods like
2697   Ember.addObserver().
2698
2699   @method watch
2700   @for Ember
2701   @param obj
2702   @param {String} keyName
2703 */
2704 Ember.watch = function(obj, keyName) {
2705   // can't watch length on Array - it is special...
2706   if (keyName === 'length' && Ember.typeOf(obj) === 'array') { return this; }
2707
2708   var m = metaFor(obj), watching = m.watching, desc;
2709
2710   // activate watching first time
2711   if (!watching[keyName]) {
2712     watching[keyName] = 1;
2713     if (isKeyName(keyName)) {
2714       desc = m.descs[keyName];
2715       if (desc && desc.willWatch) { desc.willWatch(obj, keyName); }
2716
2717       if ('function' === typeof obj.willWatchProperty) {
2718         obj.willWatchProperty(keyName);
2719       }
2720
2721       if (MANDATORY_SETTER && keyName in obj) {
2722         m.values[keyName] = obj[keyName];
2723         o_defineProperty(obj, keyName, {
2724           configurable: true,
2725           enumerable: true,
2726           set: function() {
2727             Ember.assert('Must use Ember.set() to access this property', false);
2728           },
2729           get: function() {
2730             var meta = this[META_KEY];
2731             return meta && meta.values[keyName];
2732           }
2733         });
2734       }
2735     } else {
2736       chainsFor(obj).add(keyName);
2737     }
2738
2739   }  else {
2740     watching[keyName] = (watching[keyName] || 0) + 1;
2741   }
2742   return this;
2743 };
2744
2745 Ember.isWatching = function isWatching(obj, key) {
2746   var meta = obj[META_KEY];
2747   return (meta && meta.watching[key]) > 0;
2748 };
2749
2750 Ember.watch.flushPending = flushPendingChains;
2751
2752 Ember.unwatch = function(obj, keyName) {
2753   // can't watch length on Array - it is special...
2754   if (keyName === 'length' && Ember.typeOf(obj) === 'array') { return this; }
2755
2756   var m = metaFor(obj), watching = m.watching, desc;
2757
2758   if (watching[keyName] === 1) {
2759     watching[keyName] = 0;
2760
2761     if (isKeyName(keyName)) {
2762       desc = m.descs[keyName];
2763       if (desc && desc.didUnwatch) { desc.didUnwatch(obj, keyName); }
2764
2765       if ('function' === typeof obj.didUnwatchProperty) {
2766         obj.didUnwatchProperty(keyName);
2767       }
2768
2769       if (MANDATORY_SETTER && keyName in obj) {
2770         o_defineProperty(obj, keyName, {
2771           configurable: true,
2772           enumerable: true,
2773           writable: true,
2774           value: m.values[keyName]
2775         });
2776         delete m.values[keyName];
2777       }
2778     } else {
2779       chainsFor(obj).remove(keyName);
2780     }
2781
2782   } else if (watching[keyName]>1) {
2783     watching[keyName]--;
2784   }
2785
2786   return this;
2787 };
2788
2789 /**
2790   @private
2791
2792   Call on an object when you first beget it from another object.  This will
2793   setup any chained watchers on the object instance as needed.  This method is
2794   safe to call multiple times.
2795
2796   @method rewatch
2797   @for Ember
2798   @param obj
2799 */
2800 Ember.rewatch = function(obj) {
2801   var m = metaFor(obj, false), chains = m.chains;
2802
2803   // make sure the object has its own guid.
2804   if (GUID_KEY in obj && !obj.hasOwnProperty(GUID_KEY)) {
2805     Ember.generateGuid(obj, 'ember');
2806   }
2807
2808   // make sure any chained watchers update.
2809   if (chains && chains.value() !== obj) {
2810     m.chains = chains.copy(obj);
2811   }
2812
2813   return this;
2814 };
2815
2816 Ember.finishChains = function(obj) {
2817   var m = metaFor(obj, false), chains = m.chains;
2818   if (chains) {
2819     if (chains.value() !== obj) {
2820       m.chains = chains = chains.copy(obj);
2821     }
2822     chains.didChange(true);
2823   }
2824 };
2825
2826 // ..........................................................
2827 // PROPERTY CHANGES
2828 //
2829
2830 /**
2831   This function is called just before an object property is about to change.
2832   It will notify any before observers and prepare caches among other things.
2833
2834   Normally you will not need to call this method directly but if for some
2835   reason you can't directly watch a property you can invoke this method
2836   manually along with `Ember.propertyDidChange()` which you should call just
2837   after the property value changes.
2838
2839   @method propertyWillChange
2840   @for Ember
2841   @param {Object} obj The object with the property that will change
2842   @param {String} keyName The property key (or path) that will change.
2843   @return {void}
2844 */
2845 function propertyWillChange(obj, keyName, value) {
2846   var m = metaFor(obj, false),
2847       watching = m.watching[keyName] > 0 || keyName === 'length',
2848       proto = m.proto,
2849       desc = m.descs[keyName];
2850
2851   if (!watching) { return; }
2852   if (proto === obj) { return; }
2853   if (desc && desc.willChange) { desc.willChange(obj, keyName); }
2854   dependentKeysWillChange(obj, keyName, m);
2855   chainsWillChange(obj, keyName, m);
2856   Ember.notifyBeforeObservers(obj, keyName);
2857 }
2858
2859 Ember.propertyWillChange = propertyWillChange;
2860
2861 /**
2862   This function is called just after an object property has changed.
2863   It will notify any observers and clear caches among other things.
2864
2865   Normally you will not need to call this method directly but if for some
2866   reason you can't directly watch a property you can invoke this method
2867   manually along with `Ember.propertyWilLChange()` which you should call just
2868   before the property value changes.
2869
2870   @method propertyDidChange
2871   @for Ember
2872   @param {Object} obj The object with the property that will change
2873   @param {String} keyName The property key (or path) that will change.
2874   @return {void}
2875 */
2876 function propertyDidChange(obj, keyName) {
2877   var m = metaFor(obj, false),
2878       watching = m.watching[keyName] > 0 || keyName === 'length',
2879       proto = m.proto,
2880       desc = m.descs[keyName];
2881
2882   if (proto === obj) { return; }
2883
2884   // shouldn't this mean that we're watching this key?
2885   if (desc && desc.didChange) { desc.didChange(obj, keyName); }
2886   if (!watching && keyName !== 'length') { return; }
2887
2888   dependentKeysDidChange(obj, keyName, m);
2889   chainsDidChange(obj, keyName, m);
2890   Ember.notifyObservers(obj, keyName);
2891 }
2892
2893 Ember.propertyDidChange = propertyDidChange;
2894
2895 var NODE_STACK = [];
2896
2897 /**
2898   Tears down the meta on an object so that it can be garbage collected.
2899   Multiple calls will have no effect.
2900
2901   @method destroy
2902   @for Ember
2903   @param {Object} obj  the object to destroy
2904   @return {void}
2905 */
2906 Ember.destroy = function (obj) {
2907   var meta = obj[META_KEY], node, nodes, key, nodeObject;
2908   if (meta) {
2909     obj[META_KEY] = null;
2910     // remove chainWatchers to remove circular references that would prevent GC
2911     node = meta.chains;
2912     if (node) {
2913       NODE_STACK.push(node);
2914       // process tree
2915       while (NODE_STACK.length > 0) {
2916         node = NODE_STACK.pop();
2917         // push children
2918         nodes = node._chains;
2919         if (nodes) {
2920           for (key in nodes) {
2921             if (nodes.hasOwnProperty(key)) {
2922               NODE_STACK.push(nodes[key]);
2923             }
2924           }
2925         }
2926         // remove chainWatcher in node object
2927         if (node._watching) {
2928           nodeObject = node._object;
2929           if (nodeObject) {
2930             removeChainWatcher(nodeObject, node._key, node);
2931           }
2932         }
2933       }
2934     }
2935   }
2936 };
2937
2938 })();
2939
2940
2941
2942 (function() {
2943 /**
2944 @module ember-metal
2945 */
2946
2947 Ember.warn("The CP_DEFAULT_CACHEABLE flag has been removed and computed properties are always cached by default. Use `volatile` if you don't want caching.", Ember.ENV.CP_DEFAULT_CACHEABLE !== false);
2948
2949
2950 var get = Ember.get,
2951     metaFor = Ember.meta,
2952     guidFor = Ember.guidFor,
2953     a_slice = [].slice,
2954     o_create = Ember.create,
2955     META_KEY = Ember.META_KEY,
2956     watch = Ember.watch,
2957     unwatch = Ember.unwatch;
2958
2959 // ..........................................................
2960 // DEPENDENT KEYS
2961 //
2962
2963 // data structure:
2964 //  meta.deps = {
2965 //   'depKey': {
2966 //     'keyName': count,
2967 //     __emberproto__: SRC_OBJ [to detect clones]
2968 //     },
2969 //   __emberproto__: SRC_OBJ
2970 //  }
2971
2972 /*
2973   This function returns a map of unique dependencies for a
2974   given object and key.
2975 */
2976 function keysForDep(obj, depsMeta, depKey) {
2977   var keys = depsMeta[depKey];
2978   if (!keys) {
2979     // if there are no dependencies yet for a the given key
2980     // create a new empty list of dependencies for the key
2981     keys = depsMeta[depKey] = { __emberproto__: obj };
2982   } else if (keys.__emberproto__ !== obj) {
2983     // otherwise if the dependency list is inherited from
2984     // a superclass, clone the hash
2985     keys = depsMeta[depKey] = o_create(keys);
2986     keys.__emberproto__ = obj;
2987   }
2988   return keys;
2989 }
2990
2991 /* return obj[META_KEY].deps */
2992 function metaForDeps(obj, meta) {
2993   var deps = meta.deps;
2994   // If the current object has no dependencies...
2995   if (!deps) {
2996     // initialize the dependencies with a pointer back to
2997     // the current object
2998     deps = meta.deps = { __emberproto__: obj };
2999   } else if (deps.__emberproto__ !== obj) {
3000     // otherwise if the dependencies are inherited from the
3001     // object's superclass, clone the deps
3002     deps = meta.deps = o_create(deps);
3003     deps.__emberproto__ = obj;
3004   }
3005   return deps;
3006 }
3007
3008 function addDependentKeys(desc, obj, keyName, meta) {
3009   // the descriptor has a list of dependent keys, so
3010   // add all of its dependent keys.
3011   var depKeys = desc._dependentKeys, depsMeta, idx, len, depKey, keys;
3012   if (!depKeys) return;
3013
3014   depsMeta = metaForDeps(obj, meta);
3015
3016   for(idx = 0, len = depKeys.length; idx < len; idx++) {
3017     depKey = depKeys[idx];
3018     // Lookup keys meta for depKey
3019     keys = keysForDep(obj, depsMeta, depKey);
3020     // Increment the number of times depKey depends on keyName.
3021     keys[keyName] = (keys[keyName] || 0) + 1;
3022     // Watch the depKey
3023     watch(obj, depKey);
3024   }
3025 }
3026
3027 function removeDependentKeys(desc, obj, keyName, meta) {
3028   // the descriptor has a list of dependent keys, so
3029   // add all of its dependent keys.
3030   var depKeys = desc._dependentKeys, depsMeta, idx, len, depKey, keys;
3031   if (!depKeys) return;
3032
3033   depsMeta = metaForDeps(obj, meta);
3034
3035   for(idx = 0, len = depKeys.length; idx < len; idx++) {
3036     depKey = depKeys[idx];
3037     // Lookup keys meta for depKey
3038     keys = keysForDep(obj, depsMeta, depKey);
3039     // Increment the number of times depKey depends on keyName.
3040     keys[keyName] = (keys[keyName] || 0) - 1;
3041     // Watch the depKey
3042     unwatch(obj, depKey);
3043   }
3044 }
3045
3046 // ..........................................................
3047 // COMPUTED PROPERTY
3048 //
3049
3050 /**
3051   @class ComputedProperty
3052   @namespace Ember
3053   @extends Ember.Descriptor
3054   @constructor
3055 */
3056 function ComputedProperty(func, opts) {
3057   this.func = func;
3058   this._cacheable = (opts && opts.cacheable !== undefined) ? opts.cacheable : true;
3059   this._dependentKeys = opts && opts.dependentKeys;
3060 }
3061
3062 Ember.ComputedProperty = ComputedProperty;
3063 ComputedProperty.prototype = new Ember.Descriptor();
3064
3065 var ComputedPropertyPrototype = ComputedProperty.prototype;
3066
3067 /**
3068   Call on a computed property to set it into cacheable mode.  When in this
3069   mode the computed property will automatically cache the return value of
3070   your function until one of the dependent keys changes.
3071
3072       MyApp.president = Ember.Object.create({
3073         fullName: function() {
3074           return this.get('firstName') + ' ' + this.get('lastName');
3075
3076           // After calculating the value of this function, Ember.js will
3077           // return that value without re-executing this function until
3078           // one of the dependent properties change.
3079         }.property('firstName', 'lastName')
3080       });
3081
3082   Properties are cacheable by default.
3083
3084   @method cacheable
3085   @param {Boolean} aFlag optional set to false to disable caching
3086   @chainable
3087 */
3088 ComputedPropertyPrototype.cacheable = function(aFlag) {
3089   this._cacheable = aFlag !== false;
3090   return this;
3091 };
3092
3093 /**
3094   Call on a computed property to set it into non-cached mode.  When in this
3095   mode the computed property will not automatically cache the return value.
3096
3097       MyApp.outsideService = Ember.Object.create({
3098         value: function() {
3099           return OutsideService.getValue();
3100         }.property().volatile()
3101       });
3102
3103   @method volatile
3104   @chainable
3105 */
3106 ComputedPropertyPrototype.volatile = function() {
3107   return this.cacheable(false);
3108 };
3109
3110 /**
3111   Sets the dependent keys on this computed property.  Pass any number of
3112   arguments containing key paths that this computed property depends on.
3113
3114       MyApp.president = Ember.Object.create({
3115         fullName: Ember.computed(function() {
3116           return this.get('firstName') + ' ' + this.get('lastName');
3117
3118           // Tell Ember.js that this computed property depends on firstName
3119           // and lastName
3120         }).property('firstName', 'lastName')
3121       });
3122
3123   @method property
3124   @param {String} path* zero or more property paths
3125   @chainable
3126 */
3127 ComputedPropertyPrototype.property = function() {
3128   var args = [];
3129   for (var i = 0, l = arguments.length; i < l; i++) {
3130     args.push(arguments[i]);
3131   }
3132   this._dependentKeys = args;
3133   return this;
3134 };
3135
3136 /**
3137   In some cases, you may want to annotate computed properties with additional
3138   metadata about how they function or what values they operate on. For example,
3139   computed property functions may close over variables that are then no longer
3140   available for introspection.
3141
3142   You can pass a hash of these values to a computed property like this:
3143
3144       person: function() {
3145         var personId = this.get('personId');
3146         return App.Person.create({ id: personId });
3147       }.property().meta({ type: App.Person })
3148
3149   The hash that you pass to the `meta()` function will be saved on the
3150   computed property descriptor under the `_meta` key. Ember runtime
3151   exposes a public API for retrieving these values from classes,
3152   via the `metaForProperty()` function.
3153
3154   @method meta
3155   @param {Hash} meta
3156   @chainable
3157 */
3158
3159 ComputedPropertyPrototype.meta = function(meta) {
3160   if (arguments.length === 0) {
3161     return this._meta || {};
3162   } else {
3163     this._meta = meta;
3164     return this;
3165   }
3166 };
3167
3168 /* impl descriptor API */
3169 ComputedPropertyPrototype.willWatch = function(obj, keyName) {
3170   // watch already creates meta for this instance
3171   var meta = obj[META_KEY];
3172   Ember.assert('watch should have setup meta to be writable', meta.source === obj);
3173   if (!(keyName in meta.cache)) {
3174     addDependentKeys(this, obj, keyName, meta);
3175   }
3176 };
3177
3178 ComputedPropertyPrototype.didUnwatch = function(obj, keyName) {
3179   var meta = obj[META_KEY];
3180   Ember.assert('unwatch should have setup meta to be writable', meta.source === obj);
3181   if (!(keyName in meta.cache)) {
3182     // unwatch already creates meta for this instance
3183     removeDependentKeys(this, obj, keyName, meta);
3184   }
3185 };
3186
3187 /* impl descriptor API */
3188 ComputedPropertyPrototype.didChange = function(obj, keyName) {
3189   // _suspended is set via a CP.set to ensure we don't clear
3190   // the cached value set by the setter
3191   if (this._cacheable && this._suspended !== obj) {
3192     var meta = metaFor(obj);
3193     if (keyName in meta.cache) {
3194       delete meta.cache[keyName];
3195       if (!meta.watching[keyName]) {
3196         removeDependentKeys(this, obj, keyName, meta);
3197       }
3198     }
3199   }
3200 };
3201
3202 /* impl descriptor API */
3203 ComputedPropertyPrototype.get = function(obj, keyName) {
3204   var ret, cache, meta;
3205   if (this._cacheable) {
3206     meta = metaFor(obj);
3207     cache = meta.cache;
3208     if (keyName in cache) { return cache[keyName]; }
3209     ret = cache[keyName] = this.func.call(obj, keyName);
3210     if (!meta.watching[keyName]) {
3211       addDependentKeys(this, obj, keyName, meta);
3212     }
3213   } else {
3214     ret = this.func.call(obj, keyName);
3215   }
3216   return ret;
3217 };
3218
3219 /* impl descriptor API */
3220 ComputedPropertyPrototype.set = function(obj, keyName, value) {
3221   var cacheable = this._cacheable,
3222       meta = metaFor(obj, cacheable),
3223       watched = meta.watching[keyName],
3224       oldSuspended = this._suspended,
3225       hadCachedValue = false,
3226       ret;
3227   this._suspended = obj;
3228   try {
3229     ret = this.func.call(obj, keyName, value);
3230
3231     if (cacheable && keyName in meta.cache) {
3232       if (meta.cache[keyName] === ret) {
3233         return;
3234       }
3235       hadCachedValue = true;
3236     }
3237
3238     if (watched) { Ember.propertyWillChange(obj, keyName); }
3239
3240     if (cacheable && hadCachedValue) {
3241       delete meta.cache[keyName];
3242     }
3243
3244     if (cacheable) {
3245       if (!watched && !hadCachedValue) {
3246         addDependentKeys(this, obj, keyName, meta);
3247       }
3248       meta.cache[keyName] = ret;
3249     }
3250
3251     if (watched) { Ember.propertyDidChange(obj, keyName); }
3252   } finally {
3253     this._suspended = oldSuspended;
3254   }
3255   return ret;
3256 };
3257
3258 /* called when property is defined */
3259 ComputedPropertyPrototype.setup = function(obj, keyName) {
3260   var meta = obj[META_KEY];
3261   if (meta && meta.watching[keyName]) {
3262     addDependentKeys(this, obj, keyName, metaFor(obj));
3263   }
3264 };
3265
3266 /* called before property is overridden */
3267 ComputedPropertyPrototype.teardown = function(obj, keyName) {
3268   var meta = metaFor(obj);
3269
3270   if (meta.watching[keyName] || keyName in meta.cache) {
3271     removeDependentKeys(this, obj, keyName, meta);
3272   }
3273
3274   if (this._cacheable) { delete meta.cache[keyName]; }
3275
3276   return null; // no value to restore
3277 };
3278
3279
3280 /**
3281   This helper returns a new property descriptor that wraps the passed
3282   computed property function.  You can use this helper to define properties
3283   with mixins or via Ember.defineProperty().
3284
3285   The function you pass will be used to both get and set property values.
3286   The function should accept two parameters, key and value.  If value is not
3287   undefined you should set the value first.  In either case return the
3288   current value of the property.
3289
3290   @method computed
3291   @for Ember
3292   @param {Function} func The computed property function.
3293   @return {Ember.ComputedProperty} property descriptor instance
3294 */
3295 Ember.computed = function(func) {
3296   var args;
3297
3298   if (arguments.length > 1) {
3299     args = a_slice.call(arguments, 0, -1);
3300     func = a_slice.call(arguments, -1)[0];
3301   }
3302
3303   var cp = new ComputedProperty(func);
3304
3305   if (args) {
3306     cp.property.apply(cp, args);
3307   }
3308
3309   return cp;
3310 };
3311
3312 /**
3313   Returns the cached value for a property, if one exists.
3314   This can be useful for peeking at the value of a computed
3315   property that is generated lazily, without accidentally causing
3316   it to be created.
3317
3318   @method cacheFor
3319   @for Ember
3320   @param {Object} obj the object whose property you want to check
3321   @param {String} key the name of the property whose cached value you want
3322                       to return
3323 */
3324 Ember.cacheFor = function cacheFor(obj, key) {
3325   var cache = metaFor(obj, false).cache;
3326
3327   if (cache && key in cache) {
3328     return cache[key];
3329   }
3330 };
3331
3332 /**
3333   @method computed.not
3334   @for Ember
3335   @param {String} dependentKey
3336 */
3337 Ember.computed.not = function(dependentKey) {
3338   return Ember.computed(dependentKey, function(key) {
3339     return !get(this, dependentKey);
3340   });
3341 };
3342
3343 /**
3344   @method computed.empty
3345   @for Ember
3346   @param {String} dependentKey
3347 */
3348 Ember.computed.empty = function(dependentKey) {
3349   return Ember.computed(dependentKey, function(key) {
3350     var val = get(this, dependentKey);
3351     return val === undefined || val === null || val === '' || (Ember.isArray(val) && get(val, 'length') === 0);
3352   });
3353 };
3354
3355 /**
3356   @method computed.bool
3357   @for Ember
3358   @param {String} dependentKey
3359 */
3360 Ember.computed.bool = function(dependentKey) {
3361   return Ember.computed(dependentKey, function(key) {
3362     return !!get(this, dependentKey);
3363   });
3364 };
3365
3366 })();
3367
3368
3369
3370 (function() {
3371 /**
3372 @module ember-metal
3373 */
3374
3375 var o_create = Ember.create,
3376     meta = Ember.meta,
3377     metaPath = Ember.metaPath,
3378     guidFor = Ember.guidFor,
3379     a_slice = [].slice;
3380
3381 /*
3382   The event system uses a series of nested hashes to store listeners on an
3383   object. When a listener is registered, or when an event arrives, these
3384   hashes are consulted to determine which target and action pair to invoke.
3385
3386   The hashes are stored in the object's meta hash, and look like this:
3387
3388       // Object's meta hash
3389       {
3390         listeners: {               // variable name: `listenerSet`
3391           "foo:changed": {         // variable name: `targetSet`
3392             [targetGuid]: {        // variable name: `actionSet`
3393               [methodGuid]: {      // variable name: `action`
3394                 target: [Object object],
3395                 method: [Function function]
3396               }
3397             }
3398           }
3399         }
3400       }
3401
3402 */
3403
3404 // Gets the set of all actions, keyed on the guid of each action's
3405 // method property.
3406 function actionSetFor(obj, eventName, target, writable) {
3407   return metaPath(obj, ['listeners', eventName, guidFor(target)], writable);
3408 }
3409
3410 // Gets the set of all targets, keyed on the guid of each action's
3411 // target property.
3412 function targetSetFor(obj, eventName) {
3413   var listenerSet = meta(obj, false).listeners;
3414   if (!listenerSet) { return false; }
3415
3416   return listenerSet[eventName] || false;
3417 }
3418
3419 // TODO: This knowledge should really be a part of the
3420 // meta system.
3421 var SKIP_PROPERTIES = { __ember_source__: true };
3422
3423 function iterateSet(targetSet, callback) {
3424   if (!targetSet) { return false; }
3425   // Iterate through all elements of the target set
3426   for(var targetGuid in targetSet) {
3427     if (SKIP_PROPERTIES[targetGuid]) { continue; }
3428
3429     var actionSet = targetSet[targetGuid];
3430     if (actionSet) {
3431       // Iterate through the elements of the action set
3432       for(var methodGuid in actionSet) {
3433         if (SKIP_PROPERTIES[methodGuid]) { continue; }
3434
3435         var action = actionSet[methodGuid];
3436         if (action) {
3437           if (callback(action) === true) {
3438             return true;
3439           }
3440         }
3441       }
3442     }
3443   }
3444   return false;
3445 }
3446
3447 function invokeAction(action, params, sender) {
3448   var method = action.method, target = action.target;
3449   // If there is no target, the target is the object
3450   // on which the event was fired.
3451   if (!target) { target = sender; }
3452   if ('string' === typeof method) { method = target[method]; }
3453   if (params) {
3454     method.apply(target, params);
3455   } else {
3456     method.apply(target);
3457   }
3458 }
3459
3460 function targetSetUnion(obj, eventName, targetSet) {
3461   iterateSet(targetSetFor(obj, eventName), function (action) {
3462     var targetGuid = guidFor(action.target),
3463         methodGuid = guidFor(action.method),
3464         actionSet = targetSet[targetGuid];
3465     if (!actionSet) actionSet = targetSet[targetGuid] = {};
3466     actionSet[methodGuid] = action;
3467   });
3468 }
3469
3470 function targetSetDiff(obj, eventName, targetSet) {
3471   var diffTargetSet = {};
3472   iterateSet(targetSetFor(obj, eventName), function (action) {
3473     var targetGuid = guidFor(action.target),
3474         methodGuid = guidFor(action.method),
3475         actionSet = targetSet[targetGuid],
3476         diffActionSet = diffTargetSet[targetGuid];
3477     if (!actionSet) actionSet = targetSet[targetGuid] = {};
3478     if (actionSet[methodGuid]) return;
3479     actionSet[methodGuid] = action;
3480     if (!diffActionSet) diffActionSet = diffTargetSet[targetGuid] = {};
3481     diffActionSet[methodGuid] = action;
3482   });
3483   return diffTargetSet;
3484 }
3485
3486 /**
3487   Add an event listener
3488
3489   @method addListener
3490   @for Ember
3491   @param obj
3492   @param {String} eventName
3493   @param {Object|Function} targetOrMethod A target object or a function
3494   @param {Function|String} method A function or the name of a function to be called on `target`
3495 */
3496 function addListener(obj, eventName, target, method, guid) {
3497   Ember.assert("You must pass at least an object and event name to Ember.addListener", !!obj && !!eventName);
3498
3499   if (!method && 'function' === typeof target) {
3500     method = target;
3501     target = null;
3502   }
3503
3504   var actionSet = actionSetFor(obj, eventName, target, true),
3505       // guid is used in case we wrapp given method to register
3506       // listener with method guid instead of the wrapper guid
3507       methodGuid = guid || guidFor(method);
3508
3509   if (!actionSet[methodGuid]) {
3510     actionSet[methodGuid] = { target: target, method: method };
3511   }
3512
3513   if ('function' === typeof obj.didAddListener) {
3514     obj.didAddListener(eventName, target, method);
3515   }
3516 }
3517
3518 /**
3519   Remove an event listener
3520
3521   Arguments should match those passed to {{#crossLink "Ember/addListener"}}{{/crossLink}}
3522
3523   @method removeListener
3524   @for Ember
3525   @param obj
3526   @param {String} eventName
3527   @param {Object|Function} targetOrMethod A target object or a function
3528   @param {Function|String} method A function or the name of a function to be called on `target`
3529 */
3530 function removeListener(obj, eventName, target, method) {
3531   Ember.assert("You must pass at least an object and event name to Ember.removeListener", !!obj && !!eventName);
3532
3533   if (!method && 'function' === typeof target) {
3534     method = target;
3535     target = null;
3536   }
3537
3538   function _removeListener(target, method) {
3539     var actionSet = actionSetFor(obj, eventName, target, true),
3540         methodGuid = guidFor(method);
3541
3542     // we can't simply delete this parameter, because if we do, we might
3543     // re-expose the property from the prototype chain.
3544     if (actionSet && actionSet[methodGuid]) { actionSet[methodGuid] = null; }
3545
3546     if ('function' === typeof obj.didRemoveListener) {
3547       obj.didRemoveListener(eventName, target, method);
3548     }
3549   }
3550
3551   if (method) {
3552     _removeListener(target, method);
3553   } else {
3554     iterateSet(targetSetFor(obj, eventName), function(action) {
3555       _removeListener(action.target, action.method);
3556     });
3557   }
3558 }
3559
3560 /**
3561   @private
3562
3563   Suspend listener during callback.
3564
3565   This should only be used by the target of the event listener
3566   when it is taking an action that would cause the event, e.g.
3567   an object might suspend its property change listener while it is
3568   setting that property.
3569
3570   @method suspendListener
3571   @for Ember
3572   @param obj
3573   @param {String} eventName
3574   @param {Object|Function} targetOrMethod A target object or a function
3575   @param {Function|String} method A function or the name of a function to be called on `target`
3576   @param {Function} callback
3577 */
3578 function suspendListener(obj, eventName, target, method, callback) {
3579   if (!method && 'function' === typeof target) {
3580     method = target;
3581     target = null;
3582   }
3583
3584   var actionSet = actionSetFor(obj, eventName, target, true),
3585       methodGuid = guidFor(method),
3586       action = actionSet && actionSet[methodGuid];
3587
3588   actionSet[methodGuid] = null;
3589   try {
3590     return callback.call(target);
3591   } finally {
3592     actionSet[methodGuid] = action;
3593   }
3594 }
3595
3596 /**
3597   @private
3598
3599   Suspend listener during callback.
3600
3601   This should only be used by the target of the event listener
3602   when it is taking an action that would cause the event, e.g.
3603   an object might suspend its property change listener while it is
3604   setting that property.
3605
3606   @method suspendListener
3607   @for Ember
3608   @param obj
3609   @param {Array} eventName Array of event names
3610   @param {Object|Function} targetOrMethod A target object or a function
3611   @param {Function|String} method A function or the name of a function to be called on `target`
3612   @param {Function} callback
3613 */
3614 function suspendListeners(obj, eventNames, target, method, callback) {
3615   if (!method && 'function' === typeof target) {
3616     method = target;
3617     target = null;
3618   }
3619
3620   var oldActions = [],
3621       actionSets = [],
3622       eventName, actionSet, methodGuid, action, i, l;
3623
3624   for (i=0, l=eventNames.length; i<l; i++) {
3625     eventName = eventNames[i];
3626     actionSet = actionSetFor(obj, eventName, target, true),
3627     methodGuid = guidFor(method);
3628
3629     oldActions.push(actionSet && actionSet[methodGuid]);
3630     actionSets.push(actionSet);
3631
3632     actionSet[methodGuid] = null;
3633   }
3634
3635   try {
3636     return callback.call(target);
3637   } finally {
3638     for (i=0, l=oldActions.length; i<l; i++) {
3639       eventName = eventNames[i];
3640       actionSets[i][methodGuid] = oldActions[i];
3641     }
3642   }
3643 }
3644
3645 /**
3646   @private
3647
3648   Return a list of currently watched events
3649
3650   @method watchedEvents
3651   @for Ember
3652   @param obj
3653 */
3654 function watchedEvents(obj) {
3655   var listeners = meta(obj, false).listeners, ret = [];
3656
3657   if (listeners) {
3658     for(var eventName in listeners) {
3659       if (!SKIP_PROPERTIES[eventName] && listeners[eventName]) {
3660         ret.push(eventName);
3661       }
3662     }
3663   }
3664   return ret;
3665 }
3666
3667 /**
3668   @method sendEvent
3669   @for Ember
3670   @param obj
3671   @param {String} eventName
3672   @param {Array} params
3673   @return true
3674 */
3675 function sendEvent(obj, eventName, params, targetSet) {
3676   // first give object a chance to handle it
3677   if (obj !== Ember && 'function' === typeof obj.sendEvent) {
3678     obj.sendEvent(eventName, params);
3679   }
3680
3681   if (!targetSet) targetSet = targetSetFor(obj, eventName);
3682
3683   iterateSet(targetSet, function (action) {
3684     invokeAction(action, params, obj);
3685   });
3686   return true;
3687 }
3688
3689 /**
3690   @private
3691   @method hasListeners
3692   @for Ember
3693   @param obj
3694   @param {String} eventName
3695 */
3696 function hasListeners(obj, eventName) {
3697   if (iterateSet(targetSetFor(obj, eventName), function() { return true; })) {
3698     return true;
3699   }
3700
3701   // no listeners!  might as well clean this up so it is faster later.
3702   var set = metaPath(obj, ['listeners'], true);
3703   set[eventName] = null;
3704
3705   return false;
3706 }
3707
3708 /**
3709   @private
3710   @method listenersFor
3711   @for Ember
3712   @param obj
3713   @param {String} eventName
3714 */
3715 function listenersFor(obj, eventName) {
3716   var ret = [];
3717   iterateSet(targetSetFor(obj, eventName), function (action) {
3718     ret.push([action.target, action.method]);
3719   });
3720   return ret;
3721 }
3722
3723 Ember.addListener = addListener;
3724 Ember.removeListener = removeListener;
3725 Ember._suspendListener = suspendListener;
3726 Ember._suspendListeners = suspendListeners;
3727 Ember.sendEvent = sendEvent;
3728 Ember.hasListeners = hasListeners;
3729 Ember.watchedEvents = watchedEvents;
3730 Ember.listenersFor = listenersFor;
3731 Ember.listenersDiff = targetSetDiff;
3732 Ember.listenersUnion = targetSetUnion;
3733 })();
3734
3735
3736
3737 (function() {
3738 // Ember.Logger
3739 // Ember.watch.flushPending
3740 // Ember.beginPropertyChanges, Ember.endPropertyChanges
3741 // Ember.guidFor
3742
3743 /**
3744 @module ember-metal
3745 */
3746
3747 // ..........................................................
3748 // HELPERS
3749 //
3750
3751 var slice = [].slice,
3752     forEach = Ember.ArrayPolyfills.forEach;
3753
3754 // invokes passed params - normalizing so you can pass target/func,
3755 // target/string or just func
3756 function invoke(target, method, args, ignore) {
3757
3758   if (method === undefined) {
3759     method = target;
3760     target = undefined;
3761   }
3762
3763   if ('string' === typeof method) { method = target[method]; }
3764   if (args && ignore > 0) {
3765     args = args.length > ignore ? slice.call(args, ignore) : null;
3766   }
3767
3768   return Ember.handleErrors(function() {
3769     // IE8's Function.prototype.apply doesn't accept undefined/null arguments.
3770     return method.apply(target || this, args || []);
3771   }, this);
3772 }
3773
3774
3775 // ..........................................................
3776 // RUNLOOP
3777 //
3778
3779 var timerMark; // used by timers...
3780
3781 /**
3782 Ember RunLoop (Private)
3783
3784 @class RunLoop
3785 @namespace Ember
3786 @private
3787 @constructor
3788 */
3789 var RunLoop = function(prev) {
3790   this._prev = prev || null;
3791   this.onceTimers = {};
3792 };
3793
3794 RunLoop.prototype = {
3795   /**
3796     @method end
3797   */
3798   end: function() {
3799     this.flush();
3800   },
3801
3802   /**
3803     @method prev
3804   */
3805   prev: function() {
3806     return this._prev;
3807   },
3808
3809   // ..........................................................
3810   // Delayed Actions
3811   //
3812
3813   /**
3814     @method schedule
3815     @param {String} queueName
3816     @param target
3817     @param method
3818   */
3819   schedule: function(queueName, target, method) {
3820     var queues = this._queues, queue;
3821     if (!queues) { queues = this._queues = {}; }
3822     queue = queues[queueName];
3823     if (!queue) { queue = queues[queueName] = []; }
3824
3825     var args = arguments.length > 3 ? slice.call(arguments, 3) : null;
3826     queue.push({ target: target, method: method, args: args });
3827     return this;
3828   },
3829
3830   /**
3831     @method flush
3832     @param {String} queueName
3833   */
3834   flush: function(queueName) {
3835     var queueNames, idx, len, queue, log;
3836
3837     if (!this._queues) { return this; } // nothing to do
3838
3839     function iter(item) {
3840       invoke(item.target, item.method, item.args);
3841     }
3842
3843     Ember.watch.flushPending(); // make sure all chained watchers are setup
3844
3845     if (queueName) {
3846       while (this._queues && (queue = this._queues[queueName])) {
3847         this._queues[queueName] = null;
3848
3849         // the sync phase is to allow property changes to propagate.  don't
3850         // invoke observers until that is finished.
3851         if (queueName === 'sync') {
3852           log = Ember.LOG_BINDINGS;
3853           if (log) { Ember.Logger.log('Begin: Flush Sync Queue'); }
3854
3855           Ember.beginPropertyChanges();
3856           try {
3857             forEach.call(queue, iter);
3858           } finally {
3859             Ember.endPropertyChanges();
3860           }
3861
3862           if (log) { Ember.Logger.log('End: Flush Sync Queue'); }
3863
3864         } else {
3865           forEach.call(queue, iter);
3866         }
3867       }
3868
3869     } else {
3870       queueNames = Ember.run.queues;
3871       len = queueNames.length;
3872       idx = 0;
3873
3874       outerloop:
3875       while (idx < len) {
3876         queueName = queueNames[idx];
3877         queue = this._queues && this._queues[queueName];
3878         delete this._queues[queueName];
3879
3880         if (queue) {
3881           // the sync phase is to allow property changes to propagate.  don't
3882           // invoke observers until that is finished.
3883           if (queueName === 'sync') {
3884             log = Ember.LOG_BINDINGS;
3885             if (log) { Ember.Logger.log('Begin: Flush Sync Queue'); }
3886
3887             Ember.beginPropertyChanges();
3888             try {
3889               forEach.call(queue, iter);
3890             } finally {
3891               Ember.endPropertyChanges();
3892             }
3893
3894             if (log) { Ember.Logger.log('End: Flush Sync Queue'); }
3895           } else {
3896             forEach.call(queue, iter);
3897           }
3898         }
3899
3900         // Loop through prior queues
3901         for (var i = 0; i <= idx; i++) {
3902           if (this._queues && this._queues[queueNames[i]]) {
3903             // Start over at the first queue with contents
3904             idx = i;
3905             continue outerloop;
3906           }
3907         }
3908
3909         idx++;
3910       }
3911     }
3912
3913     timerMark = null;
3914
3915     return this;
3916   }
3917
3918 };
3919
3920 Ember.RunLoop = RunLoop;
3921
3922 // ..........................................................
3923 // Ember.run - this is ideally the only public API the dev sees
3924 //
3925
3926 /**
3927   Runs the passed target and method inside of a RunLoop, ensuring any
3928   deferred actions including bindings and views updates are flushed at the
3929   end.
3930
3931   Normally you should not need to invoke this method yourself.  However if
3932   you are implementing raw event handlers when interfacing with other
3933   libraries or plugins, you should probably wrap all of your code inside this
3934   call.
3935
3936       Ember.run(function(){
3937         // code to be execute within a RunLoop 
3938       });
3939
3940   @class run
3941   @namespace Ember
3942   @static
3943   @constructor
3944   @param {Object} [target] target of method to call
3945   @param {Function|String} method Method to invoke.
3946     May be a function or a string.  If you pass a string
3947     then it will be looked up on the passed target.
3948   @param {Object} [args*] Any additional arguments you wish to pass to the method.
3949   @return {Object} return value from invoking the passed function.
3950 */
3951 Ember.run = function(target, method) {
3952   var ret, loop;
3953   run.begin();
3954   try {
3955     if (target || method) { ret = invoke(target, method, arguments, 2); }
3956   } finally {
3957     run.end();
3958   }
3959   return ret;
3960 };
3961
3962 var run = Ember.run;
3963
3964
3965 /**
3966   Begins a new RunLoop.  Any deferred actions invoked after the begin will
3967   be buffered until you invoke a matching call to Ember.run.end().  This is
3968   an lower-level way to use a RunLoop instead of using Ember.run().
3969
3970       Ember.run.begin();
3971       // code to be execute within a RunLoop 
3972       Ember.run.end();
3973
3974   @method begin
3975   @return {void}
3976 */
3977 Ember.run.begin = function() {
3978   run.currentRunLoop = new RunLoop(run.currentRunLoop);
3979 };
3980
3981 /**
3982   Ends a RunLoop.  This must be called sometime after you call Ember.run.begin()
3983   to flush any deferred actions.  This is a lower-level way to use a RunLoop
3984   instead of using Ember.run().
3985
3986       Ember.run.begin();
3987       // code to be execute within a RunLoop 
3988       Ember.run.end();
3989
3990   @method end
3991   @return {void}
3992 */
3993 Ember.run.end = function() {
3994   Ember.assert('must have a current run loop', run.currentRunLoop);
3995   try {
3996     run.currentRunLoop.end();
3997   }
3998   finally {
3999     run.currentRunLoop = run.currentRunLoop.prev();
4000   }
4001 };
4002
4003 /**
4004   Array of named queues.  This array determines the order in which queues
4005   are flushed at the end of the RunLoop.  You can define your own queues by
4006   simply adding the queue name to this array.  Normally you should not need
4007   to inspect or modify this property.
4008
4009   @property queues
4010   @type Array
4011   @default ['sync', 'actions', 'destroy', 'timers']
4012 */
4013 Ember.run.queues = ['sync', 'actions', 'destroy', 'timers'];
4014
4015 /**
4016   Adds the passed target/method and any optional arguments to the named
4017   queue to be executed at the end of the RunLoop.  If you have not already
4018   started a RunLoop when calling this method one will be started for you
4019   automatically.
4020
4021   At the end of a RunLoop, any methods scheduled in this way will be invoked.
4022   Methods will be invoked in an order matching the named queues defined in
4023   the run.queues property.
4024
4025       Ember.run.schedule('timers', this, function(){
4026         // this will be executed at the end of the RunLoop, when timers are run
4027         console.log("scheduled on timers queue");
4028       });
4029       Ember.run.schedule('sync', this, function(){
4030         // this will be executed at the end of the RunLoop, when bindings are synced
4031         console.log("scheduled on sync queue");
4032       });
4033       // Note the functions will be run in order based on the run queues order. Output would be:
4034       //   scheduled on sync queue
4035       //   scheduled on timers queue
4036
4037   @method schedule
4038   @param {String} queue The name of the queue to schedule against.
4039     Default queues are 'sync' and 'actions'
4040
4041   @param {Object} [target] target object to use as the context when invoking a method.
4042
4043   @param {String|Function} method The method to invoke.  If you pass a string it
4044     will be resolved on the target object at the time the scheduled item is
4045     invoked allowing you to change the target function.
4046
4047   @param {Object} [arguments*] Optional arguments to be passed to the queued method.
4048
4049   @return {void}
4050 */
4051 Ember.run.schedule = function(queue, target, method) {
4052   var loop = run.autorun();
4053   loop.schedule.apply(loop, arguments);
4054 };
4055
4056 var scheduledAutorun;
4057 function autorun() {
4058   scheduledAutorun = null;
4059   if (run.currentRunLoop) { run.end(); }
4060 }
4061
4062 // Used by global test teardown
4063 Ember.run.hasScheduledTimers = function() {
4064   return !!(scheduledAutorun || scheduledLater || scheduledNext);
4065 };
4066
4067 // Used by global test teardown
4068 Ember.run.cancelTimers = function () {
4069   if (scheduledAutorun) {
4070     clearTimeout(scheduledAutorun);
4071     scheduledAutorun = null;
4072   }
4073   if (scheduledLater) {
4074     clearTimeout(scheduledLater);
4075     scheduledLater = null;
4076   }
4077   if (scheduledNext) {
4078     clearTimeout(scheduledNext);
4079     scheduledNext = null;
4080   }
4081   timers = {};
4082 };
4083
4084 /**
4085   Begins a new RunLoop if necessary and schedules a timer to flush the
4086   RunLoop at a later time.  This method is used by parts of Ember to
4087   ensure the RunLoop always finishes.  You normally do not need to call this
4088   method directly.  Instead use Ember.run().
4089
4090
4091   @method autorun
4092   @example
4093     Ember.run.autorun();
4094   @return {Ember.RunLoop} the new current RunLoop
4095 */
4096 Ember.run.autorun = function() {
4097   if (!run.currentRunLoop) {
4098     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);
4099
4100     run.begin();
4101
4102     if (!scheduledAutorun) {
4103       scheduledAutorun = setTimeout(autorun, 1);
4104     }
4105   }
4106
4107   return run.currentRunLoop;
4108 };
4109
4110 /**
4111   Immediately flushes any events scheduled in the 'sync' queue.  Bindings
4112   use this queue so this method is a useful way to immediately force all
4113   bindings in the application to sync.
4114
4115   You should call this method anytime you need any changed state to propagate
4116   throughout the app immediately without repainting the UI.
4117
4118       Ember.run.sync();
4119
4120   @method sync
4121   @return {void}
4122 */
4123 Ember.run.sync = function() {
4124   run.autorun();
4125   run.currentRunLoop.flush('sync');
4126 };
4127
4128 // ..........................................................
4129 // TIMERS
4130 //
4131
4132 var timers = {}; // active timers...
4133
4134 var scheduledLater;
4135 function invokeLaterTimers() {
4136   scheduledLater = null;
4137   var now = (+ new Date()), earliest = -1;
4138   for (var key in timers) {
4139     if (!timers.hasOwnProperty(key)) { continue; }
4140     var timer = timers[key];
4141     if (timer && timer.expires) {
4142       if (now >= timer.expires) {
4143         delete timers[key];
4144         invoke(timer.target, timer.method, timer.args, 2);
4145       } else {
4146         if (earliest<0 || (timer.expires < earliest)) earliest=timer.expires;
4147       }
4148     }
4149   }
4150
4151   // schedule next timeout to fire...
4152   if (earliest > 0) { scheduledLater = setTimeout(invokeLaterTimers, earliest-(+ new Date())); }
4153 }
4154
4155 /**
4156   Invokes the passed target/method and optional arguments after a specified
4157   period if time.  The last parameter of this method must always be a number
4158   of milliseconds.
4159
4160   You should use this method whenever you need to run some action after a
4161   period of time instead of using setTimeout().  This method will ensure that
4162   items that expire during the same script execution cycle all execute
4163   together, which is often more efficient than using a real setTimeout.
4164
4165       Ember.run.later(myContext, function(){
4166         // code here will execute within a RunLoop in about 500ms with this == myContext
4167       }, 500);
4168
4169   @method later
4170   @param {Object} [target] target of method to invoke
4171
4172   @param {Function|String} method The method to invoke.
4173     If you pass a string it will be resolved on the
4174     target at the time the method is invoked.
4175
4176   @param {Object} [args*] Optional arguments to pass to the timeout.
4177
4178   @param {Number} wait
4179     Number of milliseconds to wait.
4180
4181   @return {String} a string you can use to cancel the timer in
4182     {{#crossLink "Ember/run.cancel"}}{{/crossLink}} later.
4183 */
4184 Ember.run.later = function(target, method) {
4185   var args, expires, timer, guid, wait;
4186
4187   // setTimeout compatibility...
4188   if (arguments.length===2 && 'function' === typeof target) {
4189     wait   = method;
4190     method = target;
4191     target = undefined;
4192     args   = [target, method];
4193   } else {
4194     args = slice.call(arguments);
4195     wait = args.pop();
4196   }
4197
4198   expires = (+ new Date()) + wait;
4199   timer   = { target: target, method: method, expires: expires, args: args };
4200   guid    = Ember.guidFor(timer);
4201   timers[guid] = timer;
4202   run.once(timers, invokeLaterTimers);
4203   return guid;
4204 };
4205
4206 function invokeOnceTimer(guid, onceTimers) {
4207   if (onceTimers[this.tguid]) { delete onceTimers[this.tguid][this.mguid]; }
4208   if (timers[guid]) { invoke(this.target, this.method, this.args); }
4209   delete timers[guid];
4210 }
4211
4212 function scheduleOnce(queue, target, method, args) {
4213   var tguid = Ember.guidFor(target),
4214     mguid = Ember.guidFor(method),
4215     onceTimers = run.autorun().onceTimers,
4216     guid = onceTimers[tguid] && onceTimers[tguid][mguid],
4217     timer;
4218
4219   if (guid && timers[guid]) {
4220     timers[guid].args = args; // replace args
4221   } else {
4222     timer = {
4223       target: target,
4224       method: method,
4225       args:   args,
4226       tguid:  tguid,
4227       mguid:  mguid
4228     };
4229
4230     guid  = Ember.guidFor(timer);
4231     timers[guid] = timer;
4232     if (!onceTimers[tguid]) { onceTimers[tguid] = {}; }
4233     onceTimers[tguid][mguid] = guid; // so it isn't scheduled more than once
4234
4235     run.schedule(queue, timer, invokeOnceTimer, guid, onceTimers);
4236   }
4237
4238   return guid;
4239 }
4240
4241 /**
4242   Schedules an item to run one time during the current RunLoop.  Calling
4243   this method with the same target/method combination will have no effect.
4244
4245   Note that although you can pass optional arguments these will not be
4246   considered when looking for duplicates.  New arguments will replace previous
4247   calls.
4248
4249       Ember.run(function(){
4250         var doFoo = function() { foo(); }
4251         Ember.run.once(myContext, doFoo);
4252         Ember.run.once(myContext, doFoo);
4253         // doFoo will only be executed once at the end of the RunLoop
4254       });
4255
4256   @method once
4257   @param {Object} [target] target of method to invoke
4258
4259   @param {Function|String} method The method to invoke.
4260     If you pass a string it will be resolved on the
4261     target at the time the method is invoked.
4262
4263   @param {Object} [args*] Optional arguments to pass to the timeout.
4264
4265
4266   @return {Object} timer
4267 */
4268 Ember.run.once = function(target, method) {
4269   return scheduleOnce('actions', target, method, slice.call(arguments, 2));
4270 };
4271
4272 Ember.run.scheduleOnce = function(queue, target, method, args) {
4273   return scheduleOnce(queue, target, method, slice.call(arguments, 3));
4274 };
4275
4276 var scheduledNext;
4277 function invokeNextTimers() {
4278   scheduledNext = null;
4279   for(var key in timers) {
4280     if (!timers.hasOwnProperty(key)) { continue; }
4281     var timer = timers[key];
4282     if (timer.next) {
4283       delete timers[key];
4284       invoke(timer.target, timer.method, timer.args, 2);
4285     }
4286   }
4287 }
4288
4289 /**
4290   Schedules an item to run after control has been returned to the system.
4291   This is often equivalent to calling setTimeout(function...,1).
4292
4293       Ember.run.next(myContext, function(){
4294         // code to be executed in the next RunLoop, which will be scheduled after the current one
4295       });
4296
4297   @method next
4298   @param {Object} [target] target of method to invoke
4299
4300   @param {Function|String} method The method to invoke.
4301     If you pass a string it will be resolved on the
4302     target at the time the method is invoked.
4303
4304   @param {Object} [args*] Optional arguments to pass to the timeout.
4305
4306   @return {Object} timer
4307 */
4308 Ember.run.next = function(target, method) {
4309   var guid,
4310       timer = {
4311         target: target,
4312         method: method,
4313         args: slice.call(arguments),
4314         next: true
4315       };
4316
4317   guid = Ember.guidFor(timer);
4318   timers[guid] = timer;
4319
4320   if (!scheduledNext) { scheduledNext = setTimeout(invokeNextTimers, 1); }
4321   return guid;
4322 };
4323
4324 /**
4325   Cancels a scheduled item.  Must be a value returned by `Ember.run.later()`,
4326   `Ember.run.once()`, or `Ember.run.next()`.
4327
4328       var runNext = Ember.run.next(myContext, function(){
4329         // will not be executed
4330       });
4331       Ember.run.cancel(runNext);
4332
4333       var runLater = Ember.run.later(myContext, function(){
4334         // will not be executed
4335       }, 500);
4336       Ember.run.cancel(runLater);
4337
4338       var runOnce = Ember.run.once(myContext, function(){
4339         // will not be executed
4340       });
4341       Ember.run.cancel(runOnce);
4342
4343   @method cancel
4344   @param {Object} timer Timer object to cancel
4345   @return {void}
4346 */
4347 Ember.run.cancel = function(timer) {
4348   delete timers[timer];
4349 };
4350
4351 })();
4352
4353
4354
4355 (function() {
4356 // Ember.Logger
4357 // get, set, trySet
4358 // guidFor, isArray, meta
4359 // addObserver, removeObserver
4360 // Ember.run.schedule
4361 /**
4362 @module ember-metal
4363 */
4364
4365 // ..........................................................
4366 // CONSTANTS
4367 //
4368
4369 /**
4370   Debug parameter you can turn on. This will log all bindings that fire to
4371   the console. This should be disabled in production code. Note that you
4372   can also enable this from the console or temporarily.
4373
4374   @property LOG_BINDINGS
4375   @for Ember
4376   @type Boolean
4377   @default false
4378 */
4379 Ember.LOG_BINDINGS = false || !!Ember.ENV.LOG_BINDINGS;
4380
4381 var get     = Ember.get,
4382     set     = Ember.set,
4383     guidFor = Ember.guidFor,
4384     isGlobalPath = Ember.isGlobalPath;
4385
4386
4387 function getWithGlobals(obj, path) {
4388   return get(isGlobalPath(path) ? Ember.lookup : obj, path);
4389 }
4390
4391 // ..........................................................
4392 // BINDING
4393 //
4394
4395 var Binding = function(toPath, fromPath) {
4396   this._direction = 'fwd';
4397   this._from = fromPath;
4398   this._to   = toPath;
4399   this._directionMap = Ember.Map.create();
4400 };
4401
4402 /**
4403 @class Binding
4404 @namespace Ember
4405 */
4406
4407 Binding.prototype = {
4408   /**
4409     This copies the Binding so it can be connected to another object.
4410
4411     @method copy
4412     @return {Ember.Binding}
4413   */
4414   copy: function () {
4415     var copy = new Binding(this._to, this._from);
4416     if (this._oneWay) { copy._oneWay = true; }
4417     return copy;
4418   },
4419
4420   // ..........................................................
4421   // CONFIG
4422   //
4423
4424   /**
4425     This will set "from" property path to the specified value. It will not
4426     attempt to resolve this property path to an actual object until you
4427     connect the binding.
4428
4429     The binding will search for the property path starting at the root object
4430     you pass when you connect() the binding.  It follows the same rules as
4431     `get()` - see that method for more information.
4432
4433     @method from
4434     @param {String} propertyPath the property path to connect to
4435     @return {Ember.Binding} receiver
4436   */
4437   from: function(path) {
4438     this._from = path;
4439     return this;
4440   },
4441
4442   /**
4443     This will set the "to" property path to the specified value. It will not
4444     attempt to resolve this property path to an actual object until you
4445     connect the binding.
4446
4447     The binding will search for the property path starting at the root object
4448     you pass when you connect() the binding.  It follows the same rules as
4449     `get()` - see that method for more information.
4450
4451     @method to
4452     @param {String|Tuple} propertyPath A property path or tuple
4453     @return {Ember.Binding} this
4454   */
4455   to: function(path) {
4456     this._to = path;
4457     return this;
4458   },
4459
4460   /**
4461     Configures the binding as one way. A one-way binding will relay changes
4462     on the "from" side to the "to" side, but not the other way around. This
4463     means that if you change the "to" side directly, the "from" side may have
4464     a different value.
4465
4466     @method oneWay
4467     @return {Ember.Binding} receiver
4468   */
4469   oneWay: function() {
4470     this._oneWay = true;
4471     return this;
4472   },
4473
4474   toString: function() {
4475     var oneWay = this._oneWay ? '[oneWay]' : '';
4476     return "Ember.Binding<" + guidFor(this) + ">(" + this._from + " -> " + this._to + ")" + oneWay;
4477   },
4478
4479   // ..........................................................
4480   // CONNECT AND SYNC
4481   //
4482
4483   /**
4484     Attempts to connect this binding instance so that it can receive and relay
4485     changes. This method will raise an exception if you have not set the
4486     from/to properties yet.
4487
4488     @method connect
4489     @param {Object} obj The root object for this binding.
4490     @return {Ember.Binding} this
4491   */
4492   connect: function(obj) {
4493     Ember.assert('Must pass a valid object to Ember.Binding.connect()', !!obj);
4494
4495     var fromPath = this._from, toPath = this._to;
4496     Ember.trySet(obj, toPath, getWithGlobals(obj, fromPath));
4497
4498     // add an observer on the object to be notified when the binding should be updated
4499     Ember.addObserver(obj, fromPath, this, this.fromDidChange);
4500
4501     // if the binding is a two-way binding, also set up an observer on the target
4502     if (!this._oneWay) { Ember.addObserver(obj, toPath, this, this.toDidChange); }
4503
4504     this._readyToSync = true;
4505
4506     return this;
4507   },
4508
4509   /**
4510     Disconnects the binding instance. Changes will no longer be relayed. You
4511     will not usually need to call this method.
4512
4513     @method disconnect
4514     @param {Object} obj The root object you passed when connecting the binding.
4515     @return {Ember.Binding} this
4516   */
4517   disconnect: function(obj) {
4518     Ember.assert('Must pass a valid object to Ember.Binding.disconnect()', !!obj);
4519
4520     var twoWay = !this._oneWay;
4521
4522     // remove an observer on the object so we're no longer notified of
4523     // changes that should update bindings.
4524     Ember.removeObserver(obj, this._from, this, this.fromDidChange);
4525
4526     // if the binding is two-way, remove the observer from the target as well
4527     if (twoWay) { Ember.removeObserver(obj, this._to, this, this.toDidChange); }
4528
4529     this._readyToSync = false; // disable scheduled syncs...
4530     return this;
4531   },
4532
4533   // ..........................................................
4534   // PRIVATE
4535   //
4536
4537   /* called when the from side changes */
4538   fromDidChange: function(target) {
4539     this._scheduleSync(target, 'fwd');
4540   },
4541
4542   /* called when the to side changes */
4543   toDidChange: function(target) {
4544     this._scheduleSync(target, 'back');
4545   },
4546
4547   _scheduleSync: function(obj, dir) {
4548     var directionMap = this._directionMap;
4549     var existingDir = directionMap.get(obj);
4550
4551     // if we haven't scheduled the binding yet, schedule it
4552     if (!existingDir) {
4553       Ember.run.schedule('sync', this, this._sync, obj);
4554       directionMap.set(obj, dir);
4555     }
4556
4557     // If both a 'back' and 'fwd' sync have been scheduled on the same object,
4558     // default to a 'fwd' sync so that it remains deterministic.
4559     if (existingDir === 'back' && dir === 'fwd') {
4560       directionMap.set(obj, 'fwd');
4561     }
4562   },
4563
4564   _sync: function(obj) {
4565     var log = Ember.LOG_BINDINGS;
4566
4567     // don't synchronize destroyed objects or disconnected bindings
4568     if (obj.isDestroyed || !this._readyToSync) { return; }
4569
4570     // get the direction of the binding for the object we are
4571     // synchronizing from
4572     var directionMap = this._directionMap;
4573     var direction = directionMap.get(obj);
4574
4575     var fromPath = this._from, toPath = this._to;
4576
4577     directionMap.remove(obj);
4578
4579     // if we're synchronizing from the remote object...
4580     if (direction === 'fwd') {
4581       var fromValue = getWithGlobals(obj, this._from);
4582       if (log) {
4583         Ember.Logger.log(' ', this.toString(), '->', fromValue, obj);
4584       }
4585       if (this._oneWay) {
4586         Ember.trySet(obj, toPath, fromValue);
4587       } else {
4588         Ember._suspendObserver(obj, toPath, this, this.toDidChange, function () {
4589           Ember.trySet(obj, toPath, fromValue);
4590         });
4591       }
4592     // if we're synchronizing *to* the remote object
4593     } else if (direction === 'back') {
4594       var toValue = get(obj, this._to);
4595       if (log) {
4596         Ember.Logger.log(' ', this.toString(), '<-', toValue, obj);
4597       }
4598       Ember._suspendObserver(obj, fromPath, this, this.fromDidChange, function () {
4599         Ember.trySet(Ember.isGlobalPath(fromPath) ? Ember.lookup : obj, fromPath, toValue);
4600       });
4601     }
4602   }
4603
4604 };
4605
4606 function mixinProperties(to, from) {
4607   for (var key in from) {
4608     if (from.hasOwnProperty(key)) {
4609       to[key] = from[key];
4610     }
4611   }
4612 }
4613
4614 mixinProperties(Binding, {
4615
4616   /**
4617     See {{#crossLink "Ember.Binding/from"}}{{/crossLink}}
4618
4619     @method from
4620     @static
4621   */
4622   from: function() {
4623     var C = this, binding = new C();
4624     return binding.from.apply(binding, arguments);
4625   },
4626
4627   /**
4628     See {{#crossLink "Ember.Binding/to"}}{{/crossLink}}
4629
4630     @method to
4631     @static
4632   */
4633   to: function() {
4634     var C = this, binding = new C();
4635     return binding.to.apply(binding, arguments);
4636   },
4637
4638   /**
4639     Creates a new Binding instance and makes it apply in a single direction.
4640     A one-way binding will relay changes on the "from" side object (supplied
4641     as the `from` argument) the "to" side, but not the other way around.
4642     This means that if you change the "to" side directly, the "from" side may have
4643     a different value.
4644
4645     See {{#crossLink "Binding/oneWay"}}{{/crossLink}}
4646
4647     @method oneWay
4648     @param {String} from from path.
4649     @param {Boolean} [flag] (Optional) passing nothing here will make the binding oneWay.  You can
4650       instead pass false to disable oneWay, making the binding two way again.
4651   */
4652   oneWay: function(from, flag) {
4653     var C = this, binding = new C(null, from);
4654     return binding.oneWay(flag);
4655   }
4656
4657 });
4658
4659 /**
4660   An Ember.Binding connects the properties of two objects so that whenever the
4661   value of one property changes, the other property will be changed also.
4662
4663   ## Automatic Creation of Bindings with `/^*Binding/`-named Properties
4664   You do not usually create Binding objects directly but instead describe
4665   bindings in your class or object definition using automatic binding detection.
4666
4667   Properties ending in a `Binding` suffix will be converted to Ember.Binding instances.
4668   The value of this property should be a string representing a path to another object or
4669   a custom binding instanced created using Binding helpers (see "Customizing Your Bindings"):
4670
4671       valueBinding: "MyApp.someController.title"
4672
4673   This will create a binding from `MyApp.someController.title` to the `value`
4674   property of your object instance automatically. Now the two values will be
4675   kept in sync.
4676
4677   ## One Way Bindings
4678
4679   One especially useful binding customization you can use is the `oneWay()`
4680   helper. This helper tells Ember that you are only interested in
4681   receiving changes on the object you are binding from. For example, if you
4682   are binding to a preference and you want to be notified if the preference
4683   has changed, but your object will not be changing the preference itself, you
4684   could do:
4685
4686       bigTitlesBinding: Ember.Binding.oneWay("MyApp.preferencesController.bigTitles")
4687
4688   This way if the value of MyApp.preferencesController.bigTitles changes the
4689   "bigTitles" property of your object will change also. However, if you
4690   change the value of your "bigTitles" property, it will not update the
4691   preferencesController.
4692
4693   One way bindings are almost twice as fast to setup and twice as fast to
4694   execute because the binding only has to worry about changes to one side.
4695
4696   You should consider using one way bindings anytime you have an object that
4697   may be created frequently and you do not intend to change a property; only
4698   to monitor it for changes. (such as in the example above).
4699
4700   ## Adding Bindings Manually
4701
4702   All of the examples above show you how to configure a custom binding, but
4703   the result of these customizations will be a binding template, not a fully
4704   active Binding instance. The binding will actually become active only when you
4705   instantiate the object the binding belongs to. It is useful however, to
4706   understand what actually happens when the binding is activated.
4707
4708   For a binding to function it must have at least a "from" property and a "to"
4709   property. The from property path points to the object/key that you want to
4710   bind from while the to path points to the object/key you want to bind to.
4711
4712   When you define a custom binding, you are usually describing the property
4713   you want to bind from (such as "MyApp.someController.value" in the examples
4714   above). When your object is created, it will automatically assign the value
4715   you want to bind "to" based on the name of your binding key. In the
4716   examples above, during init, Ember objects will effectively call
4717   something like this on your binding:
4718
4719       binding = Ember.Binding.from(this.valueBinding).to("value");
4720
4721   This creates a new binding instance based on the template you provide, and
4722   sets the to path to the "value" property of the new object. Now that the
4723   binding is fully configured with a "from" and a "to", it simply needs to be
4724   connected to become active. This is done through the connect() method:
4725
4726       binding.connect(this);
4727
4728   Note that when you connect a binding you pass the object you want it to be
4729   connected to.  This object will be used as the root for both the from and
4730   to side of the binding when inspecting relative paths.  This allows the
4731   binding to be automatically inherited by subclassed objects as well.
4732
4733   Now that the binding is connected, it will observe both the from and to side
4734   and relay changes.
4735
4736   If you ever needed to do so (you almost never will, but it is useful to
4737   understand this anyway), you could manually create an active binding by
4738   using the Ember.bind() helper method. (This is the same method used by
4739   to setup your bindings on objects):
4740
4741       Ember.bind(MyApp.anotherObject, "value", "MyApp.someController.value");
4742
4743   Both of these code fragments have the same effect as doing the most friendly
4744   form of binding creation like so:
4745
4746       MyApp.anotherObject = Ember.Object.create({
4747         valueBinding: "MyApp.someController.value",
4748
4749         // OTHER CODE FOR THIS OBJECT...
4750
4751       });
4752
4753   Ember's built in binding creation method makes it easy to automatically
4754   create bindings for you. You should always use the highest-level APIs
4755   available, even if you understand how it works underneath.
4756
4757   @class Binding
4758   @namespace Ember
4759   @since Ember 0.9
4760 */
4761 Ember.Binding = Binding;
4762
4763
4764 /**
4765   Global helper method to create a new binding.  Just pass the root object
4766   along with a to and from path to create and connect the binding.
4767
4768   @method bind
4769   @for Ember
4770   @param {Object} obj The root object of the transform.
4771
4772   @param {String} to The path to the 'to' side of the binding.
4773     Must be relative to obj.
4774
4775   @param {String} from The path to the 'from' side of the binding.
4776     Must be relative to obj or a global path.
4777
4778   @return {Ember.Binding} binding instance
4779 */
4780 Ember.bind = function(obj, to, from) {
4781   return new Ember.Binding(to, from).connect(obj);
4782 };
4783
4784 /**
4785   @method oneWay
4786   @for Ember
4787   @param {Object} obj The root object of the transform.
4788
4789   @param {String} to The path to the 'to' side of the binding.
4790     Must be relative to obj.
4791
4792   @param {String} from The path to the 'from' side of the binding.
4793     Must be relative to obj or a global path.
4794
4795   @return {Ember.Binding} binding instance
4796 */
4797 Ember.oneWay = function(obj, to, from) {
4798   return new Ember.Binding(to, from).oneWay().connect(obj);
4799 };
4800
4801 })();
4802
4803
4804
4805 (function() {
4806 /**
4807 @module ember-metal
4808 */
4809
4810 var Mixin, REQUIRED, Alias,
4811     classToString, superClassString,
4812     a_map = Ember.ArrayPolyfills.map,
4813     a_indexOf = Ember.ArrayPolyfills.indexOf,
4814     a_forEach = Ember.ArrayPolyfills.forEach,
4815     a_slice = [].slice,
4816     EMPTY_META = {}, // dummy for non-writable meta
4817     META_SKIP = { __emberproto__: true, __ember_count__: true },
4818     o_create = Ember.create,
4819     defineProperty = Ember.defineProperty,
4820     guidFor = Ember.guidFor;
4821
4822 function mixinsMeta(obj) {
4823   var m = Ember.meta(obj, true), ret = m.mixins;
4824   if (!ret) {
4825     ret = m.mixins = { __emberproto__: obj };
4826   } else if (ret.__emberproto__ !== obj) {
4827     ret = m.mixins = o_create(ret);
4828     ret.__emberproto__ = obj;
4829   }
4830   return ret;
4831 }
4832
4833 function initMixin(mixin, args) {
4834   if (args && args.length > 0) {
4835     mixin.mixins = a_map.call(args, function(x) {
4836       if (x instanceof Mixin) { return x; }
4837
4838       // Note: Manually setup a primitive mixin here.  This is the only
4839       // way to actually get a primitive mixin.  This way normal creation
4840       // of mixins will give you combined mixins...
4841       var mixin = new Mixin();
4842       mixin.properties = x;
4843       return mixin;
4844     });
4845   }
4846   return mixin;
4847 }
4848
4849 function isMethod(obj) {
4850   return 'function' === typeof obj &&
4851          obj.isMethod !== false &&
4852          obj !== Boolean && obj !== Object && obj !== Number && obj !== Array && obj !== Date && obj !== String;
4853 }
4854
4855 function mergeMixins(mixins, m, descs, values, base) {
4856   var len = mixins.length, idx, mixin, guid, props, value, key, ovalue, concats;
4857
4858   function removeKeys(keyName) {
4859     delete descs[keyName];
4860     delete values[keyName];
4861   }
4862
4863   for(idx=0; idx < len; idx++) {
4864     mixin = mixins[idx];
4865     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]');
4866
4867     if (mixin instanceof Mixin) {
4868       guid = guidFor(mixin);
4869       if (m[guid]) { continue; }
4870       m[guid] = mixin;
4871       props = mixin.properties;
4872     } else {
4873       props = mixin; // apply anonymous mixin properties
4874     }
4875
4876     if (props) {
4877       // reset before adding each new mixin to pickup concats from previous
4878       concats = values.concatenatedProperties || base.concatenatedProperties;
4879       if (props.concatenatedProperties) {
4880         concats = concats ? concats.concat(props.concatenatedProperties) : props.concatenatedProperties;
4881       }
4882
4883       for (key in props) {
4884         if (!props.hasOwnProperty(key)) { continue; }
4885         value = props[key];
4886         if (value instanceof Ember.Descriptor) {
4887           if (value === REQUIRED && descs[key]) { continue; }
4888
4889           descs[key]  = value;
4890           values[key] = undefined;
4891         } else {
4892           // impl super if needed...
4893           if (isMethod(value)) {
4894             ovalue = descs[key] === undefined && values[key];
4895             if (!ovalue) { ovalue = base[key]; }
4896             if ('function' !== typeof ovalue) { ovalue = null; }
4897             if (ovalue) {
4898               var o = value.__ember_observes__, ob = value.__ember_observesBefore__;
4899               value = Ember.wrap(value, ovalue);
4900               value.__ember_observes__ = o;
4901               value.__ember_observesBefore__ = ob;
4902             }
4903           } else if ((concats && a_indexOf.call(concats, key) >= 0) || key === 'concatenatedProperties') {
4904             var baseValue = values[key] || base[key];
4905             if (baseValue) {
4906               if ('function' === typeof baseValue.concat) {
4907                 value = baseValue.concat(value);
4908               } else {
4909                 value = Ember.makeArray(baseValue).concat(value);
4910               }
4911             } else {
4912               value = Ember.makeArray(value);
4913             }
4914           }
4915
4916           descs[key] = undefined;
4917           values[key] = value;
4918         }
4919       }
4920
4921       // manually copy toString() because some JS engines do not enumerate it
4922       if (props.hasOwnProperty('toString')) {
4923         base.toString = props.toString;
4924       }
4925
4926     } else if (mixin.mixins) {
4927       mergeMixins(mixin.mixins, m, descs, values, base);
4928       if (mixin._without) { a_forEach.call(mixin._without, removeKeys); }
4929     }
4930   }
4931 }
4932
4933 function writableReq(obj) {
4934   var m = Ember.meta(obj), req = m.required;
4935   if (!req || req.__emberproto__ !== obj) {
4936     req = m.required = req ? o_create(req) : { __ember_count__: 0 };
4937     req.__emberproto__ = obj;
4938   }
4939   return req;
4940 }
4941
4942 var IS_BINDING = Ember.IS_BINDING = /^.+Binding$/;
4943
4944 function detectBinding(obj, key, value, m) {
4945   if (IS_BINDING.test(key)) {
4946     var bindings = m.bindings;
4947     if (!bindings) {
4948       bindings = m.bindings = { __emberproto__: obj };
4949     } else if (bindings.__emberproto__ !== obj) {
4950       bindings = m.bindings = o_create(m.bindings);
4951       bindings.__emberproto__ = obj;
4952     }
4953     bindings[key] = value;
4954   }
4955 }
4956
4957 function connectBindings(obj, m) {
4958   // TODO Mixin.apply(instance) should disconnect binding if exists
4959   var bindings = m.bindings, key, binding, to;
4960   if (bindings) {
4961     for (key in bindings) {
4962       binding = key !== '__emberproto__' && bindings[key];
4963       if (binding) {
4964         to = key.slice(0, -7); // strip Binding off end
4965         if (binding instanceof Ember.Binding) {
4966           binding = binding.copy(); // copy prototypes' instance
4967           binding.to(to);
4968         } else { // binding is string path
4969           binding = new Ember.Binding(to, binding);
4970         }
4971         binding.connect(obj);
4972         obj[key] = binding;
4973       }
4974     }
4975     // mark as applied
4976     m.bindings = { __emberproto__: obj };
4977   }
4978 }
4979
4980 function finishPartial(obj, m) {
4981   connectBindings(obj, m || Ember.meta(obj));
4982   return obj;
4983 }
4984
4985 function applyMixin(obj, mixins, partial) {
4986   var descs = {}, values = {}, m = Ember.meta(obj), req = m.required,
4987       key, value, desc, prevValue, paths, len, idx;
4988
4989   // Go through all mixins and hashes passed in, and:
4990   //
4991   // * Handle concatenated properties
4992   // * Set up _super wrapping if necessary
4993   // * Set up computed property descriptors
4994   // * Copying `toString` in broken browsers
4995   mergeMixins(mixins, mixinsMeta(obj), descs, values, obj);
4996
4997   for(key in values) {
4998     if (key === 'contructor') { continue; }
4999     if (!values.hasOwnProperty(key)) { continue; }
5000
5001     desc = descs[key];
5002     value = values[key];
5003
5004     if (desc === REQUIRED) {
5005       if (!(key in obj)) {
5006         Ember.assert('Required property not defined: '+key, !!partial);
5007
5008         // for partial applies add to hash of required keys
5009         req = writableReq(obj);
5010         req.__ember_count__++;
5011         req[key] = true;
5012       }
5013     } else {
5014       while (desc && desc instanceof Alias) {
5015         var altKey = desc.methodName;
5016         if (descs[altKey] || values[altKey]) {
5017           value = values[altKey];
5018           desc  = descs[altKey];
5019         } else if (m.descs[altKey]) {
5020           desc  = m.descs[altKey];
5021           value = undefined;
5022         } else {
5023           desc = undefined;
5024           value = obj[altKey];
5025         }
5026       }
5027
5028       if (desc === undefined && value === undefined) { continue; }
5029
5030       prevValue = obj[key];
5031
5032       if ('function' === typeof prevValue) {
5033         if ((paths = prevValue.__ember_observesBefore__)) {
5034           len = paths.length;
5035           for (idx=0; idx < len; idx++) {
5036             Ember.removeBeforeObserver(obj, paths[idx], null, key);
5037           }
5038         } else if ((paths = prevValue.__ember_observes__)) {
5039           len = paths.length;
5040           for (idx=0; idx < len; idx++) {
5041             Ember.removeObserver(obj, paths[idx], null, key);
5042           }
5043         }
5044       }
5045
5046       detectBinding(obj, key, value, m);
5047
5048       defineProperty(obj, key, desc, value, m);
5049
5050       if ('function' === typeof value) {
5051         if (paths = value.__ember_observesBefore__) {
5052           len = paths.length;
5053           for (idx=0; idx < len; idx++) {
5054             Ember.addBeforeObserver(obj, paths[idx], null, key);
5055           }
5056         } else if (paths = value.__ember_observes__) {
5057           len = paths.length;
5058           for (idx=0; idx < len; idx++) {
5059             Ember.addObserver(obj, paths[idx], null, key);
5060           }
5061         }
5062       }
5063
5064       if (req && req[key]) {
5065         req = writableReq(obj);
5066         req.__ember_count__--;
5067         req[key] = false;
5068       }
5069     }
5070   }
5071
5072   if (!partial) { // don't apply to prototype
5073     finishPartial(obj, m);
5074   }
5075
5076   // Make sure no required attrs remain
5077   if (!partial && req && req.__ember_count__>0) {
5078     var keys = [];
5079     for (key in req) {
5080       if (META_SKIP[key]) { continue; }
5081       keys.push(key);
5082     }
5083     // TODO: Remove surrounding if clause from production build
5084     Ember.assert('Required properties not defined: '+keys.join(','));
5085   }
5086   return obj;
5087 }
5088
5089 /**
5090   @method mixin
5091   @for Ember
5092   @param obj
5093   @param mixins*
5094   @return obj
5095 */
5096 Ember.mixin = function(obj) {
5097   var args = a_slice.call(arguments, 1);
5098   applyMixin(obj, args, false);
5099   return obj;
5100 };
5101
5102 /**
5103   The `Ember.Mixin` class allows you to create mixins, whose properties can be
5104   added to other classes. For instance,
5105
5106       App.Editable = Ember.Mixin.create({
5107         edit: function() {
5108           console.log('starting to edit');
5109           this.set('isEditing', true);
5110         },
5111         isEditing: false
5112       });
5113
5114       // Mix mixins into classes by passing them as the first arguments to
5115       // .extend or .create.
5116       App.CommentView = Ember.View.extend(App.Editable, {
5117         template: Ember.Handlebars.compile('{{#if isEditing}}...{{else}}...{{/if}}')
5118       });
5119
5120       commentView = App.CommentView.create();
5121       commentView.edit(); // => outputs 'starting to edit'
5122
5123   Note that Mixins are created with `Ember.Mixin.create`, not
5124   `Ember.Mixin.extend`.
5125
5126   @class Mixin
5127   @namespace Ember
5128 */
5129 Ember.Mixin = function() { return initMixin(this, arguments); };
5130
5131 Mixin = Ember.Mixin;
5132
5133 Mixin._apply = applyMixin;
5134
5135 Mixin.applyPartial = function(obj) {
5136   var args = a_slice.call(arguments, 1);
5137   return applyMixin(obj, args, true);
5138 };
5139
5140 Mixin.finishPartial = finishPartial;
5141
5142 /**
5143   @method create
5144   @static
5145   @param arguments*
5146 */
5147 Mixin.create = function() {
5148   classToString.processed = false;
5149   var M = this;
5150   return initMixin(new M(), arguments);
5151 };
5152
5153 var MixinPrototype = Mixin.prototype;
5154
5155 /**
5156   @method reopen
5157   @param arguments*
5158 */
5159 MixinPrototype.reopen = function() {
5160   var mixin, tmp;
5161
5162   if (this.properties) {
5163     mixin = Mixin.create();
5164     mixin.properties = this.properties;
5165     delete this.properties;
5166     this.mixins = [mixin];
5167   } else if (!this.mixins) {
5168     this.mixins = [];
5169   }
5170
5171   var len = arguments.length, mixins = this.mixins, idx;
5172
5173   for(idx=0; idx < len; idx++) {
5174     mixin = arguments[idx];
5175     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]');
5176
5177     if (mixin instanceof Mixin) {
5178       mixins.push(mixin);
5179     } else {
5180       tmp = Mixin.create();
5181       tmp.properties = mixin;
5182       mixins.push(tmp);
5183     }
5184   }
5185
5186   return this;
5187 };
5188
5189 /**
5190   @method apply
5191   @param obj
5192   @return applied object
5193 */
5194 MixinPrototype.apply = function(obj) {
5195   return applyMixin(obj, [this], false);
5196 };
5197
5198 MixinPrototype.applyPartial = function(obj) {
5199   return applyMixin(obj, [this], true);
5200 };
5201
5202 function _detect(curMixin, targetMixin, seen) {
5203   var guid = guidFor(curMixin);
5204
5205   if (seen[guid]) { return false; }
5206   seen[guid] = true;
5207
5208   if (curMixin === targetMixin) { return true; }
5209   var mixins = curMixin.mixins, loc = mixins ? mixins.length : 0;
5210   while (--loc >= 0) {
5211     if (_detect(mixins[loc], targetMixin, seen)) { return true; }
5212   }
5213   return false;
5214 }
5215
5216 /**
5217   @method detect
5218   @param obj
5219   @return {Boolean}
5220 */
5221 MixinPrototype.detect = function(obj) {
5222   if (!obj) { return false; }
5223   if (obj instanceof Mixin) { return _detect(obj, this, {}); }
5224   var mixins = Ember.meta(obj, false).mixins;
5225   if (mixins) {
5226     return !!mixins[guidFor(this)];
5227   }
5228   return false;
5229 };
5230
5231 MixinPrototype.without = function() {
5232   var ret = new Mixin(this);
5233   ret._without = a_slice.call(arguments);
5234   return ret;
5235 };
5236
5237 function _keys(ret, mixin, seen) {
5238   if (seen[guidFor(mixin)]) { return; }
5239   seen[guidFor(mixin)] = true;
5240
5241   if (mixin.properties) {
5242     var props = mixin.properties;
5243     for (var key in props) {
5244       if (props.hasOwnProperty(key)) { ret[key] = true; }
5245     }
5246   } else if (mixin.mixins) {
5247     a_forEach.call(mixin.mixins, function(x) { _keys(ret, x, seen); });
5248   }
5249 }
5250
5251 MixinPrototype.keys = function() {
5252   var keys = {}, seen = {}, ret = [];
5253   _keys(keys, this, seen);
5254   for(var key in keys) {
5255     if (keys.hasOwnProperty(key)) { ret.push(key); }
5256   }
5257   return ret;
5258 };
5259
5260 /* make Mixins have nice displayNames */
5261
5262 var NAME_KEY = Ember.GUID_KEY+'_name';
5263 var get = Ember.get;
5264
5265 function processNames(paths, root, seen) {
5266   var idx = paths.length;
5267   for(var key in root) {
5268     if (!root.hasOwnProperty || !root.hasOwnProperty(key)) { continue; }
5269     var obj = root[key];
5270     paths[idx] = key;
5271
5272     if (obj && obj.toString === classToString) {
5273       obj[NAME_KEY] = paths.join('.');
5274     } else if (obj && get(obj, 'isNamespace')) {
5275       if (seen[guidFor(obj)]) { continue; }
5276       seen[guidFor(obj)] = true;
5277       processNames(paths, obj, seen);
5278     }
5279   }
5280   paths.length = idx; // cut out last item
5281 }
5282
5283 function findNamespaces() {
5284   var Namespace = Ember.Namespace, lookup = Ember.lookup, obj, isNamespace;
5285
5286   if (Namespace.PROCESSED) { return; }
5287
5288   for (var prop in lookup) {
5289     //  get(window.globalStorage, 'isNamespace') would try to read the storage for domain isNamespace and cause exception in Firefox.
5290     // globalStorage is a storage obsoleted by the WhatWG storage specification. See https://developer.mozilla.org/en/DOM/Storage#globalStorage
5291     if (prop === "globalStorage" && lookup.StorageList && lookup.globalStorage instanceof lookup.StorageList) { continue; }
5292     // Unfortunately, some versions of IE don't support window.hasOwnProperty
5293     if (lookup.hasOwnProperty && !lookup.hasOwnProperty(prop)) { continue; }
5294
5295     // At times we are not allowed to access certain properties for security reasons.
5296     // There are also times where even if we can access them, we are not allowed to access their properties.
5297     try {
5298       obj = Ember.lookup[prop];
5299       isNamespace = obj && get(obj, 'isNamespace');
5300     } catch (e) {
5301       continue;
5302     }
5303
5304     if (isNamespace) {
5305       Ember.deprecate("Namespaces should not begin with lowercase.", /^[A-Z]/.test(prop));
5306       obj[NAME_KEY] = prop;
5307     }
5308   }
5309 }
5310
5311 /**
5312   @private
5313   @method identifyNamespaces
5314   @for Ember
5315 */
5316 Ember.identifyNamespaces = findNamespaces;
5317
5318 superClassString = function(mixin) {
5319   var superclass = mixin.superclass;
5320   if (superclass) {
5321     if (superclass[NAME_KEY]) { return superclass[NAME_KEY]; }
5322     else { return superClassString(superclass); }
5323   } else {
5324     return;
5325   }
5326 };
5327
5328 classToString = function() {
5329   var Namespace = Ember.Namespace, namespace;
5330
5331   // TODO: Namespace should really be in Metal
5332   if (Namespace) {
5333     if (!this[NAME_KEY] && !classToString.processed) {
5334       if (!Namespace.PROCESSED) {
5335         findNamespaces();
5336         Namespace.PROCESSED = true;
5337       }
5338
5339       classToString.processed = true;
5340
5341       var namespaces = Namespace.NAMESPACES;
5342       for (var i=0, l=namespaces.length; i<l; i++) {
5343         namespace = namespaces[i];
5344         processNames([namespace.toString()], namespace, {});
5345       }
5346     }
5347   }
5348
5349   if (this[NAME_KEY]) {
5350     return this[NAME_KEY];
5351   } else {
5352     var str = superClassString(this);
5353     if (str) {
5354       return "(subclass of " + str + ")";
5355     } else {
5356       return "(unknown mixin)";
5357     }
5358   }
5359 };
5360
5361 MixinPrototype.toString = classToString;
5362
5363 // returns the mixins currently applied to the specified object
5364 // TODO: Make Ember.mixin
5365 Mixin.mixins = function(obj) {
5366   var ret = [], mixins = Ember.meta(obj, false).mixins, key, mixin;
5367   if (mixins) {
5368     for(key in mixins) {
5369       if (META_SKIP[key]) { continue; }
5370       mixin = mixins[key];
5371
5372       // skip primitive mixins since these are always anonymous
5373       if (!mixin.properties) { ret.push(mixins[key]); }
5374     }
5375   }
5376   return ret;
5377 };
5378
5379 REQUIRED = new Ember.Descriptor();
5380 REQUIRED.toString = function() { return '(Required Property)'; };
5381
5382 /**
5383   Denotes a required property for a mixin
5384
5385   @method required
5386   @for Ember
5387 */
5388 Ember.required = function() {
5389   return REQUIRED;
5390 };
5391
5392 Alias = function(methodName) {
5393   this.methodName = methodName;
5394 };
5395 Alias.prototype = new Ember.Descriptor();
5396
5397 /**
5398   Makes a property or method available via an additional name.
5399
5400       App.PaintSample = Ember.Object.extend({
5401         color: 'red',
5402         colour: Ember.alias('color'),
5403         name: function(){
5404           return "Zed";
5405         },
5406         moniker: Ember.alias("name")
5407       });
5408       var paintSample = App.PaintSample.create()
5409       paintSample.get('colour'); //=> 'red'
5410       paintSample.moniker(); //=> 'Zed'
5411
5412   @method alias
5413   @for Ember
5414   @param {String} methodName name of the method or property to alias
5415   @return {Ember.Descriptor}
5416 */
5417 Ember.alias = function(methodName) {
5418   return new Alias(methodName);
5419 };
5420
5421 // ..........................................................
5422 // OBSERVER HELPER
5423 //
5424
5425 /**
5426   @method observer
5427   @for Ember
5428   @param {Function} func
5429   @param {String} propertyNames*
5430   @return func
5431 */
5432 Ember.observer = function(func) {
5433   var paths = a_slice.call(arguments, 1);
5434   func.__ember_observes__ = paths;
5435   return func;
5436 };
5437
5438 // If observers ever become asynchronous, Ember.immediateObserver
5439 // must remain synchronous.
5440 /**
5441   @method immediateObserver
5442   @for Ember
5443   @param {Function} func
5444   @param {String} propertyNames*
5445   @return func
5446 */
5447 Ember.immediateObserver = function() {
5448   for (var i=0, l=arguments.length; i<l; i++) {
5449     var arg = arguments[i];
5450     Ember.assert("Immediate observers must observe internal properties only, not properties on other objects.", typeof arg !== "string" || arg.indexOf('.') === -1);
5451   }
5452
5453   return Ember.observer.apply(this, arguments);
5454 };
5455
5456 /**
5457   @method beforeObserver
5458   @for Ember
5459   @param {Function} func
5460   @param {String} propertyNames*
5461   @return func
5462 */
5463 Ember.beforeObserver = function(func) {
5464   var paths = a_slice.call(arguments, 1);
5465   func.__ember_observesBefore__ = paths;
5466   return func;
5467 };
5468
5469 })();
5470
5471
5472
5473 (function() {
5474 /**
5475 Ember Metal
5476
5477 @module ember
5478 @submodule ember-metal
5479 */
5480
5481 })();
5482
5483 (function() {
5484 (function(exports) { "use strict";
5485
5486 var browserGlobal = (typeof window !== 'undefined') ? window : {};
5487
5488 var MutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
5489 var async;
5490
5491 if (typeof process !== 'undefined') {
5492   async = function(callback, binding) {
5493     process.nextTick(function() {
5494       callback.call(binding);
5495     });
5496   };
5497 } else if (MutationObserver) {
5498   var queue = [];
5499
5500   var observer = new MutationObserver(function() {
5501     var toProcess = queue.slice();
5502     queue = [];
5503
5504     toProcess.forEach(function(tuple) {
5505       var callback = tuple[0], binding = tuple[1];
5506       callback.call(binding);
5507     });
5508   });
5509
5510   var element = document.createElement('div');
5511   observer.observe(element, { attributes: true });
5512
5513   async = function(callback, binding) {
5514     queue.push([callback, binding]);
5515     element.setAttribute('drainQueue', 'drainQueue');
5516   };
5517 } else {
5518   async = function(callback, binding) {
5519     setTimeout(function() {
5520       callback.call(binding);
5521     }, 1);
5522   };
5523 }
5524
5525 exports.async = async;
5526
5527 var Event = exports.Event = function(type, options) {
5528   this.type = type;
5529
5530   for (var option in options) {
5531     if (!options.hasOwnProperty(option)) { continue; }
5532
5533     this[option] = options[option];
5534   }
5535 };
5536
5537 var indexOf = function(callbacks, callback) {
5538   for (var i=0, l=callbacks.length; i<l; i++) {
5539     if (callbacks[i][0] === callback) { return i; }
5540   }
5541
5542   return -1;
5543 };
5544
5545 var callbacksFor = function(object) {
5546   var callbacks = object._promiseCallbacks;
5547
5548   if (!callbacks) {
5549     callbacks = object._promiseCallbacks = {};
5550   }
5551
5552   return callbacks;
5553 };
5554
5555 var EventTarget = exports.EventTarget = {
5556   mixin: function(object) {
5557     object.on = this.on;
5558     object.off = this.off;
5559     object.trigger = this.trigger;
5560     return object;
5561   },
5562
5563   on: function(eventName, callback, binding) {
5564     var allCallbacks = callbacksFor(this), callbacks;
5565     binding = binding || this;
5566
5567     callbacks = allCallbacks[eventName];
5568
5569     if (!callbacks) {
5570       callbacks = allCallbacks[eventName] = [];
5571     }
5572
5573     if (indexOf(callbacks, callback) === -1) {
5574       callbacks.push([callback, binding]);
5575     }
5576   },
5577
5578   off: function(eventName, callback) {
5579     var allCallbacks = callbacksFor(this), callbacks;
5580
5581     if (!callback) {
5582       allCallbacks[eventName] = [];
5583       return;
5584     }
5585
5586     callbacks = allCallbacks[eventName];
5587
5588     var index = indexOf(callbacks, callback);
5589
5590     if (index !== -1) { callbacks.splice(index, 1); }
5591   },
5592
5593   trigger: function(eventName, options) {
5594     var allCallbacks = callbacksFor(this),
5595         callbacks, callbackTuple, callback, binding, event;
5596
5597     if (callbacks = allCallbacks[eventName]) {
5598       for (var i=0, l=callbacks.length; i<l; i++) {
5599         callbackTuple = callbacks[i];
5600         callback = callbackTuple[0];
5601         binding = callbackTuple[1];
5602
5603         if (typeof options !== 'object') {
5604           options = { detail: options };
5605         }
5606
5607         event = new Event(eventName, options);
5608         callback.call(binding, event);
5609       }
5610     }
5611   }
5612 };
5613
5614 var Promise = exports.Promise = function() {
5615   this.on('promise:resolved', function(event) {
5616     this.trigger('success', { detail: event.detail });
5617   }, this);
5618
5619   this.on('promise:failed', function(event) {
5620     this.trigger('error', { detail: event.detail });
5621   }, this);
5622 };
5623
5624 var noop = function() {};
5625
5626 var invokeCallback = function(type, promise, callback, event) {
5627   var value, error;
5628
5629   if (callback) {
5630     try {
5631       value = callback(event.detail);
5632     } catch(e) {
5633       error = e;
5634     }
5635   } else {
5636     value = event.detail;
5637   }
5638
5639   if (value instanceof Promise) {
5640     value.then(function(value) {
5641       promise.resolve(value);
5642     }, function(error) {
5643       promise.reject(error);
5644     });
5645   } else if (callback && value) {
5646     promise.resolve(value);
5647   } else if (error) {
5648     promise.reject(error);
5649   } else {
5650     promise[type](value);
5651   }
5652 };
5653
5654 Promise.prototype = {
5655   then: function(done, fail) {
5656     var thenPromise = new Promise();
5657
5658     this.on('promise:resolved', function(event) {
5659       invokeCallback('resolve', thenPromise, done, event);
5660     });
5661
5662     this.on('promise:failed', function(event) {
5663       invokeCallback('reject', thenPromise, fail, event);
5664     });
5665
5666     return thenPromise;
5667   },
5668
5669   resolve: function(value) {
5670     exports.async(function() {
5671       this.trigger('promise:resolved', { detail: value });
5672       this.isResolved = value;
5673     }, this);
5674
5675     this.resolve = noop;
5676     this.reject = noop;
5677   },
5678
5679   reject: function(value) {
5680     exports.async(function() {
5681       this.trigger('promise:failed', { detail: value });
5682       this.isRejected = value;
5683     }, this);
5684
5685     this.resolve = noop;
5686     this.reject = noop;
5687   }
5688 };
5689
5690 EventTarget.mixin(Promise.prototype);
5691  })(window.RSVP = {});
5692
5693 })();
5694
5695 (function() {
5696 /*globals ENV */
5697 /**
5698 @module ember
5699 @submodule ember-runtime
5700 */
5701
5702 var indexOf = Ember.EnumerableUtils.indexOf;
5703
5704 // ........................................
5705 // TYPING & ARRAY MESSAGING
5706 //
5707
5708 var TYPE_MAP = {};
5709 var t = "Boolean Number String Function Array Date RegExp Object".split(" ");
5710 Ember.ArrayPolyfills.forEach.call(t, function(name) {
5711   TYPE_MAP[ "[object " + name + "]" ] = name.toLowerCase();
5712 });
5713
5714 var toString = Object.prototype.toString;
5715
5716 /**
5717   Returns a consistent type for the passed item.
5718
5719   Use this instead of the built-in `typeof` to get the type of an item.
5720   It will return the same result across all browsers and includes a bit
5721   more detail.  Here is what will be returned:
5722
5723       | Return Value  | Meaning                                              |
5724       |---------------|------------------------------------------------------|
5725       | 'string'      | String primitive                                     |
5726       | 'number'      | Number primitive                                     |
5727       | 'boolean'     | Boolean primitive                                    |
5728       | 'null'        | Null value                                           |
5729       | 'undefined'   | Undefined value                                      |
5730       | 'function'    | A function                                           |
5731       | 'array'       | An instance of Array                                 |
5732       | 'class'       | A Ember class (created using Ember.Object.extend())  |
5733       | 'instance'    | A Ember object instance                              |
5734       | 'error'       | An instance of the Error object                      |
5735       | 'object'      | A JavaScript object not inheriting from Ember.Object |
5736
5737   Examples:
5738
5739       Ember.typeOf();                      => 'undefined'
5740       Ember.typeOf(null);                  => 'null'
5741       Ember.typeOf(undefined);             => 'undefined'
5742       Ember.typeOf('michael');             => 'string'
5743       Ember.typeOf(101);                   => 'number'
5744       Ember.typeOf(true);                  => 'boolean'
5745       Ember.typeOf(Ember.makeArray);       => 'function'
5746       Ember.typeOf([1,2,90]);              => 'array'
5747       Ember.typeOf(Ember.Object.extend()); => 'class'
5748       Ember.typeOf(Ember.Object.create()); => 'instance'
5749       Ember.typeOf(new Error('teamocil')); => 'error'
5750
5751       // "normal" JavaScript object
5752       Ember.typeOf({a: 'b'});              => 'object'
5753
5754   @method typeOf
5755   @for Ember
5756   @param item {Object} the item to check
5757   @return {String} the type
5758 */
5759 Ember.typeOf = function(item) {
5760   var ret;
5761
5762   ret = (item === null || item === undefined) ? String(item) : TYPE_MAP[toString.call(item)] || 'object';
5763
5764   if (ret === 'function') {
5765     if (Ember.Object && Ember.Object.detect(item)) ret = 'class';
5766   } else if (ret === 'object') {
5767     if (item instanceof Error) ret = 'error';
5768     else if (Ember.Object && item instanceof Ember.Object) ret = 'instance';
5769     else ret = 'object';
5770   }
5771
5772   return ret;
5773 };
5774
5775 /**
5776   Returns true if the passed value is null or undefined.  This avoids errors
5777   from JSLint complaining about use of ==, which can be technically
5778   confusing.
5779
5780       Ember.none();             => true
5781       Ember.none(null);         => true
5782       Ember.none(undefined);    => true
5783       Ember.none('');           => false
5784       Ember.none([]);           => false
5785       Ember.none(function(){}); => false
5786
5787   @method none
5788   @for Ember
5789   @param {Object} obj Value to test
5790   @return {Boolean}
5791 */
5792 Ember.none = function(obj) {
5793   return obj === null || obj === undefined;
5794 };
5795
5796 /**
5797   Verifies that a value is null or an empty string | array | function.
5798
5799   Constrains the rules on `Ember.none` by returning false for empty
5800   string and empty arrays.
5801
5802       Ember.empty();               => true
5803       Ember.empty(null);           => true
5804       Ember.empty(undefined);      => true
5805       Ember.empty('');             => true
5806       Ember.empty([]);             => true
5807       Ember.empty('tobias fünke'); => false
5808       Ember.empty([0,1,2]);        => false
5809
5810   @method empty
5811   @for Ember
5812   @param {Object} obj Value to test
5813   @return {Boolean}
5814 */
5815 Ember.empty = function(obj) {
5816   return obj === null || obj === undefined || (obj.length === 0 && typeof obj !== 'function') || (typeof obj === 'object' && Ember.get(obj, 'length') === 0);
5817 };
5818
5819 /**
5820  This will compare two javascript values of possibly different types.
5821  It will tell you which one is greater than the other by returning:
5822
5823   - -1 if the first is smaller than the second,
5824   - 0 if both are equal,
5825   - 1 if the first is greater than the second.
5826
5827  The order is calculated based on Ember.ORDER_DEFINITION, if types are different.
5828  In case they have the same type an appropriate comparison for this type is made.
5829
5830     Ember.compare('hello', 'hello');  => 0
5831     Ember.compare('abc', 'dfg');      => -1
5832     Ember.compare(2, 1);              => 1
5833
5834  @method compare
5835  @for Ember
5836  @param {Object} v First value to compare
5837  @param {Object} w Second value to compare
5838  @return {Number} -1 if v < w, 0 if v = w and 1 if v > w.
5839 */
5840 Ember.compare = function compare(v, w) {
5841   if (v === w) { return 0; }
5842
5843   var type1 = Ember.typeOf(v);
5844   var type2 = Ember.typeOf(w);
5845
5846   var Comparable = Ember.Comparable;
5847   if (Comparable) {
5848     if (type1==='instance' && Comparable.detect(v.constructor)) {
5849       return v.constructor.compare(v, w);
5850     }
5851
5852     if (type2 === 'instance' && Comparable.detect(w.constructor)) {
5853       return 1-w.constructor.compare(w, v);
5854     }
5855   }
5856
5857   // If we haven't yet generated a reverse-mapping of Ember.ORDER_DEFINITION,
5858   // do so now.
5859   var mapping = Ember.ORDER_DEFINITION_MAPPING;
5860   if (!mapping) {
5861     var order = Ember.ORDER_DEFINITION;
5862     mapping = Ember.ORDER_DEFINITION_MAPPING = {};
5863     var idx, len;
5864     for (idx = 0, len = order.length; idx < len;  ++idx) {
5865       mapping[order[idx]] = idx;
5866     }
5867
5868     // We no longer need Ember.ORDER_DEFINITION.
5869     delete Ember.ORDER_DEFINITION;
5870   }
5871
5872   var type1Index = mapping[type1];
5873   var type2Index = mapping[type2];
5874
5875   if (type1Index < type2Index) { return -1; }
5876   if (type1Index > type2Index) { return 1; }
5877
5878   // types are equal - so we have to check values now
5879   switch (type1) {
5880     case 'boolean':
5881     case 'number':
5882       if (v < w) { return -1; }
5883       if (v > w) { return 1; }
5884       return 0;
5885
5886     case 'string':
5887       var comp = v.localeCompare(w);
5888       if (comp < 0) { return -1; }
5889       if (comp > 0) { return 1; }
5890       return 0;
5891
5892     case 'array':
5893       var vLen = v.length;
5894       var wLen = w.length;
5895       var l = Math.min(vLen, wLen);
5896       var r = 0;
5897       var i = 0;
5898       while (r === 0 && i < l) {
5899         r = compare(v[i],w[i]);
5900         i++;
5901       }
5902       if (r !== 0) { return r; }
5903
5904       // all elements are equal now
5905       // shorter array should be ordered first
5906       if (vLen < wLen) { return -1; }
5907       if (vLen > wLen) { return 1; }
5908       // arrays are equal now
5909       return 0;
5910
5911     case 'instance':
5912       if (Ember.Comparable && Ember.Comparable.detect(v)) {
5913         return v.compare(v, w);
5914       }
5915       return 0;
5916
5917     case 'date':
5918       var vNum = v.getTime();
5919       var wNum = w.getTime();
5920       if (vNum < wNum) { return -1; }
5921       if (vNum > wNum) { return 1; }
5922       return 0;
5923
5924     default:
5925       return 0;
5926   }
5927 };
5928
5929 function _copy(obj, deep, seen, copies) {
5930   var ret, loc, key;
5931
5932   // primitive data types are immutable, just return them.
5933   if ('object' !== typeof obj || obj===null) return obj;
5934
5935   // avoid cyclical loops
5936   if (deep && (loc=indexOf(seen, obj))>=0) return copies[loc];
5937
5938   Ember.assert('Cannot clone an Ember.Object that does not implement Ember.Copyable', !(obj instanceof Ember.Object) || (Ember.Copyable && Ember.Copyable.detect(obj)));
5939
5940   // IMPORTANT: this specific test will detect a native array only.  Any other
5941   // object will need to implement Copyable.
5942   if (Ember.typeOf(obj) === 'array') {
5943     ret = obj.slice();
5944     if (deep) {
5945       loc = ret.length;
5946       while(--loc>=0) ret[loc] = _copy(ret[loc], deep, seen, copies);
5947     }
5948   } else if (Ember.Copyable && Ember.Copyable.detect(obj)) {
5949     ret = obj.copy(deep, seen, copies);
5950   } else {
5951     ret = {};
5952     for(key in obj) {
5953       if (!obj.hasOwnProperty(key)) continue;
5954       ret[key] = deep ? _copy(obj[key], deep, seen, copies) : obj[key];
5955     }
5956   }
5957
5958   if (deep) {
5959     seen.push(obj);
5960     copies.push(ret);
5961   }
5962
5963   return ret;
5964 }
5965
5966 /**
5967   Creates a clone of the passed object. This function can take just about
5968   any type of object and create a clone of it, including primitive values
5969   (which are not actually cloned because they are immutable).
5970
5971   If the passed object implements the clone() method, then this function
5972   will simply call that method and return the result.
5973
5974   @method copy
5975   @for Ember
5976   @param {Object} object The object to clone
5977   @param {Boolean} deep If true, a deep copy of the object is made
5978   @return {Object} The cloned object
5979 */
5980 Ember.copy = function(obj, deep) {
5981   // fast paths
5982   if ('object' !== typeof obj || obj===null) return obj; // can't copy primitives
5983   if (Ember.Copyable && Ember.Copyable.detect(obj)) return obj.copy(deep);
5984   return _copy(obj, deep, deep ? [] : null, deep ? [] : null);
5985 };
5986
5987 /**
5988   Convenience method to inspect an object. This method will attempt to
5989   convert the object into a useful string description.
5990
5991   @method inspect
5992   @for Ember
5993   @param {Object} obj The object you want to inspect.
5994   @return {String} A description of the object
5995 */
5996 Ember.inspect = function(obj) {
5997   var v, ret = [];
5998   for(var key in obj) {
5999     if (obj.hasOwnProperty(key)) {
6000       v = obj[key];
6001       if (v === 'toString') { continue; } // ignore useless items
6002       if (Ember.typeOf(v) === 'function') { v = "function() { ... }"; }
6003       ret.push(key + ": " + v);
6004     }
6005   }
6006   return "{" + ret.join(" , ") + "}";
6007 };
6008
6009 /**
6010   Compares two objects, returning true if they are logically equal.  This is
6011   a deeper comparison than a simple triple equal. For sets it will compare the
6012   internal objects.  For any other object that implements `isEqual()` it will 
6013   respect that method.
6014
6015       Ember.isEqual('hello', 'hello');  => true
6016       Ember.isEqual(1, 2);              => false
6017       Ember.isEqual([4,2], [4,2]);      => false
6018
6019   @method isEqual
6020   @for Ember
6021   @param {Object} a first object to compare
6022   @param {Object} b second object to compare
6023   @return {Boolean}
6024 */
6025 Ember.isEqual = function(a, b) {
6026   if (a && 'function'===typeof a.isEqual) return a.isEqual(b);
6027   return a === b;
6028 };
6029
6030 // Used by Ember.compare
6031 Ember.ORDER_DEFINITION = Ember.ENV.ORDER_DEFINITION || [
6032   'undefined',
6033   'null',
6034   'boolean',
6035   'number',
6036   'string',
6037   'array',
6038   'object',
6039   'instance',
6040   'function',
6041   'class',
6042   'date'
6043 ];
6044
6045 /**
6046   Returns all of the keys defined on an object or hash. This is useful
6047   when inspecting objects for debugging.  On browsers that support it, this
6048   uses the native Object.keys implementation.
6049
6050   @method keys
6051   @for Ember
6052   @param {Object} obj
6053   @return {Array} Array containing keys of obj
6054 */
6055 Ember.keys = Object.keys;
6056
6057 if (!Ember.keys) {
6058   Ember.keys = function(obj) {
6059     var ret = [];
6060     for(var key in obj) {
6061       if (obj.hasOwnProperty(key)) { ret.push(key); }
6062     }
6063     return ret;
6064   };
6065 }
6066
6067 // ..........................................................
6068 // ERROR
6069 //
6070
6071 var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
6072
6073 /**
6074   A subclass of the JavaScript Error object for use in Ember.
6075
6076   @class Error
6077   @namespace Ember
6078   @extends Error
6079   @constructor
6080 */
6081 Ember.Error = function() {
6082   var tmp = Error.prototype.constructor.apply(this, arguments);
6083
6084   // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
6085   for (var idx = 0; idx < errorProps.length; idx++) {
6086     this[errorProps[idx]] = tmp[errorProps[idx]];
6087   }
6088 };
6089
6090 Ember.Error.prototype = Ember.create(Error.prototype);
6091
6092 })();
6093
6094
6095
6096 (function() {
6097 /**
6098 @module ember
6099 @submodule ember-runtime
6100 */
6101
6102 var STRING_DASHERIZE_REGEXP = (/[ _]/g);
6103 var STRING_DASHERIZE_CACHE = {};
6104 var STRING_DECAMELIZE_REGEXP = (/([a-z])([A-Z])/g);
6105 var STRING_CAMELIZE_REGEXP = (/(\-|_|\s)+(.)?/g);
6106 var STRING_UNDERSCORE_REGEXP_1 = (/([a-z\d])([A-Z]+)/g);
6107 var STRING_UNDERSCORE_REGEXP_2 = (/\-|\s+/g);
6108
6109 /**
6110   Defines the hash of localized strings for the current language.  Used by
6111   the `Ember.String.loc()` helper.  To localize, add string values to this
6112   hash.
6113
6114   @property STRINGS
6115   @for Ember
6116   @type Hash
6117 */
6118 Ember.STRINGS = {};
6119
6120 /**
6121   Defines string helper methods including string formatting and localization.
6122   Unless Ember.EXTEND_PROTOTYPES.String is false these methods will also be added
6123   to the String.prototype as well.
6124
6125   @class String
6126   @namespace Ember
6127   @static
6128 */
6129 Ember.String = {
6130
6131   /**
6132     Apply formatting options to the string.  This will look for occurrences
6133     of %@ in your string and substitute them with the arguments you pass into
6134     this method.  If you want to control the specific order of replacement,
6135     you can add a number after the key as well to indicate which argument
6136     you want to insert.
6137
6138     Ordered insertions are most useful when building loc strings where values
6139     you need to insert may appear in different orders.
6140
6141         "Hello %@ %@".fmt('John', 'Doe') => "Hello John Doe"
6142         "Hello %@2, %@1".fmt('John', 'Doe') => "Hello Doe, John"
6143
6144     @method fmt
6145     @param {Object...} [args]
6146     @return {String} formatted string
6147   */
6148   fmt: function(str, formats) {
6149     // first, replace any ORDERED replacements.
6150     var idx  = 0; // the current index for non-numerical replacements
6151     return str.replace(/%@([0-9]+)?/g, function(s, argIndex) {
6152       argIndex = (argIndex) ? parseInt(argIndex,0) - 1 : idx++ ;
6153       s = formats[argIndex];
6154       return ((s === null) ? '(null)' : (s === undefined) ? '' : s).toString();
6155     }) ;
6156   },
6157
6158   /**
6159     Formats the passed string, but first looks up the string in the localized
6160     strings hash.  This is a convenient way to localize text.  See
6161     `Ember.String.fmt()` for more information on formatting.
6162
6163     Note that it is traditional but not required to prefix localized string
6164     keys with an underscore or other character so you can easily identify
6165     localized strings.
6166
6167         Ember.STRINGS = {
6168           '_Hello World': 'Bonjour le monde',
6169           '_Hello %@ %@': 'Bonjour %@ %@'
6170         };
6171
6172         Ember.String.loc("_Hello World");
6173         => 'Bonjour le monde';
6174
6175         Ember.String.loc("_Hello %@ %@", ["John", "Smith"]);
6176         => "Bonjour John Smith";
6177
6178     @method loc
6179     @param {String} str The string to format
6180     @param {Array} formats Optional array of parameters to interpolate into string.
6181     @return {String} formatted string
6182   */
6183   loc: function(str, formats) {
6184     str = Ember.STRINGS[str] || str;
6185     return Ember.String.fmt(str, formats) ;
6186   },
6187
6188   /**
6189     Splits a string into separate units separated by spaces, eliminating any
6190     empty strings in the process.  This is a convenience method for split that
6191     is mostly useful when applied to the String.prototype.
6192
6193         Ember.String.w("alpha beta gamma").forEach(function(key) {
6194           console.log(key);
6195         });
6196         > alpha
6197         > beta
6198         > gamma
6199
6200     @method w
6201     @param {String} str The string to split
6202     @return {String} split string
6203   */
6204   w: function(str) { return str.split(/\s+/); },
6205
6206   /**
6207     Converts a camelized string into all lower case separated by underscores.
6208
6209         'innerHTML'.decamelize()         => 'inner_html'
6210         'action_name'.decamelize()       => 'action_name'
6211         'css-class-name'.decamelize()    => 'css-class-name'
6212         'my favorite items'.decamelize() => 'my favorite items'
6213
6214     @method decamelize
6215     @param {String} str The string to decamelize.
6216     @return {String} the decamelized string.
6217   */
6218   decamelize: function(str) {
6219     return str.replace(STRING_DECAMELIZE_REGEXP, '$1_$2').toLowerCase();
6220   },
6221
6222   /**
6223     Replaces underscores or spaces with dashes.
6224
6225         'innerHTML'.dasherize()         => 'inner-html'
6226         'action_name'.dasherize()       => 'action-name'
6227         'css-class-name'.dasherize()    => 'css-class-name'
6228         'my favorite items'.dasherize() => 'my-favorite-items'
6229
6230     @method dasherize
6231     @param {String} str The string to dasherize.
6232     @return {String} the dasherized string.
6233   */
6234   dasherize: function(str) {
6235     var cache = STRING_DASHERIZE_CACHE,
6236         ret   = cache[str];
6237
6238     if (ret) {
6239       return ret;
6240     } else {
6241       ret = Ember.String.decamelize(str).replace(STRING_DASHERIZE_REGEXP,'-');
6242       cache[str] = ret;
6243     }
6244
6245     return ret;
6246   },
6247
6248   /**
6249     Returns the lowerCaseCamel form of a string.
6250
6251         'innerHTML'.camelize()         => 'innerHTML'
6252         'action_name'.camelize()       => 'actionName'
6253         'css-class-name'.camelize()    => 'cssClassName'
6254         'my favorite items'.camelize() => 'myFavoriteItems'
6255
6256     @method camelize
6257     @param {String} str The string to camelize.
6258     @return {String} the camelized string.
6259   */
6260   camelize: function(str) {
6261     return str.replace(STRING_CAMELIZE_REGEXP, function(match, separator, chr) {
6262       return chr ? chr.toUpperCase() : '';
6263     });
6264   },
6265
6266   /**
6267     Returns the UpperCamelCase form of a string.
6268
6269         'innerHTML'.classify()         => 'InnerHTML'
6270         'action_name'.classify()       => 'ActionName'
6271         'css-class-name'.classify()    => 'CssClassName'
6272         'my favorite items'.classify() => 'MyFavoriteItems'
6273
6274     @method classify
6275     @param {String} str the string to classify
6276     @return {String} the classified string
6277   */
6278   classify: function(str) {
6279     var camelized = Ember.String.camelize(str);
6280     return camelized.charAt(0).toUpperCase() + camelized.substr(1);
6281   },
6282
6283   /**
6284     More general than decamelize. Returns the lower_case_and_underscored
6285     form of a string.
6286
6287         'innerHTML'.underscore()         => 'inner_html'
6288         'action_name'.underscore()       => 'action_name'
6289         'css-class-name'.underscore()    => 'css_class_name'
6290         'my favorite items'.underscore() => 'my_favorite_items'
6291
6292     @property underscore
6293     @param {String} str The string to underscore.
6294     @return {String} the underscored string.
6295   */
6296   underscore: function(str) {
6297     return str.replace(STRING_UNDERSCORE_REGEXP_1, '$1_$2').
6298       replace(STRING_UNDERSCORE_REGEXP_2, '_').toLowerCase();
6299   }
6300 };
6301
6302 })();
6303
6304
6305
6306 (function() {
6307 /**
6308 @module ember
6309 @submodule ember-runtime
6310 */
6311
6312
6313
6314 var fmt = Ember.String.fmt,
6315     w   = Ember.String.w,
6316     loc = Ember.String.loc,
6317     camelize = Ember.String.camelize,
6318     decamelize = Ember.String.decamelize,
6319     dasherize = Ember.String.dasherize,
6320     underscore = Ember.String.underscore,
6321     classify = Ember.String.classify;
6322
6323 if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {
6324
6325   /**
6326     See {{#crossLink "Ember.String/fmt"}}{{/crossLink}}
6327
6328     @method fmt
6329     @for String
6330   */
6331   String.prototype.fmt = function() {
6332     return fmt(this, arguments);
6333   };
6334
6335   /**
6336     See {{#crossLink "Ember.String/w"}}{{/crossLink}}
6337
6338     @method w
6339     @for String
6340   */
6341   String.prototype.w = function() {
6342     return w(this);
6343   };
6344
6345   /**
6346     See {{#crossLink "Ember.String/loc"}}{{/crossLink}}
6347
6348     @method loc
6349     @for String
6350   */
6351   String.prototype.loc = function() {
6352     return loc(this, arguments);
6353   };
6354
6355   /**
6356     See {{#crossLink "Ember.String/camelize"}}{{/crossLink}}
6357
6358     @method camelize
6359     @for String
6360   */
6361   String.prototype.camelize = function() {
6362     return camelize(this);
6363   };
6364
6365   /**
6366     See {{#crossLink "Ember.String/decamelize"}}{{/crossLink}}
6367
6368     @method decamelize
6369     @for String
6370   */
6371   String.prototype.decamelize = function() {
6372     return decamelize(this);
6373   };
6374
6375   /**
6376     See {{#crossLink "Ember.String/dasherize"}}{{/crossLink}}
6377
6378     @method dasherize
6379     @for String
6380   */
6381   String.prototype.dasherize = function() {
6382     return dasherize(this);
6383   };
6384
6385   /**
6386     See {{#crossLink "Ember.String/underscore"}}{{/crossLink}}
6387
6388     @method underscore
6389     @for String
6390   */
6391   String.prototype.underscore = function() {
6392     return underscore(this);
6393   };
6394
6395   /**
6396     See {{#crossLink "Ember.String/classify"}}{{/crossLink}}
6397
6398     @method classify
6399     @for String
6400   */
6401   String.prototype.classify = function() {
6402     return classify(this);
6403   };
6404 }
6405
6406
6407 })();
6408
6409
6410
6411 (function() {
6412 /**
6413 @module ember
6414 @submodule ember-runtime
6415 */
6416
6417 var a_slice = Array.prototype.slice;
6418
6419 if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Function) {
6420
6421   /**
6422     The `property` extension of Javascript's Function prototype is available
6423     when Ember.EXTEND_PROTOTYPES or Ember.EXTEND_PROTOTYPES.Function is true,
6424     which is the default.
6425
6426     Computed properties allow you to treat a function like a property:
6427
6428         MyApp.president = Ember.Object.create({
6429           firstName: "Barack",
6430           lastName: "Obama",
6431
6432           fullName: function() {
6433             return this.get('firstName') + ' ' + this.get('lastName');
6434
6435             // Call this flag to mark the function as a property
6436           }.property()
6437         });
6438
6439         MyApp.president.get('fullName');    => "Barack Obama"
6440
6441     Treating a function like a property is useful because they can work with
6442     bindings, just like any other property.
6443
6444     Many computed properties have dependencies on other properties. For
6445     example, in the above example, the `fullName` property depends on
6446     `firstName` and `lastName` to determine its value. You can tell Ember.js
6447     about these dependencies like this:
6448
6449         MyApp.president = Ember.Object.create({
6450           firstName: "Barack",
6451           lastName: "Obama",
6452
6453           fullName: function() {
6454             return this.get('firstName') + ' ' + this.get('lastName');
6455
6456             // Tell Ember.js that this computed property depends on firstName
6457             // and lastName
6458           }.property('firstName', 'lastName')
6459         });
6460
6461     Make sure you list these dependencies so Ember.js knows when to update
6462     bindings that connect to a computed property. Changing a dependency
6463     will not immediately trigger an update of the computed property, but
6464     will instead clear the cache so that it is updated when the next `get`
6465     is called on the property.
6466
6467     See {{#crossLink "Ember.ComputedProperty"}}{{/crossLink}},
6468       {{#crossLink "Ember/computed"}}{{/crossLink}}
6469
6470     @method property
6471     @for Function
6472   */
6473   Function.prototype.property = function() {
6474     var ret = Ember.computed(this);
6475     return ret.property.apply(ret, arguments);
6476   };
6477
6478   /**
6479     The `observes` extension of Javascript's Function prototype is available
6480     when Ember.EXTEND_PROTOTYPES or Ember.EXTEND_PROTOTYPES.Function is true,
6481     which is the default.
6482
6483     You can observe property changes simply by adding the `observes`
6484     call to the end of your method declarations in classes that you write.
6485     For example:
6486
6487         Ember.Object.create({
6488           valueObserver: function() {
6489             // Executes whenever the "value" property changes
6490           }.observes('value')
6491         });
6492
6493     See {{#crossLink "Ember.Observable/observes"}}{{/crossLink}}
6494
6495     @method observes
6496     @for Function
6497   */
6498   Function.prototype.observes = function() {
6499     this.__ember_observes__ = a_slice.call(arguments);
6500     return this;
6501   };
6502
6503   /**
6504     The `observesBefore` extension of Javascript's Function prototype is available
6505     when Ember.EXTEND_PROTOTYPES or Ember.EXTEND_PROTOTYPES.Function is true,
6506     which is the default.
6507
6508     You can get notified when a property changes is about to happen by
6509     by adding the `observesBefore` call to the end of your method
6510     declarations in classes that you write. For example:
6511
6512         Ember.Object.create({
6513           valueObserver: function() {
6514             // Executes whenever the "value" property is about to change
6515           }.observesBefore('value')
6516         });
6517
6518     See {{#crossLink "Ember.Observable/observesBefore"}}{{/crossLink}}
6519
6520     @method observesBefore
6521     @for Function
6522   */
6523   Function.prototype.observesBefore = function() {
6524     this.__ember_observesBefore__ = a_slice.call(arguments);
6525     return this;
6526   };
6527
6528 }
6529
6530
6531 })();
6532
6533
6534
6535 (function() {
6536
6537 })();
6538
6539
6540
6541 (function() {
6542 /**
6543 @module ember
6544 @submodule ember-runtime
6545 */
6546
6547 // ..........................................................
6548 // HELPERS
6549 //
6550
6551 var get = Ember.get, set = Ember.set;
6552 var a_slice = Array.prototype.slice;
6553 var a_indexOf = Ember.EnumerableUtils.indexOf;
6554
6555 var contexts = [];
6556
6557 function popCtx() {
6558   return contexts.length===0 ? {} : contexts.pop();
6559 }
6560
6561 function pushCtx(ctx) {
6562   contexts.push(ctx);
6563   return null;
6564 }
6565
6566 function iter(key, value) {
6567   var valueProvided = arguments.length === 2;
6568
6569   function i(item) {
6570     var cur = get(item, key);
6571     return valueProvided ? value===cur : !!cur;
6572   }
6573   return i ;
6574 }
6575
6576 /**
6577   This mixin defines the common interface implemented by enumerable objects
6578   in Ember.  Most of these methods follow the standard Array iteration
6579   API defined up to JavaScript 1.8 (excluding language-specific features that
6580   cannot be emulated in older versions of JavaScript).
6581
6582   This mixin is applied automatically to the Array class on page load, so you
6583   can use any of these methods on simple arrays.  If Array already implements
6584   one of these methods, the mixin will not override them.
6585
6586   ## Writing Your Own Enumerable
6587
6588   To make your own custom class enumerable, you need two items:
6589
6590   1. You must have a length property.  This property should change whenever
6591      the number of items in your enumerable object changes.  If you using this
6592      with an Ember.Object subclass, you should be sure to change the length
6593      property using set().
6594
6595   2. If you must implement nextObject().  See documentation.
6596
6597   Once you have these two methods implement, apply the Ember.Enumerable mixin
6598   to your class and you will be able to enumerate the contents of your object
6599   like any other collection.
6600
6601   ## Using Ember Enumeration with Other Libraries
6602
6603   Many other libraries provide some kind of iterator or enumeration like
6604   facility.  This is often where the most common API conflicts occur.
6605   Ember's API is designed to be as friendly as possible with other
6606   libraries by implementing only methods that mostly correspond to the
6607   JavaScript 1.8 API.
6608
6609   @class Enumerable
6610   @namespace Ember
6611   @extends Ember.Mixin
6612   @since Ember 0.9
6613 */
6614 Ember.Enumerable = Ember.Mixin.create(
6615   /** @scope Ember.Enumerable.prototype */ {
6616
6617   // compatibility
6618   isEnumerable: true,
6619
6620   /**
6621     Implement this method to make your class enumerable.
6622
6623     This method will be call repeatedly during enumeration.  The index value
6624     will always begin with 0 and increment monotonically.  You don't have to
6625     rely on the index value to determine what object to return, but you should
6626     always check the value and start from the beginning when you see the
6627     requested index is 0.
6628
6629     The previousObject is the object that was returned from the last call
6630     to nextObject for the current iteration.  This is a useful way to
6631     manage iteration if you are tracing a linked list, for example.
6632
6633     Finally the context parameter will always contain a hash you can use as
6634     a "scratchpad" to maintain any other state you need in order to iterate
6635     properly.  The context object is reused and is not reset between
6636     iterations so make sure you setup the context with a fresh state whenever
6637     the index parameter is 0.
6638
6639     Generally iterators will continue to call nextObject until the index
6640     reaches the your current length-1.  If you run out of data before this
6641     time for some reason, you should simply return undefined.
6642
6643     The default implementation of this method simply looks up the index.
6644     This works great on any Array-like objects.
6645
6646     @method nextObject
6647     @param {Number} index the current index of the iteration
6648     @param {Object} previousObject the value returned by the last call to nextObject.
6649     @param {Object} context a context object you can use to maintain state.
6650     @return {Object} the next object in the iteration or undefined
6651   */
6652   nextObject: Ember.required(Function),
6653
6654   /**
6655     Helper method returns the first object from a collection.  This is usually
6656     used by bindings and other parts of the framework to extract a single
6657     object if the enumerable contains only one item.
6658
6659     If you override this method, you should implement it so that it will
6660     always return the same value each time it is called.  If your enumerable
6661     contains only one object, this method should always return that object.
6662     If your enumerable is empty, this method should return undefined.
6663
6664         var arr = ["a", "b", "c"];
6665         arr.firstObject(); => "a"
6666
6667         var arr = [];
6668         arr.firstObject(); => undefined
6669
6670     @property firstObject
6671     @return {Object} the object or undefined
6672   */
6673   firstObject: Ember.computed(function() {
6674     if (get(this, 'length')===0) return undefined ;
6675
6676     // handle generic enumerables
6677     var context = popCtx(), ret;
6678     ret = this.nextObject(0, null, context);
6679     pushCtx(context);
6680     return ret ;
6681   }).property('[]'),
6682
6683   /**
6684     Helper method returns the last object from a collection. If your enumerable
6685     contains only one object, this method should always return that object.
6686     If your enumerable is empty, this method should return undefined.
6687
6688         var arr = ["a", "b", "c"];
6689         arr.lastObject(); => "c"
6690
6691         var arr = [];
6692         arr.lastObject(); => undefined
6693
6694     @property lastObject
6695     @return {Object} the last object or undefined
6696   */
6697   lastObject: Ember.computed(function() {
6698     var len = get(this, 'length');
6699     if (len===0) return undefined ;
6700     var context = popCtx(), idx=0, cur, last = null;
6701     do {
6702       last = cur;
6703       cur = this.nextObject(idx++, last, context);
6704     } while (cur !== undefined);
6705     pushCtx(context);
6706     return last;
6707   }).property('[]'),
6708
6709   /**
6710     Returns true if the passed object can be found in the receiver.  The
6711     default version will iterate through the enumerable until the object
6712     is found.  You may want to override this with a more efficient version.
6713
6714         var arr = ["a", "b", "c"];
6715         arr.contains("a"); => true
6716         arr.contains("z"); => false
6717
6718     @method contains
6719     @param {Object} obj The object to search for.
6720     @return {Boolean} true if object is found in enumerable.
6721   */
6722   contains: function(obj) {
6723     return this.find(function(item) { return item===obj; }) !== undefined;
6724   },
6725
6726   /**
6727     Iterates through the enumerable, calling the passed function on each
6728     item. This method corresponds to the forEach() method defined in
6729     JavaScript 1.6.
6730
6731     The callback method you provide should have the following signature (all
6732     parameters are optional):
6733
6734           function(item, index, enumerable);
6735
6736     - *item* is the current item in the iteration.
6737     - *index* is the current index in the iteration
6738     - *enumerable* is the enumerable object itself.
6739
6740     Note that in addition to a callback, you can also pass an optional target
6741     object that will be set as "this" on the context. This is a good way
6742     to give your iterator function access to the current object.
6743
6744     @method forEach
6745     @param {Function} callback The callback to execute
6746     @param {Object} [target] The target object to use
6747     @return {Object} receiver
6748   */
6749   forEach: function(callback, target) {
6750     if (typeof callback !== "function") throw new TypeError() ;
6751     var len = get(this, 'length'), last = null, context = popCtx();
6752
6753     if (target === undefined) target = null;
6754
6755     for(var idx=0;idx<len;idx++) {
6756       var next = this.nextObject(idx, last, context) ;
6757       callback.call(target, next, idx, this);
6758       last = next ;
6759     }
6760     last = null ;
6761     context = pushCtx(context);
6762     return this ;
6763   },
6764
6765   /**
6766     Alias for mapProperty
6767
6768     @method getEach
6769     @param {String} key name of the property
6770     @return {Array} The mapped array.
6771   */
6772   getEach: function(key) {
6773     return this.mapProperty(key);
6774   },
6775
6776   /**
6777     Sets the value on the named property for each member. This is more
6778     efficient than using other methods defined on this helper. If the object
6779     implements Ember.Observable, the value will be changed to set(), otherwise
6780     it will be set directly. null objects are skipped.
6781
6782     @method setEach
6783     @param {String} key The key to set
6784     @param {Object} value The object to set
6785     @return {Object} receiver
6786   */
6787   setEach: function(key, value) {
6788     return this.forEach(function(item) {
6789       set(item, key, value);
6790     });
6791   },
6792
6793   /**
6794     Maps all of the items in the enumeration to another value, returning
6795     a new array. This method corresponds to map() defined in JavaScript 1.6.
6796
6797     The callback method you provide should have the following signature (all
6798     parameters are optional):
6799
6800         function(item, index, enumerable);
6801
6802     - *item* is the current item in the iteration.
6803     - *index* is the current index in the iteration
6804     - *enumerable* is the enumerable object itself.
6805
6806     It should return the mapped value.
6807
6808     Note that in addition to a callback, you can also pass an optional target
6809     object that will be set as "this" on the context. This is a good way
6810     to give your iterator function access to the current object.
6811
6812     @method map
6813     @param {Function} callback The callback to execute
6814     @param {Object} [target] The target object to use
6815     @return {Array} The mapped array.
6816   */
6817   map: function(callback, target) {
6818     var ret = [];
6819     this.forEach(function(x, idx, i) {
6820       ret[idx] = callback.call(target, x, idx,i);
6821     });
6822     return ret ;
6823   },
6824
6825   /**
6826     Similar to map, this specialized function returns the value of the named
6827     property on all items in the enumeration.
6828
6829     @method mapProperty
6830     @param {String} key name of the property
6831     @return {Array} The mapped array.
6832   */
6833   mapProperty: function(key) {
6834     return this.map(function(next) {
6835       return get(next, key);
6836     });
6837   },
6838
6839   /**
6840     Returns an array with all of the items in the enumeration that the passed
6841     function returns true for. This method corresponds to filter() defined in
6842     JavaScript 1.6.
6843
6844     The callback method you provide should have the following signature (all
6845     parameters are optional):
6846
6847           function(item, index, enumerable);
6848
6849     - *item* is the current item in the iteration.
6850     - *index* is the current index in the iteration
6851     - *enumerable* is the enumerable object itself.
6852
6853     It should return the true to include the item in the results, false otherwise.
6854
6855     Note that in addition to a callback, you can also pass an optional target
6856     object that will be set as "this" on the context. This is a good way
6857     to give your iterator function access to the current object.
6858
6859     @method filter
6860     @param {Function} callback The callback to execute
6861     @param {Object} [target] The target object to use
6862     @return {Array} A filtered array.
6863   */
6864   filter: function(callback, target) {
6865     var ret = [];
6866     this.forEach(function(x, idx, i) {
6867       if (callback.call(target, x, idx, i)) ret.push(x);
6868     });
6869     return ret ;
6870   },
6871
6872   /**
6873     Returns an array with just the items with the matched property.  You
6874     can pass an optional second argument with the target value.  Otherwise
6875     this will match any property that evaluates to true.
6876
6877     @method filterProperty
6878     @param {String} key the property to test
6879     @param {String} [value] optional value to test against.
6880     @return {Array} filtered array
6881   */
6882   filterProperty: function(key, value) {
6883     return this.filter(iter.apply(this, arguments));
6884   },
6885
6886   /**
6887     Returns the first item in the array for which the callback returns true.
6888     This method works similar to the filter() method defined in JavaScript 1.6
6889     except that it will stop working on the array once a match is found.
6890
6891     The callback method you provide should have the following signature (all
6892     parameters are optional):
6893
6894           function(item, index, enumerable);
6895
6896     - *item* is the current item in the iteration.
6897     - *index* is the current index in the iteration
6898     - *enumerable* is the enumerable object itself.
6899
6900     It should return the true to include the item in the results, false otherwise.
6901
6902     Note that in addition to a callback, you can also pass an optional target
6903     object that will be set as "this" on the context. This is a good way
6904     to give your iterator function access to the current object.
6905
6906     @method find
6907     @param {Function} callback The callback to execute
6908     @param {Object} [target] The target object to use
6909     @return {Object} Found item or null.
6910   */
6911   find: function(callback, target) {
6912     var len = get(this, 'length') ;
6913     if (target === undefined) target = null;
6914
6915     var last = null, next, found = false, ret ;
6916     var context = popCtx();
6917     for(var idx=0;idx<len && !found;idx++) {
6918       next = this.nextObject(idx, last, context) ;
6919       if (found = callback.call(target, next, idx, this)) ret = next ;
6920       last = next ;
6921     }
6922     next = last = null ;
6923     context = pushCtx(context);
6924     return ret ;
6925   },
6926
6927   /**
6928     Returns the first item with a property matching the passed value.  You
6929     can pass an optional second argument with the target value.  Otherwise
6930     this will match any property that evaluates to true.
6931
6932     This method works much like the more generic find() method.
6933
6934     @method findProperty
6935     @param {String} key the property to test
6936     @param {String} [value] optional value to test against.
6937     @return {Object} found item or null
6938   */
6939   findProperty: function(key, value) {
6940     return this.find(iter.apply(this, arguments));
6941   },
6942
6943   /**
6944     Returns true if the passed function returns true for every item in the
6945     enumeration. This corresponds with the every() method in JavaScript 1.6.
6946
6947     The callback method you provide should have the following signature (all
6948     parameters are optional):
6949
6950           function(item, index, enumerable);
6951
6952     - *item* is the current item in the iteration.
6953     - *index* is the current index in the iteration
6954     - *enumerable* is the enumerable object itself.
6955
6956     It should return the true or false.
6957
6958     Note that in addition to a callback, you can also pass an optional target
6959     object that will be set as "this" on the context. This is a good way
6960     to give your iterator function access to the current object.
6961
6962     Example Usage:
6963
6964           if (people.every(isEngineer)) { Paychecks.addBigBonus(); }
6965
6966     @method every
6967     @param {Function} callback The callback to execute
6968     @param {Object} [target] The target object to use
6969     @return {Boolean}
6970   */
6971   every: function(callback, target) {
6972     return !this.find(function(x, idx, i) {
6973       return !callback.call(target, x, idx, i);
6974     });
6975   },
6976
6977   /**
6978     Returns true if the passed property resolves to true for all items in the
6979     enumerable.  This method is often simpler/faster than using a callback.
6980
6981     @method everyProperty
6982     @param {String} key the property to test
6983     @param {String} [value] optional value to test against.
6984     @return {Array} filtered array
6985   */
6986   everyProperty: function(key, value) {
6987     return this.every(iter.apply(this, arguments));
6988   },
6989
6990
6991   /**
6992     Returns true if the passed function returns true for any item in the
6993     enumeration. This corresponds with the every() method in JavaScript 1.6.
6994
6995     The callback method you provide should have the following signature (all
6996     parameters are optional):
6997
6998           function(item, index, enumerable);
6999
7000     - *item* is the current item in the iteration.
7001     - *index* is the current index in the iteration
7002     - *enumerable* is the enumerable object itself.
7003
7004     It should return the true to include the item in the results, false otherwise.
7005
7006     Note that in addition to a callback, you can also pass an optional target
7007     object that will be set as "this" on the context. This is a good way
7008     to give your iterator function access to the current object.
7009
7010     Usage Example:
7011
7012           if (people.some(isManager)) { Paychecks.addBiggerBonus(); }
7013
7014     @method some
7015     @param {Function} callback The callback to execute
7016     @param {Object} [target] The target object to use
7017     @return {Array} A filtered array.
7018   */
7019   some: function(callback, target) {
7020     return !!this.find(function(x, idx, i) {
7021       return !!callback.call(target, x, idx, i);
7022     });
7023   },
7024
7025   /**
7026     Returns true if the passed property resolves to true for any item in the
7027     enumerable.  This method is often simpler/faster than using a callback.
7028
7029     @method someProperty
7030     @param {String} key the property to test
7031     @param {String} [value] optional value to test against.
7032     @return {Boolean} true
7033   */
7034   someProperty: function(key, value) {
7035     return this.some(iter.apply(this, arguments));
7036   },
7037
7038   /**
7039     This will combine the values of the enumerator into a single value. It
7040     is a useful way to collect a summary value from an enumeration. This
7041     corresponds to the reduce() method defined in JavaScript 1.8.
7042
7043     The callback method you provide should have the following signature (all
7044     parameters are optional):
7045
7046           function(previousValue, item, index, enumerable);
7047
7048     - *previousValue* is the value returned by the last call to the iterator.
7049     - *item* is the current item in the iteration.
7050     - *index* is the current index in the iteration
7051     - *enumerable* is the enumerable object itself.
7052
7053     Return the new cumulative value.
7054
7055     In addition to the callback you can also pass an initialValue. An error
7056     will be raised if you do not pass an initial value and the enumerator is
7057     empty.
7058
7059     Note that unlike the other methods, this method does not allow you to
7060     pass a target object to set as this for the callback. It's part of the
7061     spec. Sorry.
7062
7063     @method reduce
7064     @param {Function} callback The callback to execute
7065     @param {Object} initialValue Initial value for the reduce
7066     @param {String} reducerProperty internal use only.
7067     @return {Object} The reduced value.
7068   */
7069   reduce: function(callback, initialValue, reducerProperty) {
7070     if (typeof callback !== "function") { throw new TypeError(); }
7071
7072     var ret = initialValue;
7073
7074     this.forEach(function(item, i) {
7075       ret = callback.call(null, ret, item, i, this, reducerProperty);
7076     }, this);
7077
7078     return ret;
7079   },
7080
7081   /**
7082     Invokes the named method on every object in the receiver that
7083     implements it.  This method corresponds to the implementation in
7084     Prototype 1.6.
7085
7086     @method invoke
7087     @param {String} methodName the name of the method
7088     @param {Object...} args optional arguments to pass as well.
7089     @return {Array} return values from calling invoke.
7090   */
7091   invoke: function(methodName) {
7092     var args, ret = [];
7093     if (arguments.length>1) args = a_slice.call(arguments, 1);
7094
7095     this.forEach(function(x, idx) {
7096       var method = x && x[methodName];
7097       if ('function' === typeof method) {
7098         ret[idx] = args ? method.apply(x, args) : method.call(x);
7099       }
7100     }, this);
7101
7102     return ret;
7103   },
7104
7105   /**
7106     Simply converts the enumerable into a genuine array.  The order is not
7107     guaranteed.  Corresponds to the method implemented by Prototype.
7108
7109     @method toArray
7110     @return {Array} the enumerable as an array.
7111   */
7112   toArray: function() {
7113     var ret = [];
7114     this.forEach(function(o, idx) { ret[idx] = o; });
7115     return ret ;
7116   },
7117
7118   /**
7119     Returns a copy of the array with all null elements removed.
7120
7121         var arr = ["a", null, "c", null];
7122         arr.compact(); => ["a", "c"]
7123
7124     @method compact
7125     @return {Array} the array without null elements.
7126   */
7127   compact: function() { return this.without(null); },
7128
7129   /**
7130     Returns a new enumerable that excludes the passed value.  The default
7131     implementation returns an array regardless of the receiver type unless
7132     the receiver does not contain the value.
7133
7134         var arr = ["a", "b", "a", "c"];
7135         arr.without("a"); => ["b", "c"]
7136
7137     @method without
7138     @param {Object} value
7139     @return {Ember.Enumerable}
7140   */
7141   without: function(value) {
7142     if (!this.contains(value)) return this; // nothing to do
7143     var ret = [] ;
7144     this.forEach(function(k) {
7145       if (k !== value) ret[ret.length] = k;
7146     }) ;
7147     return ret ;
7148   },
7149
7150   /**
7151     Returns a new enumerable that contains only unique values.  The default
7152     implementation returns an array regardless of the receiver type.
7153
7154         var arr = ["a", "a", "b", "b"];
7155         arr.uniq(); => ["a", "b"]
7156
7157     @method uniq
7158     @return {Ember.Enumerable}
7159   */
7160   uniq: function() {
7161     var ret = [];
7162     this.forEach(function(k){
7163       if (a_indexOf(ret, k)<0) ret.push(k);
7164     });
7165     return ret;
7166   },
7167
7168   /**
7169     This property will trigger anytime the enumerable's content changes.
7170     You can observe this property to be notified of changes to the enumerables
7171     content.
7172
7173     For plain enumerables, this property is read only.  Ember.Array overrides
7174     this method.
7175
7176     @property []
7177     @type Ember.Array
7178   */
7179   '[]': Ember.computed(function(key, value) {
7180     return this;
7181   }).property(),
7182
7183   // ..........................................................
7184   // ENUMERABLE OBSERVERS
7185   //
7186
7187   /**
7188     Registers an enumerable observer.   Must implement Ember.EnumerableObserver
7189     mixin.
7190
7191     @method addEnumerableObserver
7192     @param target {Object}
7193     @param opts {Hash}
7194   */
7195   addEnumerableObserver: function(target, opts) {
7196     var willChange = (opts && opts.willChange) || 'enumerableWillChange',
7197         didChange  = (opts && opts.didChange) || 'enumerableDidChange';
7198
7199     var hasObservers = get(this, 'hasEnumerableObservers');
7200     if (!hasObservers) Ember.propertyWillChange(this, 'hasEnumerableObservers');
7201     Ember.addListener(this, '@enumerable:before', target, willChange);
7202     Ember.addListener(this, '@enumerable:change', target, didChange);
7203     if (!hasObservers) Ember.propertyDidChange(this, 'hasEnumerableObservers');
7204     return this;
7205   },
7206
7207   /**
7208     Removes a registered enumerable observer.
7209
7210     @method removeEnumerableObserver
7211     @param target {Object}
7212     @param [opts] {Hash}
7213   */
7214   removeEnumerableObserver: function(target, opts) {
7215     var willChange = (opts && opts.willChange) || 'enumerableWillChange',
7216         didChange  = (opts && opts.didChange) || 'enumerableDidChange';
7217
7218     var hasObservers = get(this, 'hasEnumerableObservers');
7219     if (hasObservers) Ember.propertyWillChange(this, 'hasEnumerableObservers');
7220     Ember.removeListener(this, '@enumerable:before', target, willChange);
7221     Ember.removeListener(this, '@enumerable:change', target, didChange);
7222     if (hasObservers) Ember.propertyDidChange(this, 'hasEnumerableObservers');
7223     return this;
7224   },
7225
7226   /**
7227     Becomes true whenever the array currently has observers watching changes
7228     on the array.
7229
7230     @property hasEnumerableObservers
7231     @type Boolean
7232   */
7233   hasEnumerableObservers: Ember.computed(function() {
7234     return Ember.hasListeners(this, '@enumerable:change') || Ember.hasListeners(this, '@enumerable:before');
7235   }).property(),
7236
7237
7238   /**
7239     Invoke this method just before the contents of your enumerable will
7240     change.  You can either omit the parameters completely or pass the objects
7241     to be removed or added if available or just a count.
7242
7243     @method enumerableContentWillChange
7244     @param {Ember.Enumerable|Number} removing An enumerable of the objects to
7245       be removed or the number of items to be removed.
7246     @param {Ember.Enumerable|Number} adding An enumerable of the objects to be
7247       added or the number of items to be added.
7248     @chainable
7249   */
7250   enumerableContentWillChange: function(removing, adding) {
7251
7252     var removeCnt, addCnt, hasDelta;
7253
7254     if ('number' === typeof removing) removeCnt = removing;
7255     else if (removing) removeCnt = get(removing, 'length');
7256     else removeCnt = removing = -1;
7257
7258     if ('number' === typeof adding) addCnt = adding;
7259     else if (adding) addCnt = get(adding,'length');
7260     else addCnt = adding = -1;
7261
7262     hasDelta = addCnt<0 || removeCnt<0 || addCnt-removeCnt!==0;
7263
7264     if (removing === -1) removing = null;
7265     if (adding   === -1) adding   = null;
7266
7267     Ember.propertyWillChange(this, '[]');
7268     if (hasDelta) Ember.propertyWillChange(this, 'length');
7269     Ember.sendEvent(this, '@enumerable:before', [this, removing, adding]);
7270
7271     return this;
7272   },
7273
7274   /**
7275     Invoke this method when the contents of your enumerable has changed.
7276     This will notify any observers watching for content changes.  If your are
7277     implementing an ordered enumerable (such as an array), also pass the
7278     start and end values where the content changed so that it can be used to
7279     notify range observers.
7280
7281     @method enumerableContentDidChange
7282     @param {Number} [start] optional start offset for the content change.
7283       For unordered enumerables, you should always pass -1.
7284     @param {Ember.Enumerable|Number} removing An enumerable of the objects to
7285       be removed or the number of items to be removed.
7286     @param {Ember.Enumerable|Number} adding  An enumerable of the objects to
7287       be added or the number of items to be added.
7288     @chainable
7289   */
7290   enumerableContentDidChange: function(removing, adding) {
7291     var notify = this.propertyDidChange, removeCnt, addCnt, hasDelta;
7292
7293     if ('number' === typeof removing) removeCnt = removing;
7294     else if (removing) removeCnt = get(removing, 'length');
7295     else removeCnt = removing = -1;
7296
7297     if ('number' === typeof adding) addCnt = adding;
7298     else if (adding) addCnt = get(adding, 'length');
7299     else addCnt = adding = -1;
7300
7301     hasDelta = addCnt<0 || removeCnt<0 || addCnt-removeCnt!==0;
7302
7303     if (removing === -1) removing = null;
7304     if (adding   === -1) adding   = null;
7305
7306     Ember.sendEvent(this, '@enumerable:change', [this, removing, adding]);
7307     if (hasDelta) Ember.propertyDidChange(this, 'length');
7308     Ember.propertyDidChange(this, '[]');
7309
7310     return this ;
7311   }
7312
7313 }) ;
7314
7315
7316
7317
7318 })();
7319
7320
7321
7322 (function() {
7323 /**
7324 @module ember
7325 @submodule ember-runtime
7326 */
7327
7328 // ..........................................................
7329 // HELPERS
7330 //
7331
7332 var get = Ember.get, set = Ember.set, meta = Ember.meta, map = Ember.EnumerableUtils.map, cacheFor = Ember.cacheFor;
7333
7334 function none(obj) { return obj===null || obj===undefined; }
7335
7336 // ..........................................................
7337 // ARRAY
7338 //
7339 /**
7340   This module implements Observer-friendly Array-like behavior.  This mixin is
7341   picked up by the Array class as well as other controllers, etc. that want to
7342   appear to be arrays.
7343
7344   Unlike Ember.Enumerable, this mixin defines methods specifically for
7345   collections that provide index-ordered access to their contents.  When you
7346   are designing code that needs to accept any kind of Array-like object, you
7347   should use these methods instead of Array primitives because these will
7348   properly notify observers of changes to the array.
7349
7350   Although these methods are efficient, they do add a layer of indirection to
7351   your application so it is a good idea to use them only when you need the
7352   flexibility of using both true JavaScript arrays and "virtual" arrays such
7353   as controllers and collections.
7354
7355   You can use the methods defined in this module to access and modify array
7356   contents in a KVO-friendly way.  You can also be notified whenever the
7357   membership if an array changes by changing the syntax of the property to
7358   .observes('*myProperty.[]') .
7359
7360   To support Ember.Array in your own class, you must override two
7361   primitives to use it: replace() and objectAt().
7362
7363   Note that the Ember.Array mixin also incorporates the Ember.Enumerable mixin.  All
7364   Ember.Array-like objects are also enumerable.
7365
7366   @class Array
7367   @namespace Ember
7368   @extends Ember.Mixin
7369   @uses Ember.Enumerable
7370   @since Ember 0.9.0
7371 */
7372 Ember.Array = Ember.Mixin.create(Ember.Enumerable, /** @scope Ember.Array.prototype */ {
7373
7374   // compatibility
7375   isSCArray: true,
7376
7377   /**
7378     Your array must support the length property. Your replace methods should
7379     set this property whenever it changes.
7380
7381     @property {Number} length
7382   */
7383   length: Ember.required(),
7384
7385   /**
7386     Returns the object at the given index. If the given index is negative or
7387     is greater or equal than the array length, returns `undefined`.
7388
7389     This is one of the primitives you must implement to support `Ember.Array`.
7390     If your object supports retrieving the value of an array item using `get()`
7391     (i.e. `myArray.get(0)`), then you do not need to implement this method
7392     yourself.
7393
7394         var arr = ['a', 'b', 'c', 'd'];
7395         arr.objectAt(0);  => "a"
7396         arr.objectAt(3);  => "d"
7397         arr.objectAt(-1); => undefined
7398         arr.objectAt(4);  => undefined
7399         arr.objectAt(5);  => undefined
7400
7401     @method objectAt
7402     @param {Number} idx
7403       The index of the item to return.
7404   */
7405   objectAt: function(idx) {
7406     if ((idx < 0) || (idx>=get(this, 'length'))) return undefined ;
7407     return get(this, idx);
7408   },
7409
7410   /**
7411     This returns the objects at the specified indexes, using `objectAt`.
7412
7413         var arr = ['a', 'b', 'c', 'd'];
7414         arr.objectsAt([0, 1, 2]) => ["a", "b", "c"]
7415         arr.objectsAt([2, 3, 4]) => ["c", "d", undefined]
7416
7417     @method objectsAt
7418     @param {Array} indexes
7419       An array of indexes of items to return.
7420    */
7421   objectsAt: function(indexes) {
7422     var self = this;
7423     return map(indexes, function(idx){ return self.objectAt(idx); });
7424   },
7425
7426   // overrides Ember.Enumerable version
7427   nextObject: function(idx) {
7428     return this.objectAt(idx);
7429   },
7430
7431   /**
7432     This is the handler for the special array content property.  If you get
7433     this property, it will return this.  If you set this property it a new
7434     array, it will replace the current content.
7435
7436     This property overrides the default property defined in Ember.Enumerable.
7437
7438     @property []
7439   */
7440   '[]': Ember.computed(function(key, value) {
7441     if (value !== undefined) this.replace(0, get(this, 'length'), value) ;
7442     return this ;
7443   }).property(),
7444
7445   firstObject: Ember.computed(function() {
7446     return this.objectAt(0);
7447   }).property(),
7448
7449   lastObject: Ember.computed(function() {
7450     return this.objectAt(get(this, 'length')-1);
7451   }).property(),
7452
7453   // optimized version from Enumerable
7454   contains: function(obj){
7455     return this.indexOf(obj) >= 0;
7456   },
7457
7458   // Add any extra methods to Ember.Array that are native to the built-in Array.
7459   /**
7460     Returns a new array that is a slice of the receiver. This implementation
7461     uses the observable array methods to retrieve the objects for the new
7462     slice.
7463
7464         var arr = ['red', 'green', 'blue'];
7465         arr.slice(0);      => ['red', 'green', 'blue']
7466         arr.slice(0, 2);   => ['red', 'green']
7467         arr.slice(1, 100); => ['green', 'blue']
7468
7469     @method slice
7470     @param beginIndex {Integer} (Optional) index to begin slicing from.
7471     @param endIndex {Integer} (Optional) index to end the slice at.
7472     @return {Array} New array with specified slice
7473   */
7474   slice: function(beginIndex, endIndex) {
7475     var ret = [];
7476     var length = get(this, 'length') ;
7477     if (none(beginIndex)) beginIndex = 0 ;
7478     if (none(endIndex) || (endIndex > length)) endIndex = length ;
7479     while(beginIndex < endIndex) {
7480       ret[ret.length] = this.objectAt(beginIndex++) ;
7481     }
7482     return ret ;
7483   },
7484
7485   /**
7486     Returns the index of the given object's first occurrence.
7487     If no startAt argument is given, the starting location to
7488     search is 0. If it's negative, will count backward from
7489     the end of the array. Returns -1 if no match is found.
7490
7491         var arr = ["a", "b", "c", "d", "a"];
7492         arr.indexOf("a");      =>  0
7493         arr.indexOf("z");      => -1
7494         arr.indexOf("a", 2);   =>  4
7495         arr.indexOf("a", -1);  =>  4
7496         arr.indexOf("b", 3);   => -1
7497         arr.indexOf("a", 100); => -1
7498
7499     @method indexOf
7500     @param {Object} object the item to search for
7501     @param {Number} startAt optional starting location to search, default 0
7502     @return {Number} index or -1 if not found
7503   */
7504   indexOf: function(object, startAt) {
7505     var idx, len = get(this, 'length');
7506
7507     if (startAt === undefined) startAt = 0;
7508     if (startAt < 0) startAt += len;
7509
7510     for(idx=startAt;idx<len;idx++) {
7511       if (this.objectAt(idx, true) === object) return idx ;
7512     }
7513     return -1;
7514   },
7515
7516   /**
7517     Returns the index of the given object's last occurrence.
7518     If no startAt argument is given, the search starts from
7519     the last position. If it's negative, will count backward
7520     from the end of the array. Returns -1 if no match is found.
7521
7522         var arr = ["a", "b", "c", "d", "a"];
7523         arr.lastIndexOf("a");      =>  4
7524         arr.lastIndexOf("z");      => -1
7525         arr.lastIndexOf("a", 2);   =>  0
7526         arr.lastIndexOf("a", -1);  =>  4
7527         arr.lastIndexOf("b", 3);   =>  1
7528         arr.lastIndexOf("a", 100); =>  4
7529
7530     @method lastIndexOf
7531     @param {Object} object the item to search for
7532     @param {Number} startAt optional starting location to search, default 0
7533     @return {Number} index or -1 if not found
7534   */
7535   lastIndexOf: function(object, startAt) {
7536     var idx, len = get(this, 'length');
7537
7538     if (startAt === undefined || startAt >= len) startAt = len-1;
7539     if (startAt < 0) startAt += len;
7540
7541     for(idx=startAt;idx>=0;idx--) {
7542       if (this.objectAt(idx) === object) return idx ;
7543     }
7544     return -1;
7545   },
7546
7547   // ..........................................................
7548   // ARRAY OBSERVERS
7549   //
7550
7551   /**
7552     Adds an array observer to the receiving array.  The array observer object
7553     normally must implement two methods:
7554
7555     * `arrayWillChange(start, removeCount, addCount)` - This method will be
7556       called just before the array is modified.
7557     * `arrayDidChange(start, removeCount, addCount)` - This method will be
7558       called just after the array is modified.
7559
7560     Both callbacks will be passed the starting index of the change as well a
7561     a count of the items to be removed and added.  You can use these callbacks
7562     to optionally inspect the array during the change, clear caches, or do
7563     any other bookkeeping necessary.
7564
7565     In addition to passing a target, you can also include an options hash
7566     which you can use to override the method names that will be invoked on the
7567     target.
7568
7569     @method addArrayObserver
7570     @param {Object} target The observer object.
7571     @param {Hash} opts Optional hash of configuration options including
7572       willChange, didChange, and a context option.
7573     @return {Ember.Array} receiver
7574   */
7575   addArrayObserver: function(target, opts) {
7576     var willChange = (opts && opts.willChange) || 'arrayWillChange',
7577         didChange  = (opts && opts.didChange) || 'arrayDidChange';
7578
7579     var hasObservers = get(this, 'hasArrayObservers');
7580     if (!hasObservers) Ember.propertyWillChange(this, 'hasArrayObservers');
7581     Ember.addListener(this, '@array:before', target, willChange);
7582     Ember.addListener(this, '@array:change', target, didChange);
7583     if (!hasObservers) Ember.propertyDidChange(this, 'hasArrayObservers');
7584     return this;
7585   },
7586
7587   /**
7588     Removes an array observer from the object if the observer is current
7589     registered.  Calling this method multiple times with the same object will
7590     have no effect.
7591
7592     @method removeArrayObserver
7593     @param {Object} target The object observing the array.
7594     @return {Ember.Array} receiver
7595   */
7596   removeArrayObserver: function(target, opts) {
7597     var willChange = (opts && opts.willChange) || 'arrayWillChange',
7598         didChange  = (opts && opts.didChange) || 'arrayDidChange';
7599
7600     var hasObservers = get(this, 'hasArrayObservers');
7601     if (hasObservers) Ember.propertyWillChange(this, 'hasArrayObservers');
7602     Ember.removeListener(this, '@array:before', target, willChange);
7603     Ember.removeListener(this, '@array:change', target, didChange);
7604     if (hasObservers) Ember.propertyDidChange(this, 'hasArrayObservers');
7605     return this;
7606   },
7607
7608   /**
7609     Becomes true whenever the array currently has observers watching changes
7610     on the array.
7611
7612     @property Boolean
7613   */
7614   hasArrayObservers: Ember.computed(function() {
7615     return Ember.hasListeners(this, '@array:change') || Ember.hasListeners(this, '@array:before');
7616   }).property(),
7617
7618   /**
7619     If you are implementing an object that supports Ember.Array, call this
7620     method just before the array content changes to notify any observers and
7621     invalidate any related properties.  Pass the starting index of the change
7622     as well as a delta of the amounts to change.
7623
7624     @method arrayContentWillChange
7625     @param {Number} startIdx The starting index in the array that will change.
7626     @param {Number} removeAmt The number of items that will be removed.  If you pass null assumes 0
7627     @param {Number} addAmt The number of items that will be added.  If you pass null assumes 0.
7628     @return {Ember.Array} receiver
7629   */
7630   arrayContentWillChange: function(startIdx, removeAmt, addAmt) {
7631
7632     // if no args are passed assume everything changes
7633     if (startIdx===undefined) {
7634       startIdx = 0;
7635       removeAmt = addAmt = -1;
7636     } else {
7637       if (removeAmt === undefined) removeAmt=-1;
7638       if (addAmt    === undefined) addAmt=-1;
7639     }
7640
7641     // Make sure the @each proxy is set up if anyone is observing @each
7642     if (Ember.isWatching(this, '@each')) { get(this, '@each'); }
7643
7644     Ember.sendEvent(this, '@array:before', [this, startIdx, removeAmt, addAmt]);
7645
7646     var removing, lim;
7647     if (startIdx>=0 && removeAmt>=0 && get(this, 'hasEnumerableObservers')) {
7648       removing = [];
7649       lim = startIdx+removeAmt;
7650       for(var idx=startIdx;idx<lim;idx++) removing.push(this.objectAt(idx));
7651     } else {
7652       removing = removeAmt;
7653     }
7654
7655     this.enumerableContentWillChange(removing, addAmt);
7656
7657     return this;
7658   },
7659
7660   arrayContentDidChange: function(startIdx, removeAmt, addAmt) {
7661
7662     // if no args are passed assume everything changes
7663     if (startIdx===undefined) {
7664       startIdx = 0;
7665       removeAmt = addAmt = -1;
7666     } else {
7667       if (removeAmt === undefined) removeAmt=-1;
7668       if (addAmt    === undefined) addAmt=-1;
7669     }
7670
7671     var adding, lim;
7672     if (startIdx>=0 && addAmt>=0 && get(this, 'hasEnumerableObservers')) {
7673       adding = [];
7674       lim = startIdx+addAmt;
7675       for(var idx=startIdx;idx<lim;idx++) adding.push(this.objectAt(idx));
7676     } else {
7677       adding = addAmt;
7678     }
7679
7680     this.enumerableContentDidChange(removeAmt, adding);
7681     Ember.sendEvent(this, '@array:change', [this, startIdx, removeAmt, addAmt]);
7682
7683     var length      = get(this, 'length'),
7684         cachedFirst = cacheFor(this, 'firstObject'),
7685         cachedLast  = cacheFor(this, 'lastObject');
7686     if (this.objectAt(0) !== cachedFirst) {
7687       Ember.propertyWillChange(this, 'firstObject');
7688       Ember.propertyDidChange(this, 'firstObject');
7689     }
7690     if (this.objectAt(length-1) !== cachedLast) {
7691       Ember.propertyWillChange(this, 'lastObject');
7692       Ember.propertyDidChange(this, 'lastObject');
7693     }
7694
7695     return this;
7696   },
7697
7698   // ..........................................................
7699   // ENUMERATED PROPERTIES
7700   //
7701
7702   /**
7703     Returns a special object that can be used to observe individual properties
7704     on the array.  Just get an equivalent property on this object and it will
7705     return an enumerable that maps automatically to the named key on the
7706     member objects.
7707
7708     @property @each
7709   */
7710   '@each': Ember.computed(function() {
7711     if (!this.__each) this.__each = new Ember.EachProxy(this);
7712     return this.__each;
7713   }).property()
7714
7715 }) ;
7716
7717 })();
7718
7719
7720
7721 (function() {
7722 /**
7723 @module ember
7724 @submodule ember-runtime
7725 */
7726
7727
7728 /**
7729   Implements some standard methods for comparing objects. Add this mixin to
7730   any class you create that can compare its instances.
7731
7732   You should implement the compare() method.
7733
7734   @class Comparable
7735   @namespace Ember
7736   @extends Ember.Mixin
7737   @since Ember 0.9
7738 */
7739 Ember.Comparable = Ember.Mixin.create( /** @scope Ember.Comparable.prototype */{
7740
7741   /**
7742     walk like a duck. Indicates that the object can be compared.
7743
7744     @property isComparable
7745     @type Boolean
7746     @default true
7747   */
7748   isComparable: true,
7749
7750   /**
7751     Override to return the result of the comparison of the two parameters. The
7752     compare method should return:
7753
7754       - `-1` if `a < b`
7755       - `0` if `a == b`
7756       - `1` if `a > b`
7757
7758     Default implementation raises an exception.
7759
7760     @method compare
7761     @param a {Object} the first object to compare
7762     @param b {Object} the second object to compare
7763     @return {Integer} the result of the comparison
7764   */
7765   compare: Ember.required(Function)
7766
7767 });
7768
7769
7770 })();
7771
7772
7773
7774 (function() {
7775 /**
7776 @module ember
7777 @submodule ember-runtime
7778 */
7779
7780
7781
7782 var get = Ember.get, set = Ember.set;
7783
7784 /**
7785   Implements some standard methods for copying an object.  Add this mixin to
7786   any object you create that can create a copy of itself.  This mixin is
7787   added automatically to the built-in array.
7788
7789   You should generally implement the copy() method to return a copy of the
7790   receiver.
7791
7792   Note that frozenCopy() will only work if you also implement Ember.Freezable.
7793
7794   @class Copyable
7795   @namespace Ember
7796   @extends Ember.Mixin
7797   @since Ember 0.9
7798 */
7799 Ember.Copyable = Ember.Mixin.create(
7800 /** @scope Ember.Copyable.prototype */ {
7801
7802   /**
7803     Override to return a copy of the receiver.  Default implementation raises
7804     an exception.
7805
7806     @method copy
7807     @param deep {Boolean} if true, a deep copy of the object should be made
7808     @return {Object} copy of receiver
7809   */
7810   copy: Ember.required(Function),
7811
7812   /**
7813     If the object implements Ember.Freezable, then this will return a new copy
7814     if the object is not frozen and the receiver if the object is frozen.
7815
7816     Raises an exception if you try to call this method on a object that does
7817     not support freezing.
7818
7819     You should use this method whenever you want a copy of a freezable object
7820     since a freezable object can simply return itself without actually
7821     consuming more memory.
7822
7823     @method frozenCopy
7824     @return {Object} copy of receiver or receiver
7825   */
7826   frozenCopy: function() {
7827     if (Ember.Freezable && Ember.Freezable.detect(this)) {
7828       return get(this, 'isFrozen') ? this : this.copy().freeze();
7829     } else {
7830       throw new Error(Ember.String.fmt("%@ does not support freezing", [this]));
7831     }
7832   }
7833 });
7834
7835
7836
7837
7838 })();
7839
7840
7841
7842 (function() {
7843 /**
7844 @module ember
7845 @submodule ember-runtime
7846 */
7847
7848
7849 var get = Ember.get, set = Ember.set;
7850
7851 /**
7852   The Ember.Freezable mixin implements some basic methods for marking an object
7853   as frozen. Once an object is frozen it should be read only. No changes
7854   may be made the internal state of the object.
7855
7856   ## Enforcement
7857
7858   To fully support freezing in your subclass, you must include this mixin and
7859   override any method that might alter any property on the object to instead
7860   raise an exception. You can check the state of an object by checking the
7861   isFrozen property.
7862
7863   Although future versions of JavaScript may support language-level freezing
7864   object objects, that is not the case today. Even if an object is freezable,
7865   it is still technically possible to modify the object, even though it could
7866   break other parts of your application that do not expect a frozen object to
7867   change. It is, therefore, very important that you always respect the
7868   isFrozen property on all freezable objects.
7869
7870   ## Example Usage
7871
7872   The example below shows a simple object that implement the Ember.Freezable
7873   protocol.
7874
7875         Contact = Ember.Object.extend(Ember.Freezable, {
7876
7877           firstName: null,
7878
7879           lastName: null,
7880
7881           // swaps the names
7882           swapNames: function() {
7883             if (this.get('isFrozen')) throw Ember.FROZEN_ERROR;
7884             var tmp = this.get('firstName');
7885             this.set('firstName', this.get('lastName'));
7886             this.set('lastName', tmp);
7887             return this;
7888           }
7889
7890         });
7891
7892         c = Context.create({ firstName: "John", lastName: "Doe" });
7893         c.swapNames();  => returns c
7894         c.freeze();
7895         c.swapNames();  => EXCEPTION
7896
7897   ## Copying
7898
7899   Usually the Ember.Freezable protocol is implemented in cooperation with the
7900   Ember.Copyable protocol, which defines a frozenCopy() method that will return
7901   a frozen object, if the object implements this method as well.
7902
7903   @class Freezable
7904   @namespace Ember
7905   @extends Ember.Mixin
7906   @since Ember 0.9
7907 */
7908 Ember.Freezable = Ember.Mixin.create(
7909 /** @scope Ember.Freezable.prototype */ {
7910
7911   /**
7912     Set to true when the object is frozen.  Use this property to detect whether
7913     your object is frozen or not.
7914
7915     @property isFrozen
7916     @type Boolean
7917   */
7918   isFrozen: false,
7919
7920   /**
7921     Freezes the object.  Once this method has been called the object should
7922     no longer allow any properties to be edited.
7923
7924     @method freeze
7925     @return {Object} receiver
7926   */
7927   freeze: function() {
7928     if (get(this, 'isFrozen')) return this;
7929     set(this, 'isFrozen', true);
7930     return this;
7931   }
7932
7933 });
7934
7935 Ember.FROZEN_ERROR = "Frozen object cannot be modified.";
7936
7937 })();
7938
7939
7940
7941 (function() {
7942 /**
7943 @module ember
7944 @submodule ember-runtime
7945 */
7946
7947 var forEach = Ember.EnumerableUtils.forEach;
7948
7949 /**
7950   This mixin defines the API for modifying generic enumerables.  These methods
7951   can be applied to an object regardless of whether it is ordered or
7952   unordered.
7953
7954   Note that an Enumerable can change even if it does not implement this mixin.
7955   For example, a MappedEnumerable cannot be directly modified but if its
7956   underlying enumerable changes, it will change also.
7957
7958   ## Adding Objects
7959
7960   To add an object to an enumerable, use the addObject() method.  This
7961   method will only add the object to the enumerable if the object is not
7962   already present and the object if of a type supported by the enumerable.
7963
7964       set.addObject(contact);
7965
7966   ## Removing Objects
7967
7968   To remove an object form an enumerable, use the removeObject() method.  This
7969   will only remove the object if it is already in the enumerable, otherwise
7970   this method has no effect.
7971
7972       set.removeObject(contact);
7973
7974   ## Implementing In Your Own Code
7975
7976   If you are implementing an object and want to support this API, just include
7977   this mixin in your class and implement the required methods.  In your unit
7978   tests, be sure to apply the Ember.MutableEnumerableTests to your object.
7979
7980   @class MutableEnumerable
7981   @namespace Ember
7982   @extends Ember.Mixin
7983   @uses Ember.Enumerable
7984 */
7985 Ember.MutableEnumerable = Ember.Mixin.create(Ember.Enumerable,
7986   /** @scope Ember.MutableEnumerable.prototype */ {
7987
7988   /**
7989     __Required.__ You must implement this method to apply this mixin.
7990
7991     Attempts to add the passed object to the receiver if the object is not
7992     already present in the collection. If the object is present, this method
7993     has no effect.
7994
7995     If the passed object is of a type not supported by the receiver
7996     then this method should raise an exception.
7997
7998     @method addObject
7999     @param {Object} object The object to add to the enumerable.
8000     @return {Object} the passed object
8001   */
8002   addObject: Ember.required(Function),
8003
8004   /**
8005     Adds each object in the passed enumerable to the receiver.
8006
8007     @method addObjects
8008     @param {Ember.Enumerable} objects the objects to add.
8009     @return {Object} receiver
8010   */
8011   addObjects: function(objects) {
8012     Ember.beginPropertyChanges(this);
8013     forEach(objects, function(obj) { this.addObject(obj); }, this);
8014     Ember.endPropertyChanges(this);
8015     return this;
8016   },
8017
8018   /**
8019     __Required.__ You must implement this method to apply this mixin.
8020
8021     Attempts to remove the passed object from the receiver collection if the
8022     object is in present in the collection.  If the object is not present,
8023     this method has no effect.
8024
8025     If the passed object is of a type not supported by the receiver
8026     then this method should raise an exception.
8027
8028     @method removeObject
8029     @param {Object} object The object to remove from the enumerable.
8030     @return {Object} the passed object
8031   */
8032   removeObject: Ember.required(Function),
8033
8034
8035   /**
8036     Removes each objects in the passed enumerable from the receiver.
8037
8038     @method removeObjects
8039     @param {Ember.Enumerable} objects the objects to remove
8040     @return {Object} receiver
8041   */
8042   removeObjects: function(objects) {
8043     Ember.beginPropertyChanges(this);
8044     forEach(objects, function(obj) { this.removeObject(obj); }, this);
8045     Ember.endPropertyChanges(this);
8046     return this;
8047   }
8048
8049 });
8050
8051 })();
8052
8053
8054
8055 (function() {
8056 /**
8057 @module ember
8058 @submodule ember-runtime
8059 */
8060 // ..........................................................
8061 // CONSTANTS
8062 //
8063
8064 var OUT_OF_RANGE_EXCEPTION = "Index out of range" ;
8065 var EMPTY = [];
8066
8067 // ..........................................................
8068 // HELPERS
8069 //
8070
8071 var get = Ember.get, set = Ember.set, forEach = Ember.EnumerableUtils.forEach;
8072
8073 /**
8074   This mixin defines the API for modifying array-like objects.  These methods
8075   can be applied only to a collection that keeps its items in an ordered set.
8076
8077   Note that an Array can change even if it does not implement this mixin.
8078   For example, one might implement a SparseArray that cannot be directly
8079   modified, but if its underlying enumerable changes, it will change also.
8080
8081   @class MutableArray
8082   @namespace Ember
8083   @extends Ember.Mixin
8084   @uses Ember.Array
8085   @uses Ember.MutableEnumerable
8086 */
8087 Ember.MutableArray = Ember.Mixin.create(Ember.Array, Ember.MutableEnumerable,
8088   /** @scope Ember.MutableArray.prototype */ {
8089
8090   /**
8091     __Required.__ You must implement this method to apply this mixin.
8092
8093     This is one of the primitives you must implement to support Ember.Array.  You
8094     should replace amt objects started at idx with the objects in the passed
8095     array.  You should also call this.enumerableContentDidChange() ;
8096
8097     @method replace
8098     @param {Number} idx Starting index in the array to replace.  If idx >= length,
8099       then append to the end of the array.
8100     @param {Number} amt Number of elements that should be removed from the array,
8101       starting at *idx*.
8102     @param {Array} objects An array of zero or more objects that should be inserted
8103       into the array at *idx*
8104   */
8105   replace: Ember.required(),
8106
8107   /**
8108     Remove all elements from self. This is useful if you
8109     want to reuse an existing array without having to recreate it.
8110
8111         var colors = ["red", "green", "blue"];
8112         color.length();  => 3
8113         colors.clear();  => []
8114         colors.length(); => 0
8115
8116     @method clear
8117     @return {Ember.Array} An empty Array. 
8118   */
8119   clear: function () {
8120     var len = get(this, 'length');
8121     if (len === 0) return this;
8122     this.replace(0, len, EMPTY);
8123     return this;
8124   },
8125
8126   /**
8127     This will use the primitive replace() method to insert an object at the
8128     specified index.
8129
8130         var colors = ["red", "green", "blue"];
8131         colors.insertAt(2, "yellow"); => ["red", "green", "yellow", "blue"]
8132         colors.insertAt(5, "orange"); => Error: Index out of range
8133
8134     @method insertAt
8135     @param {Number} idx index of insert the object at.
8136     @param {Object} object object to insert
8137   */
8138   insertAt: function(idx, object) {
8139     if (idx > get(this, 'length')) throw new Error(OUT_OF_RANGE_EXCEPTION) ;
8140     this.replace(idx, 0, [object]) ;
8141     return this ;
8142   },
8143
8144   /**
8145     Remove an object at the specified index using the replace() primitive
8146     method.  You can pass either a single index, or a start and a length.
8147
8148     If you pass a start and length that is beyond the
8149     length this method will throw an Ember.OUT_OF_RANGE_EXCEPTION
8150
8151         var colors = ["red", "green", "blue", "yellow", "orange"];
8152         colors.removeAt(0); => ["green", "blue", "yellow", "orange"]
8153         colors.removeAt(2, 2); => ["green", "blue"]
8154         colors.removeAt(4, 2); => Error: Index out of range
8155
8156     @method removeAt
8157     @param {Number} start index, start of range
8158     @param {Number} len length of passing range
8159     @return {Object} receiver
8160   */
8161   removeAt: function(start, len) {
8162     if ('number' === typeof start) {
8163
8164       if ((start < 0) || (start >= get(this, 'length'))) {
8165         throw new Error(OUT_OF_RANGE_EXCEPTION);
8166       }
8167
8168       // fast case
8169       if (len === undefined) len = 1;
8170       this.replace(start, len, EMPTY);
8171     }
8172
8173     return this ;
8174   },
8175
8176   /**
8177     Push the object onto the end of the array.  Works just like push() but it
8178     is KVO-compliant.
8179
8180         var colors = ["red", "green", "blue"];
8181         colors.pushObject("black"); => ["red", "green", "blue", "black"]
8182         colors.pushObject(["yellow", "orange"]); => ["red", "green", "blue", "black", ["yellow", "orange"]]
8183
8184     @method pushObject
8185     @param {anything} obj object to push
8186   */
8187   pushObject: function(obj) {
8188     this.insertAt(get(this, 'length'), obj) ;
8189     return obj ;
8190   },
8191
8192   /**
8193     Add the objects in the passed numerable to the end of the array.  Defers
8194     notifying observers of the change until all objects are added.
8195
8196         var colors = ["red", "green", "blue"];
8197         colors.pushObjects("black"); => ["red", "green", "blue", "black"]
8198         colors.pushObjects(["yellow", "orange"]); => ["red", "green", "blue", "black", "yellow", "orange"]
8199
8200     @method pushObjects
8201     @param {Ember.Enumerable} objects the objects to add
8202     @return {Ember.Array} receiver
8203   */
8204   pushObjects: function(objects) {
8205     this.replace(get(this, 'length'), 0, objects);
8206     return this;
8207   },
8208
8209   /**
8210     Pop object from array or nil if none are left.  Works just like pop() but
8211     it is KVO-compliant.
8212
8213         var colors = ["red", "green", "blue"];
8214         colors.popObject(); => "blue"
8215         console.log(colors); => ["red", "green"]
8216
8217     @method popObject
8218     @return object
8219   */
8220   popObject: function() {
8221     var len = get(this, 'length') ;
8222     if (len === 0) return null ;
8223
8224     var ret = this.objectAt(len-1) ;
8225     this.removeAt(len-1, 1) ;
8226     return ret ;
8227   },
8228
8229   /**
8230     Shift an object from start of array or nil if none are left.  Works just
8231     like shift() but it is KVO-compliant.
8232
8233         var colors = ["red", "green", "blue"];
8234         colors.shiftObject(); => "red"
8235         console.log(colors); => ["green", "blue"]
8236
8237     @method shiftObject
8238     @return object
8239   */
8240   shiftObject: function() {
8241     if (get(this, 'length') === 0) return null ;
8242     var ret = this.objectAt(0) ;
8243     this.removeAt(0) ;
8244     return ret ;
8245   },
8246
8247   /**
8248     Unshift an object to start of array.  Works just like unshift() but it is
8249     KVO-compliant.
8250
8251         var colors = ["red", "green", "blue"];
8252         colors.unshiftObject("yellow"); => ["yellow", "red", "green", "blue"]
8253         colors.unshiftObject(["black", "white"]); => [["black", "white"], "yellow", "red", "green", "blue"]
8254
8255     @method unshiftObject
8256     @param {anything} obj object to unshift
8257   */
8258   unshiftObject: function(obj) {
8259     this.insertAt(0, obj) ;
8260     return obj ;
8261   },
8262
8263   /**
8264     Adds the named objects to the beginning of the array.  Defers notifying
8265     observers until all objects have been added.
8266
8267         var colors = ["red", "green", "blue"];
8268         colors.unshiftObjects(["black", "white"]); => ["black", "white", "red", "green", "blue"]
8269         colors.unshiftObjects("yellow"); => Type Error: 'undefined' is not a function
8270
8271     @method unshiftObjects
8272     @param {Ember.Enumerable} objects the objects to add
8273     @return {Ember.Array} receiver
8274   */
8275   unshiftObjects: function(objects) {
8276     this.replace(0, 0, objects);
8277     return this;
8278   },
8279
8280   /**
8281     Reverse objects in the array.  Works just like reverse() but it is
8282     KVO-compliant.
8283
8284     @method reverseObjects
8285     @return {Ember.Array} receiver
8286    */
8287   reverseObjects: function() {
8288     var len = get(this, 'length');
8289     if (len === 0) return this;
8290     var objects = this.toArray().reverse();
8291     this.replace(0, len, objects);
8292     return this;
8293   },
8294
8295   /**
8296     Replace all the the receiver's content with content of the argument.
8297     If argument is an empty array receiver will be cleared.
8298
8299         var colors = ["red", "green", "blue"];
8300         colors.setObjects(["black", "white"]); => ["black", "white"]
8301         colors.setObjects([]); => []
8302
8303     @method setObjects
8304     @param {Ember.Array} objects array whose content will be used for replacing
8305         the content of the receiver
8306     @return {Ember.Array} receiver with the new content
8307    */
8308   setObjects: function(objects) {
8309     if (objects.length === 0) return this.clear();
8310
8311     var len = get(this, 'length');
8312     this.replace(0, len, objects);
8313     return this;
8314   },
8315
8316   // ..........................................................
8317   // IMPLEMENT Ember.MutableEnumerable
8318   //
8319
8320   removeObject: function(obj) {
8321     var loc = get(this, 'length') || 0;
8322     while(--loc >= 0) {
8323       var curObject = this.objectAt(loc) ;
8324       if (curObject === obj) this.removeAt(loc) ;
8325     }
8326     return this ;
8327   },
8328
8329   addObject: function(obj) {
8330     if (!this.contains(obj)) this.pushObject(obj);
8331     return this ;
8332   }
8333
8334 });
8335
8336
8337 })();
8338
8339
8340
8341 (function() {
8342 /**
8343 @module ember
8344 @submodule ember-runtime
8345 */
8346
8347 var get = Ember.get, set = Ember.set, defineProperty = Ember.defineProperty;
8348
8349 /**
8350   ## Overview
8351
8352   This mixin provides properties and property observing functionality, core
8353   features of the Ember object model.
8354
8355   Properties and observers allow one object to observe changes to a
8356   property on another object. This is one of the fundamental ways that
8357   models, controllers and views communicate with each other in an Ember
8358   application.
8359
8360   Any object that has this mixin applied can be used in observer
8361   operations. That includes Ember.Object and most objects you will
8362   interact with as you write your Ember application.
8363
8364   Note that you will not generally apply this mixin to classes yourself,
8365   but you will use the features provided by this module frequently, so it
8366   is important to understand how to use it.
8367
8368   ## Using get() and set()
8369
8370   Because of Ember's support for bindings and observers, you will always
8371   access properties using the get method, and set properties using the
8372   set method. This allows the observing objects to be notified and
8373   computed properties to be handled properly.
8374
8375   More documentation about `get` and `set` are below.
8376
8377   ## Observing Property Changes
8378
8379   You typically observe property changes simply by adding the `observes`
8380   call to the end of your method declarations in classes that you write.
8381   For example:
8382
8383       Ember.Object.create({
8384         valueObserver: function() {
8385           // Executes whenever the "value" property changes
8386         }.observes('value')
8387       });
8388
8389   Although this is the most common way to add an observer, this capability
8390   is actually built into the Ember.Object class on top of two methods
8391   defined in this mixin: `addObserver` and `removeObserver`. You can use
8392   these two methods to add and remove observers yourself if you need to
8393   do so at runtime.
8394
8395   To add an observer for a property, call:
8396
8397       object.addObserver('propertyKey', targetObject, targetAction)
8398
8399   This will call the `targetAction` method on the `targetObject` to be called
8400   whenever the value of the `propertyKey` changes.
8401
8402   Note that if `propertyKey` is a computed property, the observer will be
8403   called when any of the property dependencies are changed, even if the
8404   resulting value of the computed property is unchanged. This is necessary
8405   because computed properties are not computed until `get` is called.
8406
8407   @class Observable
8408   @namespace Ember
8409   @extends Ember.Mixin
8410 */
8411 Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ {
8412
8413   // compatibility
8414   isObserverable: true,
8415
8416   /**
8417     Retrieves the value of a property from the object.
8418
8419     This method is usually similar to using object[keyName] or object.keyName,
8420     however it supports both computed properties and the unknownProperty
8421     handler.
8422
8423     Because `get` unifies the syntax for accessing all these kinds
8424     of properties, it can make many refactorings easier, such as replacing a
8425     simple property with a computed property, or vice versa.
8426
8427     ### Computed Properties
8428
8429     Computed properties are methods defined with the `property` modifier
8430     declared at the end, such as:
8431
8432           fullName: function() {
8433             return this.getEach('firstName', 'lastName').compact().join(' ');
8434           }.property('firstName', 'lastName')
8435
8436     When you call `get` on a computed property, the function will be
8437     called and the return value will be returned instead of the function
8438     itself.
8439
8440     ### Unknown Properties
8441
8442     Likewise, if you try to call `get` on a property whose value is
8443     undefined, the unknownProperty() method will be called on the object.
8444     If this method returns any value other than undefined, it will be returned
8445     instead. This allows you to implement "virtual" properties that are
8446     not defined upfront.
8447
8448     @method get
8449     @param {String} key The property to retrieve
8450     @return {Object} The property value or undefined.
8451   */
8452   get: function(keyName) {
8453     return get(this, keyName);
8454   },
8455
8456   /**
8457     To get multiple properties at once, call getProperties
8458     with a list of strings or an array:
8459
8460           record.getProperties('firstName', 'lastName', 'zipCode'); // => { firstName: 'John', lastName: 'Doe', zipCode: '10011' }
8461
8462    is equivalent to:
8463
8464           record.getProperties(['firstName', 'lastName', 'zipCode']); // => { firstName: 'John', lastName: 'Doe', zipCode: '10011' }
8465
8466     @method getProperties
8467     @param {String...|Array} list of keys to get
8468     @return {Hash}
8469   */
8470   getProperties: function() {
8471     var ret = {};
8472     var propertyNames = arguments;
8473     if (arguments.length === 1 && Ember.typeOf(arguments[0]) === 'array') {
8474       propertyNames = arguments[0];
8475     }
8476     for(var i = 0; i < propertyNames.length; i++) {
8477       ret[propertyNames[i]] = get(this, propertyNames[i]);
8478     }
8479     return ret;
8480   },
8481
8482   /**
8483     Sets the provided key or path to the value.
8484
8485     This method is generally very similar to calling object[key] = value or
8486     object.key = value, except that it provides support for computed
8487     properties, the unknownProperty() method and property observers.
8488
8489     ### Computed Properties
8490
8491     If you try to set a value on a key that has a computed property handler
8492     defined (see the get() method for an example), then set() will call
8493     that method, passing both the value and key instead of simply changing
8494     the value itself. This is useful for those times when you need to
8495     implement a property that is composed of one or more member
8496     properties.
8497
8498     ### Unknown Properties
8499
8500     If you try to set a value on a key that is undefined in the target
8501     object, then the unknownProperty() handler will be called instead. This
8502     gives you an opportunity to implement complex "virtual" properties that
8503     are not predefined on the object. If unknownProperty() returns
8504     undefined, then set() will simply set the value on the object.
8505
8506     ### Property Observers
8507
8508     In addition to changing the property, set() will also register a
8509     property change with the object. Unless you have placed this call
8510     inside of a beginPropertyChanges() and endPropertyChanges(), any "local"
8511     observers (i.e. observer methods declared on the same object), will be
8512     called immediately. Any "remote" observers (i.e. observer methods
8513     declared on another object) will be placed in a queue and called at a
8514     later time in a coalesced manner.
8515
8516     ### Chaining
8517
8518     In addition to property changes, set() returns the value of the object
8519     itself so you can do chaining like this:
8520
8521           record.set('firstName', 'Charles').set('lastName', 'Jolley');
8522
8523     @method set
8524     @param {String} key The property to set
8525     @param {Object} value The value to set or null.
8526     @return {Ember.Observable}
8527   */
8528   set: function(keyName, value) {
8529     set(this, keyName, value);
8530     return this;
8531   },
8532
8533   /**
8534     To set multiple properties at once, call setProperties
8535     with a Hash:
8536
8537           record.setProperties({ firstName: 'Charles', lastName: 'Jolley' });
8538
8539     @method setProperties
8540     @param {Hash} hash the hash of keys and values to set
8541     @return {Ember.Observable}
8542   */
8543   setProperties: function(hash) {
8544     return Ember.setProperties(this, hash);
8545   },
8546
8547   /**
8548     Begins a grouping of property changes.
8549
8550     You can use this method to group property changes so that notifications
8551     will not be sent until the changes are finished. If you plan to make a
8552     large number of changes to an object at one time, you should call this
8553     method at the beginning of the changes to begin deferring change
8554     notifications. When you are done making changes, call endPropertyChanges()
8555     to deliver the deferred change notifications and end deferring.
8556
8557     @method beginPropertyChanges
8558     @return {Ember.Observable}
8559   */
8560   beginPropertyChanges: function() {
8561     Ember.beginPropertyChanges();
8562     return this;
8563   },
8564
8565   /**
8566     Ends a grouping of property changes.
8567
8568     You can use this method to group property changes so that notifications
8569     will not be sent until the changes are finished. If you plan to make a
8570     large number of changes to an object at one time, you should call
8571     beginPropertyChanges() at the beginning of the changes to defer change
8572     notifications. When you are done making changes, call this method to
8573     deliver the deferred change notifications and end deferring.
8574
8575     @method endPropertyChanges
8576     @return {Ember.Observable}
8577   */
8578   endPropertyChanges: function() {
8579     Ember.endPropertyChanges();
8580     return this;
8581   },
8582
8583   /**
8584     Notify the observer system that a property is about to change.
8585
8586     Sometimes you need to change a value directly or indirectly without
8587     actually calling get() or set() on it. In this case, you can use this
8588     method and propertyDidChange() instead. Calling these two methods
8589     together will notify all observers that the property has potentially
8590     changed value.
8591
8592     Note that you must always call propertyWillChange and propertyDidChange as
8593     a pair. If you do not, it may get the property change groups out of order
8594     and cause notifications to be delivered more often than you would like.
8595
8596     @method propertyWillChange
8597     @param {String} key The property key that is about to change.
8598     @return {Ember.Observable}
8599   */
8600   propertyWillChange: function(keyName){
8601     Ember.propertyWillChange(this, keyName);
8602     return this;
8603   },
8604
8605   /**
8606     Notify the observer system that a property has just changed.
8607
8608     Sometimes you need to change a value directly or indirectly without
8609     actually calling get() or set() on it. In this case, you can use this
8610     method and propertyWillChange() instead. Calling these two methods
8611     together will notify all observers that the property has potentially
8612     changed value.
8613
8614     Note that you must always call propertyWillChange and propertyDidChange as
8615     a pair. If you do not, it may get the property change groups out of order
8616     and cause notifications to be delivered more often than you would like.
8617
8618     @method propertyDidChange
8619     @param {String} keyName The property key that has just changed.
8620     @return {Ember.Observable}
8621   */
8622   propertyDidChange: function(keyName) {
8623     Ember.propertyDidChange(this, keyName);
8624     return this;
8625   },
8626
8627   /**
8628     Convenience method to call `propertyWillChange` and `propertyDidChange` in
8629     succession.
8630
8631     @method notifyPropertyChange
8632     @param {String} keyName The property key to be notified about.
8633     @return {Ember.Observable}
8634   */
8635   notifyPropertyChange: function(keyName) {
8636     this.propertyWillChange(keyName);
8637     this.propertyDidChange(keyName);
8638     return this;
8639   },
8640
8641   addBeforeObserver: function(key, target, method) {
8642     Ember.addBeforeObserver(this, key, target, method);
8643   },
8644
8645   /**
8646     Adds an observer on a property.
8647
8648     This is the core method used to register an observer for a property.
8649
8650     Once you call this method, anytime the key's value is set, your observer
8651     will be notified. Note that the observers are triggered anytime the
8652     value is set, regardless of whether it has actually changed. Your
8653     observer should be prepared to handle that.
8654
8655     You can also pass an optional context parameter to this method. The
8656     context will be passed to your observer method whenever it is triggered.
8657     Note that if you add the same target/method pair on a key multiple times
8658     with different context parameters, your observer will only be called once
8659     with the last context you passed.
8660
8661     ### Observer Methods
8662
8663     Observer methods you pass should generally have the following signature if
8664     you do not pass a "context" parameter:
8665
8666           fooDidChange: function(sender, key, value, rev);
8667
8668     The sender is the object that changed. The key is the property that
8669     changes. The value property is currently reserved and unused. The rev
8670     is the last property revision of the object when it changed, which you can
8671     use to detect if the key value has really changed or not.
8672
8673     If you pass a "context" parameter, the context will be passed before the
8674     revision like so:
8675
8676           fooDidChange: function(sender, key, value, context, rev);
8677
8678     Usually you will not need the value, context or revision parameters at
8679     the end. In this case, it is common to write observer methods that take
8680     only a sender and key value as parameters or, if you aren't interested in
8681     any of these values, to write an observer that has no parameters at all.
8682
8683     @method addObserver
8684     @param {String} key The key to observer
8685     @param {Object} target The target object to invoke
8686     @param {String|Function} method The method to invoke.
8687     @return {Ember.Object} self
8688   */
8689   addObserver: function(key, target, method) {
8690     Ember.addObserver(this, key, target, method);
8691   },
8692
8693   /**
8694     Remove an observer you have previously registered on this object. Pass
8695     the same key, target, and method you passed to addObserver() and your
8696     target will no longer receive notifications.
8697
8698     @method removeObserver
8699     @param {String} key The key to observer
8700     @param {Object} target The target object to invoke
8701     @param {String|Function} method The method to invoke.
8702     @return {Ember.Observable} receiver
8703   */
8704   removeObserver: function(key, target, method) {
8705     Ember.removeObserver(this, key, target, method);
8706   },
8707
8708   /**
8709     Returns true if the object currently has observers registered for a
8710     particular key. You can use this method to potentially defer performing
8711     an expensive action until someone begins observing a particular property
8712     on the object.
8713
8714     @method hasObserverFor
8715     @param {String} key Key to check
8716     @return {Boolean}
8717   */
8718   hasObserverFor: function(key) {
8719     return Ember.hasListeners(this, key+':change');
8720   },
8721
8722   /**
8723     This method will be called when a client attempts to get the value of a
8724     property that has not been defined in one of the typical ways. Override
8725     this method to create "virtual" properties.
8726
8727     @method unknownProperty
8728     @param {String} key The name of the unknown property that was requested.
8729     @return {Object} The property value or undefined. Default is undefined.
8730   */
8731   unknownProperty: function(key) {
8732     return undefined;
8733   },
8734
8735   /**
8736     This method will be called when a client attempts to set the value of a
8737     property that has not been defined in one of the typical ways. Override
8738     this method to create "virtual" properties.
8739
8740     @method setUnknownProperty
8741     @param {String} key The name of the unknown property to be set.
8742     @param {Object} value The value the unknown property is to be set to.
8743   */
8744   setUnknownProperty: function(key, value) {
8745     defineProperty(this, key);
8746     set(this, key, value);
8747   },
8748
8749   /**
8750     @deprecated
8751     @method getPath
8752     @param {String} path The property path to retrieve
8753     @return {Object} The property value or undefined.
8754   */
8755   getPath: function(path) {
8756     Ember.deprecate("getPath is deprecated since get now supports paths");
8757     return this.get(path);
8758   },
8759
8760   /**
8761     @deprecated
8762     @method setPath
8763     @param {String} path The path to the property that will be set
8764     @param {Object} value The value to set or null.
8765     @return {Ember.Observable}
8766   */
8767   setPath: function(path, value) {
8768     Ember.deprecate("setPath is deprecated since set now supports paths");
8769     return this.set(path, value);
8770   },
8771
8772   /**
8773     Retrieves the value of a property, or a default value in the case that the property
8774     returns undefined.
8775
8776         person.getWithDefault('lastName', 'Doe');
8777
8778     @method getWithDefault
8779     @param {String} keyName The name of the property to retrieve
8780     @param {Object} defaultValue The value to return if the property value is undefined
8781     @return {Object} The property value or the defaultValue.
8782   */
8783   getWithDefault: function(keyName, defaultValue) {
8784     return Ember.getWithDefault(this, keyName, defaultValue);
8785   },
8786
8787   /**
8788     Set the value of a property to the current value plus some amount.
8789
8790         person.incrementProperty('age');
8791         team.incrementProperty('score', 2);
8792
8793     @method incrementProperty
8794     @param {String} keyName The name of the property to increment
8795     @param {Object} increment The amount to increment by. Defaults to 1
8796     @return {Object} The new property value
8797   */
8798   incrementProperty: function(keyName, increment) {
8799     if (!increment) { increment = 1; }
8800     set(this, keyName, (get(this, keyName) || 0)+increment);
8801     return get(this, keyName);
8802   },
8803
8804   /**
8805     Set the value of a property to the current value minus some amount.
8806
8807         player.decrementProperty('lives');
8808         orc.decrementProperty('health', 5);
8809
8810     @method decrementProperty
8811     @param {String} keyName The name of the property to decrement
8812     @param {Object} increment The amount to decrement by. Defaults to 1
8813     @return {Object} The new property value
8814   */
8815   decrementProperty: function(keyName, increment) {
8816     if (!increment) { increment = 1; }
8817     set(this, keyName, (get(this, keyName) || 0)-increment);
8818     return get(this, keyName);
8819   },
8820
8821   /**
8822     Set the value of a boolean property to the opposite of it's
8823     current value.
8824
8825         starship.toggleProperty('warpDriveEnaged');
8826
8827     @method toggleProperty
8828     @param {String} keyName The name of the property to toggle
8829     @return {Object} The new property value
8830   */
8831   toggleProperty: function(keyName) {
8832     set(this, keyName, !get(this, keyName));
8833     return get(this, keyName);
8834   },
8835
8836   /**
8837     Returns the cached value of a computed property, if it exists.
8838     This allows you to inspect the value of a computed property
8839     without accidentally invoking it if it is intended to be
8840     generated lazily.
8841
8842     @method cacheFor
8843     @param {String} keyName
8844     @return {Object} The cached value of the computed property, if any
8845   */
8846   cacheFor: function(keyName) {
8847     return Ember.cacheFor(this, keyName);
8848   },
8849
8850   // intended for debugging purposes
8851   observersForKey: function(keyName) {
8852     return Ember.observersFor(this, keyName);
8853   }
8854 });
8855
8856
8857 })();
8858
8859
8860
8861 (function() {
8862 /**
8863 @module ember
8864 @submodule ember-runtime
8865 */
8866
8867 var get = Ember.get, set = Ember.set;
8868
8869 /**
8870 @class TargetActionSupport
8871 @namespace Ember
8872 @extends Ember.Mixin
8873 */
8874 Ember.TargetActionSupport = Ember.Mixin.create({
8875   target: null,
8876   action: null,
8877
8878   targetObject: Ember.computed(function() {
8879     var target = get(this, 'target');
8880
8881     if (Ember.typeOf(target) === "string") {
8882       var value = get(this, target);
8883       if (value === undefined) { value = get(Ember.lookup, target); }
8884       return value;
8885     } else {
8886       return target;
8887     }
8888   }).property('target'),
8889
8890   triggerAction: function() {
8891     var action = get(this, 'action'),
8892         target = get(this, 'targetObject');
8893
8894     if (target && action) {
8895       var ret;
8896
8897       if (typeof target.send === 'function') {
8898         ret = target.send(action, this);
8899       } else {
8900         if (typeof action === 'string') {
8901           action = target[action];
8902         }
8903         ret = action.call(target, this);
8904       }
8905       if (ret !== false) ret = true;
8906
8907       return ret;
8908     } else {
8909       return false;
8910     }
8911   }
8912 });
8913
8914 })();
8915
8916
8917
8918 (function() {
8919 /**
8920 @module ember
8921 @submodule ember-runtime
8922 */
8923
8924 /**
8925   @class Evented
8926   @namespace Ember
8927   @extends Ember.Mixin
8928  */
8929 Ember.Evented = Ember.Mixin.create({
8930   on: function(name, target, method) {
8931     Ember.addListener(this, name, target, method);
8932   },
8933
8934   one: function(name, target, method) {
8935     if (!method) {
8936       method = target;
8937       target = null;
8938     }
8939
8940     var self = this;
8941     var wrapped = function() {
8942       Ember.removeListener(self, name, target, method);
8943
8944       if ('string' === typeof method) { method = this[method]; }
8945
8946       // Internally, a `null` target means that the target is
8947       // the first parameter to addListener. That means that
8948       // the `this` passed into this function is the target
8949       // determined by the event system.
8950       method.apply(this, arguments);
8951     };
8952
8953     Ember.addListener(this, name, target, wrapped, Ember.guidFor(method));
8954   },
8955
8956   trigger: function(name) {
8957     var args = [], i, l;
8958     for (i = 1, l = arguments.length; i < l; i++) {
8959       args.push(arguments[i]);
8960     }
8961     Ember.sendEvent(this, name, args);
8962   },
8963
8964   fire: function(name) {
8965     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.");
8966     this.trigger.apply(this, arguments);
8967   },
8968
8969   off: function(name, target, method) {
8970     Ember.removeListener(this, name, target, method);
8971   },
8972
8973   has: function(name) {
8974     return Ember.hasListeners(this, name);
8975   }
8976 });
8977
8978 })();
8979
8980
8981
8982 (function() {
8983 /**
8984 @module ember
8985 @submodule ember-runtime
8986 */
8987
8988 var get = Ember.get,
8989     slice = Array.prototype.slice;
8990
8991 /**
8992   @class Deferred
8993   @namespace Ember
8994   @extends Ember.Mixin
8995  */
8996 Ember.Deferred = Ember.Mixin.create({
8997
8998   /**
8999     Add handlers to be called when the Deferred object is resolved or rejected.
9000
9001     @method then
9002     @param {Function} doneCallback a callback function to be called when done
9003     @param {Function} failCallback a callback function to be called when failed
9004   */
9005   then: function(doneCallback, failCallback) {
9006     return get(this, 'promise').then(doneCallback, failCallback);
9007   },
9008
9009   /**
9010     Resolve a Deferred object and call any doneCallbacks with the given args.
9011
9012     @method resolve
9013   */
9014   resolve: function(value) {
9015     get(this, 'promise').resolve(value);
9016   },
9017
9018   /**
9019     Reject a Deferred object and call any failCallbacks with the given args.
9020
9021     @method reject
9022   */
9023   reject: function(value) {
9024     get(this, 'promise').reject(value);
9025   },
9026
9027   promise: Ember.computed(function() {
9028     return new RSVP.Promise();
9029   })
9030 });
9031
9032 })();
9033
9034
9035
9036 (function() {
9037
9038 })();
9039
9040
9041
9042 (function() {
9043 /**
9044 @module ember
9045 @submodule ember-runtime
9046 */
9047
9048
9049 // NOTE: this object should never be included directly.  Instead use Ember.
9050 // Ember.Object.  We only define this separately so that Ember.Set can depend on it
9051
9052
9053 var set = Ember.set, get = Ember.get,
9054     o_create = Ember.create,
9055     o_defineProperty = Ember.platform.defineProperty,
9056     a_slice = Array.prototype.slice,
9057     GUID_KEY = Ember.GUID_KEY,
9058     guidFor = Ember.guidFor,
9059     generateGuid = Ember.generateGuid,
9060     meta = Ember.meta,
9061     rewatch = Ember.rewatch,
9062     finishChains = Ember.finishChains,
9063     destroy = Ember.destroy,
9064     schedule = Ember.run.schedule,
9065     Mixin = Ember.Mixin,
9066     applyMixin = Mixin._apply,
9067     finishPartial = Mixin.finishPartial,
9068     reopen = Mixin.prototype.reopen,
9069     classToString = Mixin.prototype.toString;
9070
9071 var undefinedDescriptor = {
9072   configurable: true,
9073   writable: true,
9074   enumerable: false,
9075   value: undefined
9076 };
9077
9078 function makeCtor() {
9079
9080   // Note: avoid accessing any properties on the object since it makes the
9081   // method a lot faster.  This is glue code so we want it to be as fast as
9082   // possible.
9083
9084   var wasApplied = false, initMixins;
9085
9086   var Class = function() {
9087     if (!wasApplied) {
9088       Class.proto(); // prepare prototype...
9089     }
9090     o_defineProperty(this, GUID_KEY, undefinedDescriptor);
9091     o_defineProperty(this, '_super', undefinedDescriptor);
9092     var m = meta(this);
9093     m.proto = this;
9094     if (initMixins) {
9095       this.reopen.apply(this, initMixins);
9096       initMixins = null;
9097     }
9098     finishPartial(this, m);
9099     delete m.proto;
9100     finishChains(this);
9101     this.init.apply(this, arguments);
9102   };
9103
9104   Class.toString = classToString;
9105   Class.willReopen = function() {
9106     if (wasApplied) {
9107       Class.PrototypeMixin = Mixin.create(Class.PrototypeMixin);
9108     }
9109
9110     wasApplied = false;
9111   };
9112   Class._initMixins = function(args) { initMixins = args; };
9113
9114   Class.proto = function() {
9115     var superclass = Class.superclass;
9116     if (superclass) { superclass.proto(); }
9117
9118     if (!wasApplied) {
9119       wasApplied = true;
9120       Class.PrototypeMixin.applyPartial(Class.prototype);
9121       rewatch(Class.prototype);
9122     }
9123
9124     return this.prototype;
9125   };
9126
9127   return Class;
9128
9129 }
9130
9131 var CoreObject = makeCtor();
9132
9133 CoreObject.PrototypeMixin = Mixin.create({
9134
9135   reopen: function() {
9136     applyMixin(this, arguments, true);
9137     return this;
9138   },
9139
9140   isInstance: true,
9141
9142   init: function() {},
9143
9144   /**
9145     @property isDestroyed
9146     @default false
9147   */
9148   isDestroyed: false,
9149
9150   /**
9151     @property isDestroying
9152     @default false
9153   */
9154   isDestroying: false,
9155
9156   /**
9157     Destroys an object by setting the isDestroyed flag and removing its
9158     metadata, which effectively destroys observers and bindings.
9159
9160     If you try to set a property on a destroyed object, an exception will be
9161     raised.
9162
9163     Note that destruction is scheduled for the end of the run loop and does not
9164     happen immediately.
9165
9166     @method destroy
9167     @return {Ember.Object} receiver
9168   */
9169   destroy: function() {
9170     if (this.isDestroying) { return; }
9171
9172     this.isDestroying = true;
9173
9174     if (this.willDestroy) { this.willDestroy(); }
9175
9176     set(this, 'isDestroyed', true);
9177     schedule('destroy', this, this._scheduledDestroy);
9178     return this;
9179   },
9180
9181   /**
9182     @private
9183
9184     Invoked by the run loop to actually destroy the object. This is
9185     scheduled for execution by the `destroy` method.
9186
9187     @method _scheduledDestroy
9188   */
9189   _scheduledDestroy: function() {
9190     destroy(this);
9191     if (this.didDestroy) { this.didDestroy(); }
9192   },
9193
9194   bind: function(to, from) {
9195     if (!(from instanceof Ember.Binding)) { from = Ember.Binding.from(from); }
9196     from.to(to).connect(this);
9197     return from;
9198   },
9199
9200   toString: function() {
9201     return '<'+this.constructor.toString()+':'+guidFor(this)+'>';
9202   }
9203 });
9204
9205 if (Ember.config.overridePrototypeMixin) {
9206   Ember.config.overridePrototypeMixin(CoreObject.PrototypeMixin);
9207 }
9208
9209 CoreObject.__super__ = null;
9210
9211 var ClassMixin = Mixin.create({
9212
9213   ClassMixin: Ember.required(),
9214
9215   PrototypeMixin: Ember.required(),
9216
9217   isClass: true,
9218
9219   isMethod: false,
9220
9221   extend: function() {
9222     var Class = makeCtor(), proto;
9223     Class.ClassMixin = Mixin.create(this.ClassMixin);
9224     Class.PrototypeMixin = Mixin.create(this.PrototypeMixin);
9225
9226     Class.ClassMixin.ownerConstructor = Class;
9227     Class.PrototypeMixin.ownerConstructor = Class;
9228
9229     reopen.apply(Class.PrototypeMixin, arguments);
9230
9231     Class.superclass = this;
9232     Class.__super__  = this.prototype;
9233
9234     proto = Class.prototype = o_create(this.prototype);
9235     proto.constructor = Class;
9236     generateGuid(proto, 'ember');
9237     meta(proto).proto = proto; // this will disable observers on prototype
9238
9239     Class.ClassMixin.apply(Class);
9240     return Class;
9241   },
9242
9243   create: function() {
9244     var C = this;
9245     if (arguments.length>0) { this._initMixins(arguments); }
9246     return new C();
9247   },
9248
9249   reopen: function() {
9250     this.willReopen();
9251     reopen.apply(this.PrototypeMixin, arguments);
9252     return this;
9253   },
9254
9255   reopenClass: function() {
9256     reopen.apply(this.ClassMixin, arguments);
9257     applyMixin(this, arguments, false);
9258     return this;
9259   },
9260
9261   detect: function(obj) {
9262     if ('function' !== typeof obj) { return false; }
9263     while(obj) {
9264       if (obj===this) { return true; }
9265       obj = obj.superclass;
9266     }
9267     return false;
9268   },
9269
9270   detectInstance: function(obj) {
9271     return obj instanceof this;
9272   },
9273
9274   /**
9275     In some cases, you may want to annotate computed properties with additional
9276     metadata about how they function or what values they operate on. For example,
9277     computed property functions may close over variables that are then no longer
9278     available for introspection.
9279
9280     You can pass a hash of these values to a computed property like this:
9281
9282         person: function() {
9283           var personId = this.get('personId');
9284           return App.Person.create({ id: personId });
9285         }.property().meta({ type: App.Person })
9286
9287     Once you've done this, you can retrieve the values saved to the computed
9288     property from your class like this:
9289
9290         MyClass.metaForProperty('person');
9291
9292     This will return the original hash that was passed to `meta()`.
9293
9294     @method metaForProperty
9295     @param key {String} property name
9296   */
9297   metaForProperty: function(key) {
9298     var desc = meta(this.proto(), false).descs[key];
9299
9300     Ember.assert("metaForProperty() could not find a computed property with key '"+key+"'.", !!desc && desc instanceof Ember.ComputedProperty);
9301     return desc._meta || {};
9302   },
9303
9304   /**
9305     Iterate over each computed property for the class, passing its name
9306     and any associated metadata (see `metaForProperty`) to the callback.
9307
9308     @method eachComputedProperty
9309     @param {Function} callback
9310     @param {Object} binding
9311   */
9312   eachComputedProperty: function(callback, binding) {
9313     var proto = this.proto(),
9314         descs = meta(proto).descs,
9315         empty = {},
9316         property;
9317
9318     for (var name in descs) {
9319       property = descs[name];
9320
9321       if (property instanceof Ember.ComputedProperty) {
9322         callback.call(binding || this, name, property._meta || empty);
9323       }
9324     }
9325   }
9326
9327 });
9328
9329 if (Ember.config.overrideClassMixin) {
9330   Ember.config.overrideClassMixin(ClassMixin);
9331 }
9332
9333 CoreObject.ClassMixin = ClassMixin;
9334 ClassMixin.apply(CoreObject);
9335
9336 /**
9337   @class CoreObject
9338   @namespace Ember
9339 */
9340 Ember.CoreObject = CoreObject;
9341
9342
9343
9344
9345 })();
9346
9347
9348
9349 (function() {
9350 /**
9351 @module ember
9352 @submodule ember-runtime
9353 */
9354
9355 var get = Ember.get, set = Ember.set, guidFor = Ember.guidFor, none = Ember.none;
9356
9357 /**
9358   An unordered collection of objects.
9359
9360   A Set works a bit like an array except that its items are not ordered.
9361   You can create a set to efficiently test for membership for an object. You
9362   can also iterate through a set just like an array, even accessing objects
9363   by index, however there is no guarantee as to their order.
9364
9365   All Sets are observable via the Enumerable Observer API - which works
9366   on any enumerable object including both Sets and Arrays.
9367
9368   ## Creating a Set
9369
9370   You can create a set like you would most objects using
9371   `new Ember.Set()`.  Most new sets you create will be empty, but you can
9372   also initialize the set with some content by passing an array or other
9373   enumerable of objects to the constructor.
9374
9375   Finally, you can pass in an existing set and the set will be copied. You
9376   can also create a copy of a set by calling `Ember.Set#copy()`.
9377
9378       #js
9379       // creates a new empty set
9380       var foundNames = new Ember.Set();
9381
9382       // creates a set with four names in it.
9383       var names = new Ember.Set(["Charles", "Tom", "Juan", "Alex"]); // :P
9384
9385       // creates a copy of the names set.
9386       var namesCopy = new Ember.Set(names);
9387
9388       // same as above.
9389       var anotherNamesCopy = names.copy();
9390
9391   ## Adding/Removing Objects
9392
9393   You generally add or remove objects from a set using `add()` or
9394   `remove()`. You can add any type of object including primitives such as
9395   numbers, strings, and booleans.
9396
9397   Unlike arrays, objects can only exist one time in a set. If you call `add()`
9398   on a set with the same object multiple times, the object will only be added
9399   once. Likewise, calling `remove()` with the same object multiple times will
9400   remove the object the first time and have no effect on future calls until
9401   you add the object to the set again.
9402
9403   NOTE: You cannot add/remove null or undefined to a set. Any attempt to do so
9404   will be ignored.
9405
9406   In addition to add/remove you can also call `push()`/`pop()`. Push behaves
9407   just like `add()` but `pop()`, unlike `remove()` will pick an arbitrary
9408   object, remove it and return it. This is a good way to use a set as a job
9409   queue when you don't care which order the jobs are executed in.
9410
9411   ## Testing for an Object
9412
9413   To test for an object's presence in a set you simply call
9414   `Ember.Set#contains()`.
9415
9416   ## Observing changes
9417
9418   When using `Ember.Set`, you can observe the `"[]"` property to be
9419   alerted whenever the content changes.  You can also add an enumerable
9420   observer to the set to be notified of specific objects that are added and
9421   removed from the set.  See `Ember.Enumerable` for more information on
9422   enumerables.
9423
9424   This is often unhelpful. If you are filtering sets of objects, for instance,
9425   it is very inefficient to re-filter all of the items each time the set
9426   changes. It would be better if you could just adjust the filtered set based
9427   on what was changed on the original set. The same issue applies to merging
9428   sets, as well.
9429
9430   ## Other Methods
9431
9432   `Ember.Set` primary implements other mixin APIs.  For a complete reference
9433   on the methods you will use with `Ember.Set`, please consult these mixins.
9434   The most useful ones will be `Ember.Enumerable` and
9435   `Ember.MutableEnumerable` which implement most of the common iterator
9436   methods you are used to on Array.
9437
9438   Note that you can also use the `Ember.Copyable` and `Ember.Freezable`
9439   APIs on `Ember.Set` as well.  Once a set is frozen it can no longer be
9440   modified.  The benefit of this is that when you call frozenCopy() on it,
9441   Ember will avoid making copies of the set.  This allows you to write
9442   code that can know with certainty when the underlying set data will or
9443   will not be modified.
9444
9445   @class Set
9446   @namespace Ember
9447   @extends Ember.CoreObject
9448   @uses Ember.MutableEnumerable
9449   @uses Ember.Copyable
9450   @uses Ember.Freezable
9451   @since Ember 0.9
9452 */
9453 Ember.Set = Ember.CoreObject.extend(Ember.MutableEnumerable, Ember.Copyable, Ember.Freezable,
9454   /** @scope Ember.Set.prototype */ {
9455
9456   // ..........................................................
9457   // IMPLEMENT ENUMERABLE APIS
9458   //
9459
9460   /**
9461     This property will change as the number of objects in the set changes.
9462
9463     @property length
9464     @type number
9465     @default 0
9466   */
9467   length: 0,
9468
9469   /**
9470     Clears the set. This is useful if you want to reuse an existing set
9471     without having to recreate it.
9472
9473         var colors = new Ember.Set(["red", "green", "blue"]);
9474         colors.length;  => 3
9475         colors.clear();
9476         colors.length;  => 0
9477
9478     @method clear
9479     @return {Ember.Set} An empty Set
9480   */
9481   clear: function() {
9482     if (this.isFrozen) { throw new Error(Ember.FROZEN_ERROR); }
9483
9484     var len = get(this, 'length');
9485     if (len === 0) { return this; }
9486
9487     var guid;
9488
9489     this.enumerableContentWillChange(len, 0);
9490     Ember.propertyWillChange(this, 'firstObject');
9491     Ember.propertyWillChange(this, 'lastObject');
9492
9493     for (var i=0; i < len; i++){
9494       guid = guidFor(this[i]);
9495       delete this[guid];
9496       delete this[i];
9497     }
9498
9499     set(this, 'length', 0);
9500
9501     Ember.propertyDidChange(this, 'firstObject');
9502     Ember.propertyDidChange(this, 'lastObject');
9503     this.enumerableContentDidChange(len, 0);
9504
9505     return this;
9506   },
9507
9508   /**
9509     Returns true if the passed object is also an enumerable that contains the
9510     same objects as the receiver.
9511
9512         var colors = ["red", "green", "blue"],
9513             same_colors = new Ember.Set(colors);
9514         same_colors.isEqual(colors); => true
9515         same_colors.isEqual(["purple", "brown"]); => false
9516
9517     @method isEqual
9518     @param {Ember.Set} obj the other object.
9519     @return {Boolean}
9520   */
9521   isEqual: function(obj) {
9522     // fail fast
9523     if (!Ember.Enumerable.detect(obj)) return false;
9524
9525     var loc = get(this, 'length');
9526     if (get(obj, 'length') !== loc) return false;
9527
9528     while(--loc >= 0) {
9529       if (!obj.contains(this[loc])) return false;
9530     }
9531
9532     return true;
9533   },
9534
9535   /**
9536     Adds an object to the set. Only non-null objects can be added to a set
9537     and those can only be added once. If the object is already in the set or
9538     the passed value is null this method will have no effect.
9539
9540     This is an alias for `Ember.MutableEnumerable.addObject()`.
9541
9542         var colors = new Ember.Set();
9543         colors.add("blue");    => ["blue"]
9544         colors.add("blue");    => ["blue"]
9545         colors.add("red");     => ["blue", "red"]
9546         colors.add(null);      => ["blue", "red"]
9547         colors.add(undefined); => ["blue", "red"]
9548
9549     @method add
9550     @param {Object} obj The object to add.
9551     @return {Ember.Set} The set itself.
9552   */
9553   add: Ember.alias('addObject'),
9554
9555   /**
9556     Removes the object from the set if it is found.  If you pass a null value
9557     or an object that is already not in the set, this method will have no
9558     effect. This is an alias for `Ember.MutableEnumerable.removeObject()`.
9559
9560         var colors = new Ember.Set(["red", "green", "blue"]);
9561         colors.remove("red");    => ["blue", "green"]
9562         colors.remove("purple"); => ["blue", "green"]
9563         colors.remove(null);     => ["blue", "green"]
9564
9565     @method remove
9566     @param {Object} obj The object to remove
9567     @return {Ember.Set} The set itself.
9568   */
9569   remove: Ember.alias('removeObject'),
9570
9571   /**
9572     Removes the last element from the set and returns it, or null if it's empty.
9573
9574         var colors = new Ember.Set(["green", "blue"]);
9575         colors.pop(); => "blue"
9576         colors.pop(); => "green"
9577         colors.pop(); => null
9578
9579     @method pop
9580     @return {Object} The removed object from the set or null.
9581   */
9582   pop: function() {
9583     if (get(this, 'isFrozen')) throw new Error(Ember.FROZEN_ERROR);
9584     var obj = this.length > 0 ? this[this.length-1] : null;
9585     this.remove(obj);
9586     return obj;
9587   },
9588
9589   /**
9590     Inserts the given object on to the end of the set. It returns
9591     the set itself.
9592
9593     This is an alias for `Ember.MutableEnumerable.addObject()`.
9594
9595         var colors = new Ember.Set();
9596         colors.push("red");   => ["red"]
9597         colors.push("green"); => ["red", "green"]
9598         colors.push("blue");  => ["red", "green", "blue"]
9599
9600     @method push
9601     @return {Ember.Set} The set itself.
9602   */
9603   push: Ember.alias('addObject'),
9604
9605   /**
9606     Removes the last element from the set and returns it, or null if it's empty.
9607
9608     This is an alias for `Ember.Set.pop()`.
9609
9610         var colors = new Ember.Set(["green", "blue"]);
9611         colors.shift(); => "blue"
9612         colors.shift(); => "green"
9613         colors.shift(); => null
9614
9615     @method shift
9616     @return {Object} The removed object from the set or null.
9617   */
9618   shift: Ember.alias('pop'),
9619
9620   /**
9621     Inserts the given object on to the end of the set. It returns
9622     the set itself.
9623
9624     This is an alias of `Ember.Set.push()`
9625
9626         var colors = new Ember.Set();
9627         colors.unshift("red");   => ["red"]
9628         colors.unshift("green"); => ["red", "green"]
9629         colors.unshift("blue");  => ["red", "green", "blue"]
9630
9631     @method unshift
9632     @return {Ember.Set} The set itself.
9633   */
9634   unshift: Ember.alias('push'),
9635
9636   /**
9637     Adds each object in the passed enumerable to the set.
9638
9639     This is an alias of `Ember.MutableEnumerable.addObjects()`
9640
9641         var colors = new Ember.Set();
9642         colors.addEach(["red", "green", "blue"]); => ["red", "green", "blue"]
9643
9644     @method addEach
9645     @param {Ember.Enumerable} objects the objects to add.
9646     @return {Ember.Set} The set itself.
9647   */
9648   addEach: Ember.alias('addObjects'),
9649
9650   /**
9651     Removes each object in the passed enumerable to the set.
9652
9653     This is an alias of `Ember.MutableEnumerable.removeObjects()`
9654
9655         var colors = new Ember.Set(["red", "green", "blue"]);
9656         colors.removeEach(["red", "blue"]); => ["green"]
9657
9658     @method removeEach
9659     @param {Ember.Enumerable} objects the objects to remove.
9660     @return {Ember.Set} The set itself.
9661   */
9662   removeEach: Ember.alias('removeObjects'),
9663
9664   // ..........................................................
9665   // PRIVATE ENUMERABLE SUPPORT
9666   //
9667
9668   init: function(items) {
9669     this._super();
9670     if (items) this.addObjects(items);
9671   },
9672
9673   // implement Ember.Enumerable
9674   nextObject: function(idx) {
9675     return this[idx];
9676   },
9677
9678   // more optimized version
9679   firstObject: Ember.computed(function() {
9680     return this.length > 0 ? this[0] : undefined;
9681   }).property(),
9682
9683   // more optimized version
9684   lastObject: Ember.computed(function() {
9685     return this.length > 0 ? this[this.length-1] : undefined;
9686   }).property(),
9687
9688   // implements Ember.MutableEnumerable
9689   addObject: function(obj) {
9690     if (get(this, 'isFrozen')) throw new Error(Ember.FROZEN_ERROR);
9691     if (none(obj)) return this; // nothing to do
9692
9693     var guid = guidFor(obj),
9694         idx  = this[guid],
9695         len  = get(this, 'length'),
9696         added ;
9697
9698     if (idx>=0 && idx<len && (this[idx] === obj)) return this; // added
9699
9700     added = [obj];
9701
9702     this.enumerableContentWillChange(null, added);
9703     Ember.propertyWillChange(this, 'lastObject');
9704
9705     len = get(this, 'length');
9706     this[guid] = len;
9707     this[len] = obj;
9708     set(this, 'length', len+1);
9709
9710     Ember.propertyDidChange(this, 'lastObject');
9711     this.enumerableContentDidChange(null, added);
9712
9713     return this;
9714   },
9715
9716   // implements Ember.MutableEnumerable
9717   removeObject: function(obj) {
9718     if (get(this, 'isFrozen')) throw new Error(Ember.FROZEN_ERROR);
9719     if (none(obj)) return this; // nothing to do
9720
9721     var guid = guidFor(obj),
9722         idx  = this[guid],
9723         len = get(this, 'length'),
9724         isFirst = idx === 0,
9725         isLast = idx === len-1,
9726         last, removed;
9727
9728
9729     if (idx>=0 && idx<len && (this[idx] === obj)) {
9730       removed = [obj];
9731
9732       this.enumerableContentWillChange(removed, null);
9733       if (isFirst) { Ember.propertyWillChange(this, 'firstObject'); }
9734       if (isLast)  { Ember.propertyWillChange(this, 'lastObject'); }
9735
9736       // swap items - basically move the item to the end so it can be removed
9737       if (idx < len-1) {
9738         last = this[len-1];
9739         this[idx] = last;
9740         this[guidFor(last)] = idx;
9741       }
9742
9743       delete this[guid];
9744       delete this[len-1];
9745       set(this, 'length', len-1);
9746
9747       if (isFirst) { Ember.propertyDidChange(this, 'firstObject'); }
9748       if (isLast)  { Ember.propertyDidChange(this, 'lastObject'); }
9749       this.enumerableContentDidChange(removed, null);
9750     }
9751
9752     return this;
9753   },
9754
9755   // optimized version
9756   contains: function(obj) {
9757     return this[guidFor(obj)]>=0;
9758   },
9759
9760   copy: function() {
9761     var C = this.constructor, ret = new C(), loc = get(this, 'length');
9762     set(ret, 'length', loc);
9763     while(--loc>=0) {
9764       ret[loc] = this[loc];
9765       ret[guidFor(this[loc])] = loc;
9766     }
9767     return ret;
9768   },
9769
9770   toString: function() {
9771     var len = this.length, idx, array = [];
9772     for(idx = 0; idx < len; idx++) {
9773       array[idx] = this[idx];
9774     }
9775     return "Ember.Set<%@>".fmt(array.join(','));
9776   }
9777
9778 });
9779
9780 })();
9781
9782
9783
9784 (function() {
9785 /**
9786 @module ember
9787 @submodule ember-runtime
9788 */
9789
9790 /**
9791   `Ember.Object` is the main base class for all Ember objects. It is a subclass
9792   of `Ember.CoreObject` with the `Ember.Observable` mixin applied. For details,
9793   see the documentation for each of these.
9794
9795   @class Object
9796   @namespace Ember
9797   @extends Ember.CoreObject
9798   @uses Ember.Observable
9799 */
9800 Ember.Object = Ember.CoreObject.extend(Ember.Observable);
9801
9802 })();
9803
9804
9805
9806 (function() {
9807 /**
9808 @module ember
9809 @submodule ember-runtime
9810 */
9811
9812 var indexOf = Ember.ArrayPolyfills.indexOf;
9813
9814 /**
9815   A Namespace is an object usually used to contain other objects or methods
9816   such as an application or framework.  Create a namespace anytime you want
9817   to define one of these new containers.
9818
9819   # Example Usage
9820
9821       MyFramework = Ember.Namespace.create({
9822         VERSION: '1.0.0'
9823       });
9824
9825   @class Namespace
9826   @namespace Ember
9827   @extends Ember.Object
9828 */
9829 Ember.Namespace = Ember.Object.extend({
9830   isNamespace: true,
9831
9832   init: function() {
9833     Ember.Namespace.NAMESPACES.push(this);
9834     Ember.Namespace.PROCESSED = false;
9835   },
9836
9837   toString: function() {
9838     Ember.identifyNamespaces();
9839     return this[Ember.GUID_KEY+'_name'];
9840   },
9841
9842   destroy: function() {
9843     var namespaces = Ember.Namespace.NAMESPACES;
9844     Ember.lookup[this.toString()] = undefined;
9845     namespaces.splice(indexOf.call(namespaces, this), 1);
9846     this._super();
9847   }
9848 });
9849
9850 Ember.Namespace.NAMESPACES = [Ember];
9851 Ember.Namespace.PROCESSED = false;
9852
9853 })();
9854
9855
9856
9857 (function() {
9858 /**
9859 @module ember
9860 @submodule ember-runtime
9861 */
9862
9863 /**
9864   Defines a namespace that will contain an executable application.  This is
9865   very similar to a normal namespace except that it is expected to include at
9866   least a 'ready' function which can be run to initialize the application.
9867
9868   Currently Ember.Application is very similar to Ember.Namespace.  However, this
9869   class may be augmented by additional frameworks so it is important to use
9870   this instance when building new applications.
9871
9872   # Example Usage
9873
9874       MyApp = Ember.Application.create({
9875         VERSION: '1.0.0',
9876         store: Ember.Store.create().from(Ember.fixtures)
9877       });
9878
9879       MyApp.ready = function() {
9880         //..init code goes here...
9881       }
9882
9883   @class Application
9884   @namespace Ember
9885   @extends Ember.Namespace
9886 */
9887 Ember.Application = Ember.Namespace.extend();
9888
9889
9890 })();
9891
9892
9893
9894 (function() {
9895 /**
9896 @module ember
9897 @submodule ember-runtime
9898 */
9899
9900
9901 var get = Ember.get, set = Ember.set;
9902
9903 /**
9904   An ArrayProxy wraps any other object that implements Ember.Array and/or
9905   Ember.MutableArray, forwarding all requests. This makes it very useful for
9906   a number of binding use cases or other cases where being able to swap
9907   out the underlying array is useful.
9908
9909   A simple example of usage:
9910
9911       var pets = ['dog', 'cat', 'fish'];
9912       var ap = Ember.ArrayProxy.create({ content: Ember.A(pets) });
9913       ap.get('firstObject'); // => 'dog'
9914       ap.set('content', ['amoeba', 'paramecium']);
9915       ap.get('firstObject'); // => 'amoeba'
9916
9917   This class can also be useful as a layer to transform the contents of
9918   an array, as they are accessed. This can be done by overriding
9919   `objectAtContent`:
9920
9921       var pets = ['dog', 'cat', 'fish'];
9922       var ap = Ember.ArrayProxy.create({
9923           content: Ember.A(pets),
9924           objectAtContent: function(idx) {
9925               return this.get('content').objectAt(idx).toUpperCase();
9926           }
9927       });
9928       ap.get('firstObject'); // => 'DOG'
9929
9930
9931   @class ArrayProxy
9932   @namespace Ember
9933   @extends Ember.Object
9934   @uses Ember.MutableArray
9935 */
9936 Ember.ArrayProxy = Ember.Object.extend(Ember.MutableArray,
9937 /** @scope Ember.ArrayProxy.prototype */ {
9938
9939   /**
9940     The content array.  Must be an object that implements Ember.Array and/or
9941     Ember.MutableArray.
9942
9943     @property content
9944     @type Ember.Array
9945   */
9946   content: null,
9947
9948   /**
9949    The array that the proxy pretends to be. In the default `ArrayProxy`
9950    implementation, this and `content` are the same. Subclasses of `ArrayProxy`
9951    can override this property to provide things like sorting and filtering.
9952    
9953    @property arrangedContent
9954   */
9955   arrangedContent: Ember.computed('content', function() {
9956     return get(this, 'content');
9957   }),
9958
9959   /**
9960     Should actually retrieve the object at the specified index from the
9961     content. You can override this method in subclasses to transform the
9962     content item to something new.
9963
9964     This method will only be called if content is non-null.
9965
9966     @method objectAtContent
9967     @param {Number} idx The index to retrieve.
9968     @return {Object} the value or undefined if none found
9969   */
9970   objectAtContent: function(idx) {
9971     return get(this, 'arrangedContent').objectAt(idx);
9972   },
9973
9974   /**
9975     Should actually replace the specified objects on the content array.
9976     You can override this method in subclasses to transform the content item
9977     into something new.
9978
9979     This method will only be called if content is non-null.
9980
9981     @method replaceContent
9982     @param {Number} idx The starting index
9983     @param {Number} amt The number of items to remove from the content.
9984     @param {Array} objects Optional array of objects to insert or null if no objects.
9985     @return {void}
9986   */
9987   replaceContent: function(idx, amt, objects) {
9988     get(this, 'arrangedContent').replace(idx, amt, objects);
9989   },
9990
9991   /**
9992     @private
9993
9994     Invoked when the content property is about to change. Notifies observers that the
9995     entire array content will change.
9996
9997     @method _contentWillChange
9998   */
9999   _contentWillChange: Ember.beforeObserver(function() {
10000     this._teardownContent();
10001   }, 'content'),
10002
10003   _teardownContent: function() {
10004     var content = get(this, 'content');
10005
10006     if (content) {
10007       content.removeArrayObserver(this, {
10008         willChange: 'contentArrayWillChange',
10009         didChange: 'contentArrayDidChange'
10010       });
10011     }
10012   },
10013
10014   contentArrayWillChange: Ember.K,
10015   contentArrayDidChange: Ember.K,
10016
10017   /**
10018     @private
10019
10020     Invoked when the content property changes.  Notifies observers that the
10021     entire array content has changed.
10022
10023     @method _contentDidChange
10024   */
10025   _contentDidChange: Ember.observer(function() {
10026     var content = get(this, 'content');
10027
10028     Ember.assert("Can't set ArrayProxy's content to itself", content !== this);
10029
10030     this._setupContent();
10031   }, 'content'),
10032
10033   _setupContent: function() {
10034     var content = get(this, 'content');
10035
10036     if (content) {
10037       content.addArrayObserver(this, {
10038         willChange: 'contentArrayWillChange',
10039         didChange: 'contentArrayDidChange'
10040       });
10041     }
10042   },
10043
10044   _arrangedContentWillChange: Ember.beforeObserver(function() {
10045     var arrangedContent = get(this, 'arrangedContent'),
10046         len = arrangedContent ? get(arrangedContent, 'length') : 0;
10047
10048     this.arrangedContentArrayWillChange(this, 0, len, undefined);
10049     this.arrangedContentWillChange(this);
10050
10051     this._teardownArrangedContent(arrangedContent);
10052   }, 'arrangedContent'),
10053
10054   _arrangedContentDidChange: Ember.observer(function() {
10055     var arrangedContent = get(this, 'arrangedContent'),
10056         len = arrangedContent ? get(arrangedContent, 'length') : 0;
10057
10058     Ember.assert("Can't set ArrayProxy's content to itself", arrangedContent !== this);
10059
10060     this._setupArrangedContent();
10061
10062     this.arrangedContentDidChange(this);
10063     this.arrangedContentArrayDidChange(this, 0, undefined, len);
10064   }, 'arrangedContent'),
10065
10066   _setupArrangedContent: function() {
10067     var arrangedContent = get(this, 'arrangedContent');
10068
10069     if (arrangedContent) {
10070       arrangedContent.addArrayObserver(this, {
10071         willChange: 'arrangedContentArrayWillChange',
10072         didChange: 'arrangedContentArrayDidChange'
10073       });
10074     }
10075   },
10076
10077   _teardownArrangedContent: function() {
10078     var arrangedContent = get(this, 'arrangedContent');
10079
10080     if (arrangedContent) {
10081       arrangedContent.removeArrayObserver(this, {
10082         willChange: 'arrangedContentArrayWillChange',
10083         didChange: 'arrangedContentArrayDidChange'
10084       });
10085     }
10086   },
10087
10088   arrangedContentWillChange: Ember.K,
10089   arrangedContentDidChange: Ember.K,
10090
10091   objectAt: function(idx) {
10092     return get(this, 'content') && this.objectAtContent(idx);
10093   },
10094
10095   length: Ember.computed(function() {
10096     var arrangedContent = get(this, 'arrangedContent');
10097     return arrangedContent ? get(arrangedContent, 'length') : 0;
10098     // No dependencies since Enumerable notifies length of change
10099   }).property(),
10100
10101   replace: function(idx, amt, objects) {
10102     Ember.assert('The content property of '+ this.constructor + ' should be set before modifying it', this.get('content'));
10103     if (get(this, 'content')) this.replaceContent(idx, amt, objects);
10104     return this;
10105   },
10106
10107   arrangedContentArrayWillChange: function(item, idx, removedCnt, addedCnt) {
10108     this.arrayContentWillChange(idx, removedCnt, addedCnt);
10109   },
10110
10111   arrangedContentArrayDidChange: function(item, idx, removedCnt, addedCnt) {
10112     this.arrayContentDidChange(idx, removedCnt, addedCnt);
10113   },
10114
10115   init: function() {
10116     this._super();
10117     this._setupContent();
10118     this._setupArrangedContent();
10119   },
10120
10121   willDestroy: function() {
10122     this._teardownArrangedContent();
10123     this._teardownContent();
10124   }
10125 });
10126
10127
10128 })();
10129
10130
10131
10132 (function() {
10133 /**
10134 @module ember
10135 @submodule ember-runtime
10136 */
10137
10138 var get = Ember.get,
10139     set = Ember.set,
10140     fmt = Ember.String.fmt,
10141     addBeforeObserver = Ember.addBeforeObserver,
10142     addObserver = Ember.addObserver,
10143     removeBeforeObserver = Ember.removeBeforeObserver,
10144     removeObserver = Ember.removeObserver,
10145     propertyWillChange = Ember.propertyWillChange,
10146     propertyDidChange = Ember.propertyDidChange;
10147
10148 function contentPropertyWillChange(content, contentKey) {
10149   var key = contentKey.slice(8); // remove "content."
10150   if (key in this) { return; }  // if shadowed in proxy
10151   propertyWillChange(this, key);
10152 }
10153
10154 function contentPropertyDidChange(content, contentKey) {
10155   var key = contentKey.slice(8); // remove "content."
10156   if (key in this) { return; } // if shadowed in proxy
10157   propertyDidChange(this, key);
10158 }
10159
10160 /**
10161   `Ember.ObjectProxy` forwards all properties not defined by the proxy itself
10162   to a proxied `content` object.
10163
10164       object = Ember.Object.create({
10165         name: 'Foo'
10166       });
10167       proxy = Ember.ObjectProxy.create({
10168         content: object
10169       });
10170
10171       // Access and change existing properties
10172       proxy.get('name') // => 'Foo'
10173       proxy.set('name', 'Bar');
10174       object.get('name') // => 'Bar'
10175
10176       // Create new 'description' property on `object`
10177       proxy.set('description', 'Foo is a whizboo baz');
10178       object.get('description') // => 'Foo is a whizboo baz'
10179
10180   While `content` is unset, setting a property to be delegated will throw an Error.
10181
10182       proxy = Ember.ObjectProxy.create({
10183         content: null,
10184         flag: null
10185       });
10186       proxy.set('flag', true);
10187       proxy.get('flag'); // => true
10188       proxy.get('foo'); // => undefined
10189       proxy.set('foo', 'data'); // throws Error
10190
10191   Delegated properties can be bound to and will change when content is updated.
10192
10193   Computed properties on the proxy itself can depend on delegated properties.
10194
10195       ProxyWithComputedProperty = Ember.ObjectProxy.extend({
10196         fullName: function () {
10197           var firstName = this.get('firstName'),
10198               lastName = this.get('lastName');
10199           if (firstName && lastName) {
10200             return firstName + ' ' + lastName;
10201           }
10202           return firstName || lastName;
10203         }.property('firstName', 'lastName')
10204       });
10205       proxy = ProxyWithComputedProperty.create();
10206       proxy.get('fullName'); => undefined
10207       proxy.set('content', {
10208         firstName: 'Tom', lastName: 'Dale'
10209       }); // triggers property change for fullName on proxy
10210       proxy.get('fullName'); => 'Tom Dale'
10211
10212   @class ObjectProxy
10213   @namespace Ember
10214   @extends Ember.Object
10215 */
10216 Ember.ObjectProxy = Ember.Object.extend(
10217 /** @scope Ember.ObjectProxy.prototype */ {
10218   /**
10219     The object whose properties will be forwarded.
10220
10221     @property content
10222     @type Ember.Object
10223     @default null
10224   */
10225   content: null,
10226   _contentDidChange: Ember.observer(function() {
10227     Ember.assert("Can't set ObjectProxy's content to itself", this.get('content') !== this);
10228   }, 'content'),
10229
10230   willWatchProperty: function (key) {
10231     var contentKey = 'content.' + key;
10232     addBeforeObserver(this, contentKey, null, contentPropertyWillChange);
10233     addObserver(this, contentKey, null, contentPropertyDidChange);
10234   },
10235
10236   didUnwatchProperty: function (key) {
10237     var contentKey = 'content.' + key;
10238     removeBeforeObserver(this, contentKey, null, contentPropertyWillChange);
10239     removeObserver(this, contentKey, null, contentPropertyDidChange);
10240   },
10241
10242   unknownProperty: function (key) {
10243     var content = get(this, 'content');
10244     if (content) {
10245       return get(content, key);
10246     }
10247   },
10248
10249   setUnknownProperty: function (key, value) {
10250     var content = get(this, 'content');
10251     Ember.assert(fmt("Cannot delegate set('%@', %@) to the 'content' property of object proxy %@: its 'content' is undefined.", [key, value, this]), content);
10252     return set(content, key, value);
10253   }
10254 });
10255
10256 })();
10257
10258
10259
10260 (function() {
10261 /**
10262 @module ember
10263 @submodule ember-runtime
10264 */
10265
10266
10267 var set = Ember.set, get = Ember.get, guidFor = Ember.guidFor;
10268 var forEach = Ember.EnumerableUtils.forEach;
10269
10270 var EachArray = Ember.Object.extend(Ember.Array, {
10271
10272   init: function(content, keyName, owner) {
10273     this._super();
10274     this._keyName = keyName;
10275     this._owner   = owner;
10276     this._content = content;
10277   },
10278
10279   objectAt: function(idx) {
10280     var item = this._content.objectAt(idx);
10281     return item && get(item, this._keyName);
10282   },
10283
10284   length: Ember.computed(function() {
10285     var content = this._content;
10286     return content ? get(content, 'length') : 0;
10287   }).property()
10288
10289 });
10290
10291 var IS_OBSERVER = /^.+:(before|change)$/;
10292
10293 function addObserverForContentKey(content, keyName, proxy, idx, loc) {
10294   var objects = proxy._objects, guid;
10295   if (!objects) objects = proxy._objects = {};
10296
10297   while(--loc>=idx) {
10298     var item = content.objectAt(loc);
10299     if (item) {
10300       Ember.addBeforeObserver(item, keyName, proxy, 'contentKeyWillChange');
10301       Ember.addObserver(item, keyName, proxy, 'contentKeyDidChange');
10302
10303       // keep track of the indicies each item was found at so we can map
10304       // it back when the obj changes.
10305       guid = guidFor(item);
10306       if (!objects[guid]) objects[guid] = [];
10307       objects[guid].push(loc);
10308     }
10309   }
10310 }
10311
10312 function removeObserverForContentKey(content, keyName, proxy, idx, loc) {
10313   var objects = proxy._objects;
10314   if (!objects) objects = proxy._objects = {};
10315   var indicies, guid;
10316
10317   while(--loc>=idx) {
10318     var item = content.objectAt(loc);
10319     if (item) {
10320       Ember.removeBeforeObserver(item, keyName, proxy, 'contentKeyWillChange');
10321       Ember.removeObserver(item, keyName, proxy, 'contentKeyDidChange');
10322
10323       guid = guidFor(item);
10324       indicies = objects[guid];
10325       indicies[indicies.indexOf(loc)] = null;
10326     }
10327   }
10328 }
10329
10330 /**
10331   This is the object instance returned when you get the @each property on an
10332   array.  It uses the unknownProperty handler to automatically create
10333   EachArray instances for property names.
10334
10335   @private
10336   @class EachProxy
10337   @namespace Ember
10338   @extends Ember.Object
10339 */
10340 Ember.EachProxy = Ember.Object.extend({
10341
10342   init: function(content) {
10343     this._super();
10344     this._content = content;
10345     content.addArrayObserver(this);
10346
10347     // in case someone is already observing some keys make sure they are
10348     // added
10349     forEach(Ember.watchedEvents(this), function(eventName) {
10350       this.didAddListener(eventName);
10351     }, this);
10352   },
10353
10354   /**
10355     You can directly access mapped properties by simply requesting them.
10356     The unknownProperty handler will generate an EachArray of each item.
10357
10358     @method unknownProperty
10359     @param keyName {String}
10360     @param value {anything}
10361   */
10362   unknownProperty: function(keyName, value) {
10363     var ret;
10364     ret = new EachArray(this._content, keyName, this);
10365     Ember.defineProperty(this, keyName, null, ret);
10366     this.beginObservingContentKey(keyName);
10367     return ret;
10368   },
10369
10370   // ..........................................................
10371   // ARRAY CHANGES
10372   // Invokes whenever the content array itself changes.
10373
10374   arrayWillChange: function(content, idx, removedCnt, addedCnt) {
10375     var keys = this._keys, key, array, lim;
10376
10377     lim = removedCnt>0 ? idx+removedCnt : -1;
10378     Ember.beginPropertyChanges(this);
10379
10380     for(key in keys) {
10381       if (!keys.hasOwnProperty(key)) { continue; }
10382
10383       if (lim>0) removeObserverForContentKey(content, key, this, idx, lim);
10384
10385       Ember.propertyWillChange(this, key);
10386     }
10387
10388     Ember.propertyWillChange(this._content, '@each');
10389     Ember.endPropertyChanges(this);
10390   },
10391
10392   arrayDidChange: function(content, idx, removedCnt, addedCnt) {
10393     var keys = this._keys, key, array, lim;
10394
10395     lim = addedCnt>0 ? idx+addedCnt : -1;
10396     Ember.beginPropertyChanges(this);
10397
10398     for(key in keys) {
10399       if (!keys.hasOwnProperty(key)) { continue; }
10400
10401       if (lim>0) addObserverForContentKey(content, key, this, idx, lim);
10402
10403       Ember.propertyDidChange(this, key);
10404     }
10405
10406     Ember.propertyDidChange(this._content, '@each');
10407     Ember.endPropertyChanges(this);
10408   },
10409
10410   // ..........................................................
10411   // LISTEN FOR NEW OBSERVERS AND OTHER EVENT LISTENERS
10412   // Start monitoring keys based on who is listening...
10413
10414   didAddListener: function(eventName) {
10415     if (IS_OBSERVER.test(eventName)) {
10416       this.beginObservingContentKey(eventName.slice(0, -7));
10417     }
10418   },
10419
10420   didRemoveListener: function(eventName) {
10421     if (IS_OBSERVER.test(eventName)) {
10422       this.stopObservingContentKey(eventName.slice(0, -7));
10423     }
10424   },
10425
10426   // ..........................................................
10427   // CONTENT KEY OBSERVING
10428   // Actual watch keys on the source content.
10429
10430   beginObservingContentKey: function(keyName) {
10431     var keys = this._keys;
10432     if (!keys) keys = this._keys = {};
10433     if (!keys[keyName]) {
10434       keys[keyName] = 1;
10435       var content = this._content,
10436           len = get(content, 'length');
10437       addObserverForContentKey(content, keyName, this, 0, len);
10438     } else {
10439       keys[keyName]++;
10440     }
10441   },
10442
10443   stopObservingContentKey: function(keyName) {
10444     var keys = this._keys;
10445     if (keys && (keys[keyName]>0) && (--keys[keyName]<=0)) {
10446       var content = this._content,
10447           len     = get(content, 'length');
10448       removeObserverForContentKey(content, keyName, this, 0, len);
10449     }
10450   },
10451
10452   contentKeyWillChange: function(obj, keyName) {
10453     Ember.propertyWillChange(this, keyName);
10454   },
10455
10456   contentKeyDidChange: function(obj, keyName) {
10457     Ember.propertyDidChange(this, keyName);
10458   }
10459
10460 });
10461
10462
10463
10464 })();
10465
10466
10467
10468 (function() {
10469 /**
10470 @module ember
10471 @submodule ember-runtime
10472 */
10473
10474
10475 var get = Ember.get, set = Ember.set;
10476
10477 // Add Ember.Array to Array.prototype.  Remove methods with native
10478 // implementations and supply some more optimized versions of generic methods
10479 // because they are so common.
10480 var NativeArray = Ember.Mixin.create(Ember.MutableArray, Ember.Observable, Ember.Copyable, {
10481
10482   // because length is a built-in property we need to know to just get the
10483   // original property.
10484   get: function(key) {
10485     if (key==='length') return this.length;
10486     else if ('number' === typeof key) return this[key];
10487     else return this._super(key);
10488   },
10489
10490   objectAt: function(idx) {
10491     return this[idx];
10492   },
10493
10494   // primitive for array support.
10495   replace: function(idx, amt, objects) {
10496
10497     if (this.isFrozen) throw Ember.FROZEN_ERROR ;
10498
10499     // if we replaced exactly the same number of items, then pass only the
10500     // replaced range.  Otherwise, pass the full remaining array length
10501     // since everything has shifted
10502     var len = objects ? get(objects, 'length') : 0;
10503     this.arrayContentWillChange(idx, amt, len);
10504
10505     if (!objects || objects.length === 0) {
10506       this.splice(idx, amt) ;
10507     } else {
10508       var args = [idx, amt].concat(objects) ;
10509       this.splice.apply(this,args) ;
10510     }
10511
10512     this.arrayContentDidChange(idx, amt, len);
10513     return this ;
10514   },
10515
10516   // If you ask for an unknown property, then try to collect the value
10517   // from member items.
10518   unknownProperty: function(key, value) {
10519     var ret;// = this.reducedProperty(key, value) ;
10520     if ((value !== undefined) && ret === undefined) {
10521       ret = this[key] = value;
10522     }
10523     return ret ;
10524   },
10525
10526   // If browser did not implement indexOf natively, then override with
10527   // specialized version
10528   indexOf: function(object, startAt) {
10529     var idx, len = this.length;
10530
10531     if (startAt === undefined) startAt = 0;
10532     else startAt = (startAt < 0) ? Math.ceil(startAt) : Math.floor(startAt);
10533     if (startAt < 0) startAt += len;
10534
10535     for(idx=startAt;idx<len;idx++) {
10536       if (this[idx] === object) return idx ;
10537     }
10538     return -1;
10539   },
10540
10541   lastIndexOf: function(object, startAt) {
10542     var idx, len = this.length;
10543
10544     if (startAt === undefined) startAt = len-1;
10545     else startAt = (startAt < 0) ? Math.ceil(startAt) : Math.floor(startAt);
10546     if (startAt < 0) startAt += len;
10547
10548     for(idx=startAt;idx>=0;idx--) {
10549       if (this[idx] === object) return idx ;
10550     }
10551     return -1;
10552   },
10553
10554   copy: function() {
10555     return this.slice();
10556   }
10557 });
10558
10559 // Remove any methods implemented natively so we don't override them
10560 var ignore = ['length'];
10561 Ember.EnumerableUtils.forEach(NativeArray.keys(), function(methodName) {
10562   if (Array.prototype[methodName]) ignore.push(methodName);
10563 });
10564
10565 if (ignore.length>0) {
10566   NativeArray = NativeArray.without.apply(NativeArray, ignore);
10567 }
10568
10569 /**
10570   The NativeArray mixin contains the properties needed to to make the native
10571   Array support Ember.MutableArray and all of its dependent APIs.  Unless you
10572   have Ember.EXTEND_PROTOTYPES or Ember.EXTEND_PROTOTYPES.Array set to false, this
10573   will be applied automatically. Otherwise you can apply the mixin at anytime by
10574   calling `Ember.NativeArray.activate`.
10575
10576   @class NativeArray
10577   @namespace Ember
10578   @extends Ember.Mixin
10579   @uses Ember.MutableArray
10580   @uses Ember.MutableEnumerable
10581   @uses Ember.Copyable
10582   @uses Ember.Freezable
10583 */
10584 Ember.NativeArray = NativeArray;
10585
10586 /**
10587   Creates an Ember.NativeArray from an Array like object.
10588   Does not modify the original object.
10589
10590   @method A
10591   @for Ember
10592   @return {Ember.NativeArray}
10593 */
10594 Ember.A = function(arr){
10595   if (arr === undefined) { arr = []; }
10596   return Ember.NativeArray.apply(arr);
10597 };
10598
10599 /**
10600   Activates the mixin on the Array.prototype if not already applied.  Calling
10601   this method more than once is safe.
10602
10603   @method activate
10604   @for Ember.NativeArray
10605   @static
10606   @return {void}
10607 */
10608 Ember.NativeArray.activate = function() {
10609   NativeArray.apply(Array.prototype);
10610
10611   Ember.A = function(arr) { return arr || []; };
10612 };
10613
10614 if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Array) {
10615   Ember.NativeArray.activate();
10616 }
10617
10618
10619 })();
10620
10621
10622
10623 (function() {
10624 /**
10625 @module ember
10626 @submodule ember-runtime
10627 */
10628
10629 var get = Ember.get, set = Ember.set;
10630
10631 Ember._PromiseChain = Ember.Object.extend({
10632   promises: null,
10633   failureCallback: Ember.K,
10634   successCallback: Ember.K,
10635   abortCallback: Ember.K,
10636   promiseSuccessCallback: Ember.K,
10637
10638   runNextPromise: function() {
10639     if (get(this, 'isDestroyed')) { return; }
10640
10641     var item = get(this, 'promises').shiftObject();
10642     if (item) {
10643       var promise = get(item, 'promise') || item;
10644       Ember.assert("Cannot find promise to invoke", Ember.canInvoke(promise, 'then'));
10645
10646       var self = this;
10647
10648       var successCallback = function() {
10649         self.promiseSuccessCallback.call(this, item, arguments);
10650         self.runNextPromise();
10651       };
10652
10653       var failureCallback = get(self, 'failureCallback');
10654
10655       promise.then(successCallback, failureCallback);
10656      } else {
10657       this.successCallback();
10658     }
10659   },
10660
10661   start: function() {
10662     this.runNextPromise();
10663     return this;
10664   },
10665
10666   abort: function() {
10667     this.abortCallback();
10668     this.destroy();
10669   },
10670
10671   init: function() {
10672     set(this, 'promises', Ember.A(get(this, 'promises')));
10673     this._super();
10674   }
10675 });
10676
10677
10678 })();
10679
10680
10681
10682 (function() {
10683 /**
10684 @module ember
10685 @submodule ember-runtime
10686 */
10687
10688 var loadHooks = {};
10689 var loaded = {};
10690
10691 /**
10692 @method onLoad
10693 @for Ember
10694 @param name {String} name of hook
10695 @param callback {Function} callback to be called
10696 */
10697 Ember.onLoad = function(name, callback) {
10698   var object;
10699
10700   loadHooks[name] = loadHooks[name] || Ember.A();
10701   loadHooks[name].pushObject(callback);
10702
10703   if (object = loaded[name]) {
10704     callback(object);
10705   }
10706 };
10707
10708 /**
10709 @method runLoadHooks
10710 @for Ember
10711 @param name {String} name of hook
10712 @param object {Object} object to pass to callbacks
10713 */
10714 Ember.runLoadHooks = function(name, object) {
10715   var hooks;
10716
10717   loaded[name] = object;
10718
10719   if (hooks = loadHooks[name]) {
10720     loadHooks[name].forEach(function(callback) {
10721       callback(object);
10722     });
10723   }
10724 };
10725
10726 })();
10727
10728
10729
10730 (function() {
10731
10732 })();
10733
10734
10735
10736 (function() {
10737 /**
10738 @module ember
10739 @submodule ember-runtime
10740 */
10741
10742 /**
10743   Ember.ControllerMixin provides a standard interface for all classes
10744   that compose Ember's controller layer: Ember.Controller, Ember.ArrayController,
10745   and Ember.ObjectController.
10746
10747   Within an Ember.Router-managed application single shared instaces of every
10748   Controller object in your application's namespace will be added to the
10749   application's Ember.Router instance. See `Ember.Application#initialize`
10750   for additional information.
10751
10752   ## Views
10753   By default a controller instance will be the rendering context
10754   for its associated Ember.View. This connection is made during calls to
10755   `Ember.ControllerMixin#connectOutlet`.
10756
10757   Within the view's template, the Ember.View instance can be accessed
10758   through the controller with `{{view}}`.
10759
10760   ## Target Forwarding
10761   By default a controller will target your application's Ember.Router instance.
10762   Calls to `{{action}}` within the template of a controller's view are forwarded
10763   to the router. See `Ember.Handlebars.helpers.action` for additional information.
10764
10765   @class ControllerMixin
10766   @namespace Ember
10767   @extends Ember.Mixin
10768 */
10769 Ember.ControllerMixin = Ember.Mixin.create({
10770   /**
10771     The object to which events from the view should be sent.
10772
10773     For example, when a Handlebars template uses the `{{action}}` helper,
10774     it will attempt to send the event to the view's controller's `target`.
10775
10776     By default, a controller's `target` is set to the router after it is
10777     instantiated by `Ember.Application#initialize`.
10778
10779     @property target
10780     @default null
10781   */
10782   target: null,
10783
10784   store: null
10785 });
10786
10787 /**
10788   @class Controller
10789   @namespace Ember
10790   @extends Ember.Object
10791   @uses Ember.ControllerMixin
10792 */
10793 Ember.Controller = Ember.Object.extend(Ember.ControllerMixin);
10794
10795 })();
10796
10797
10798
10799 (function() {
10800 /**
10801 @module ember
10802 @submodule ember-runtime
10803 */
10804
10805 var get = Ember.get, set = Ember.set, forEach = Ember.EnumerableUtils.forEach;
10806
10807 /**
10808   Ember.SortableMixin provides a standard interface for array proxies
10809   to specify a sort order and maintain this sorting when objects are added,
10810   removed, or updated without changing the implicit order of their underlying
10811   content array:
10812
10813       songs = [
10814         {trackNumber: 4, title: 'Ob-La-Di, Ob-La-Da'},
10815         {trackNumber: 2, title: 'Back in the U.S.S.R.'},
10816         {trackNumber: 3, title: 'Glass Onion'},
10817       ];
10818
10819       songsController = Ember.ArrayController.create({
10820         content: songs,
10821         sortProperties: ['trackNumber']
10822       });
10823
10824       songsController.get('firstObject'); // {trackNumber: 2, title: 'Back in the U.S.S.R.'}
10825
10826       songsController.addObject({trackNumber: 1, title: 'Dear Prudence'});
10827       songsController.get('firstObject'); // {trackNumber: 1, title: 'Dear Prudence'}
10828
10829
10830   @class SortableMixin
10831   @namespace Ember
10832   @extends Ember.Mixin
10833   @uses Ember.MutableEnumerable
10834 */
10835 Ember.SortableMixin = Ember.Mixin.create(Ember.MutableEnumerable, {
10836   sortProperties: null,
10837   sortAscending: true,
10838
10839   addObject: function(obj) {
10840     var content = get(this, 'content');
10841     content.pushObject(obj);
10842   },
10843
10844   removeObject: function(obj) {
10845     var content = get(this, 'content');
10846     content.removeObject(obj);
10847   },
10848
10849   orderBy: function(item1, item2) {
10850     var result = 0,
10851         sortProperties = get(this, 'sortProperties'),
10852         sortAscending = get(this, 'sortAscending');
10853
10854     Ember.assert("you need to define `sortProperties`", !!sortProperties);
10855
10856     forEach(sortProperties, function(propertyName) {
10857       if (result === 0) {
10858         result = Ember.compare(get(item1, propertyName), get(item2, propertyName));
10859         if ((result !== 0) && !sortAscending) {
10860           result = (-1) * result;
10861         }
10862       }
10863     });
10864
10865     return result;
10866   },
10867
10868   destroy: function() {
10869     var content = get(this, 'content'),
10870         sortProperties = get(this, 'sortProperties');
10871
10872     if (content && sortProperties) {
10873       forEach(content, function(item) {
10874         forEach(sortProperties, function(sortProperty) {
10875           Ember.removeObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
10876         }, this);
10877       }, this);
10878     }
10879
10880     return this._super();
10881   },
10882
10883   isSorted: Ember.computed('sortProperties', function() {
10884     return !!get(this, 'sortProperties');
10885   }),
10886
10887   arrangedContent: Ember.computed('content', 'sortProperties.@each', function(key, value) {
10888     var content = get(this, 'content'),
10889         isSorted = get(this, 'isSorted'),
10890         sortProperties = get(this, 'sortProperties'),
10891         self = this;
10892
10893     if (content && isSorted) {
10894       content = content.slice();
10895       content.sort(function(item1, item2) {
10896         return self.orderBy(item1, item2);
10897       });
10898       forEach(content, function(item) {
10899         forEach(sortProperties, function(sortProperty) {
10900           Ember.addObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
10901         }, this);
10902       }, this);
10903       return Ember.A(content);
10904     }
10905
10906     return content;
10907   }),
10908
10909   _contentWillChange: Ember.beforeObserver(function() {
10910     var content = get(this, 'content'),
10911         sortProperties = get(this, 'sortProperties');
10912
10913     if (content && sortProperties) {
10914       forEach(content, function(item) {
10915         forEach(sortProperties, function(sortProperty) {
10916           Ember.removeObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
10917         }, this);
10918       }, this);
10919     }
10920
10921     this._super();
10922   }, 'content'),
10923
10924   sortAscendingWillChange: Ember.beforeObserver(function() {
10925     this._lastSortAscending = get(this, 'sortAscending');
10926   }, 'sortAscending'),
10927
10928   sortAscendingDidChange: Ember.observer(function() {
10929     if (get(this, 'sortAscending') !== this._lastSortAscending) {
10930       var arrangedContent = get(this, 'arrangedContent');
10931       arrangedContent.reverseObjects();
10932     }
10933   }, 'sortAscending'),
10934
10935   contentArrayWillChange: function(array, idx, removedCount, addedCount) {
10936     var isSorted = get(this, 'isSorted');
10937
10938     if (isSorted) {
10939       var arrangedContent = get(this, 'arrangedContent');
10940       var removedObjects = array.slice(idx, idx+removedCount);
10941       var sortProperties = get(this, 'sortProperties');
10942
10943       forEach(removedObjects, function(item) {
10944         arrangedContent.removeObject(item);
10945
10946         forEach(sortProperties, function(sortProperty) {
10947           Ember.removeObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
10948         }, this);
10949       });
10950     }
10951
10952     return this._super(array, idx, removedCount, addedCount);
10953   },
10954
10955   contentArrayDidChange: function(array, idx, removedCount, addedCount) {
10956     var isSorted = get(this, 'isSorted'),
10957         sortProperties = get(this, 'sortProperties');
10958
10959     if (isSorted) {
10960       var addedObjects = array.slice(idx, idx+addedCount);
10961       var arrangedContent = get(this, 'arrangedContent');
10962
10963       forEach(addedObjects, function(item) {
10964         this.insertItemSorted(item);
10965
10966         forEach(sortProperties, function(sortProperty) {
10967           Ember.addObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
10968         }, this);
10969       }, this);
10970     }
10971
10972     return this._super(array, idx, removedCount, addedCount);
10973   },
10974
10975   insertItemSorted: function(item) {
10976     var arrangedContent = get(this, 'arrangedContent');
10977     var length = get(arrangedContent, 'length');
10978
10979     var idx = this._binarySearch(item, 0, length);
10980     arrangedContent.insertAt(idx, item);
10981   },
10982
10983   contentItemSortPropertyDidChange: function(item) {
10984     var arrangedContent = get(this, 'arrangedContent'),
10985         oldIndex = arrangedContent.indexOf(item),
10986         leftItem = arrangedContent.objectAt(oldIndex - 1),
10987         rightItem = arrangedContent.objectAt(oldIndex + 1),
10988         leftResult = leftItem && this.orderBy(item, leftItem),
10989         rightResult = rightItem && this.orderBy(item, rightItem);
10990
10991     if (leftResult < 0 || rightResult > 0) {
10992       arrangedContent.removeObject(item);
10993       this.insertItemSorted(item);
10994     }
10995   },
10996
10997   _binarySearch: function(item, low, high) {
10998     var mid, midItem, res, arrangedContent;
10999
11000     if (low === high) {
11001       return low;
11002     }
11003
11004     arrangedContent = get(this, 'arrangedContent');
11005
11006     mid = low + Math.floor((high - low) / 2);
11007     midItem = arrangedContent.objectAt(mid);
11008
11009     res = this.orderBy(midItem, item);
11010
11011     if (res < 0) {
11012       return this._binarySearch(item, mid+1, high);
11013     } else if (res > 0) {
11014       return this._binarySearch(item, low, mid);
11015     }
11016
11017     return mid;
11018   }
11019 });
11020
11021 })();
11022
11023
11024
11025 (function() {
11026 /**
11027 @module ember
11028 @submodule ember-runtime
11029 */
11030
11031 var get = Ember.get, set = Ember.set;
11032
11033 /**
11034   Ember.ArrayController provides a way for you to publish a collection of objects
11035   so that you can easily bind to the collection from a Handlebars #each helper,
11036   an Ember.CollectionView, or other controllers.
11037
11038   The advantage of using an ArrayController is that you only have to set up
11039   your view bindings once; to change what's displayed, simply swap out the
11040   `content` property on the controller.
11041
11042   For example, imagine you wanted to display a list of items fetched via an XHR
11043   request. Create an Ember.ArrayController and set its `content` property:
11044
11045   ``` javascript
11046   MyApp.listController = Ember.ArrayController.create();
11047
11048   $.get('people.json', function(data) {
11049     MyApp.listController.set('content', data);
11050   });
11051   ```
11052
11053   Then, create a view that binds to your new controller:
11054
11055   ``` handlebars
11056   {{#each MyApp.listController}}
11057     {{firstName}} {{lastName}}
11058   {{/each}}
11059   ```
11060
11061   Although you are binding to the controller, the behavior of this controller
11062   is to pass through any methods or properties to the underlying array. This
11063   capability comes from `Ember.ArrayProxy`, which this class inherits from.
11064
11065   Note: As of this writing, `ArrayController` does not add any functionality
11066   to its superclass, `ArrayProxy`. The Ember team plans to add additional
11067   controller-specific functionality in the future, e.g. single or multiple
11068   selection support. If you are creating something that is conceptually a
11069   controller, use this class.
11070
11071   @class ArrayController
11072   @namespace Ember
11073   @extends Ember.ArrayProxy
11074   @uses Ember.SortableMixin
11075   @uses Ember.ControllerMixin
11076 */
11077
11078 Ember.ArrayController = Ember.ArrayProxy.extend(Ember.ControllerMixin,
11079   Ember.SortableMixin);
11080
11081 })();
11082
11083
11084
11085 (function() {
11086 /**
11087 @module ember
11088 @submodule ember-runtime
11089 */
11090
11091 /**
11092   Ember.ObjectController is part of Ember's Controller layer. A single
11093   shared instance of each Ember.ObjectController subclass in your application's
11094   namespace will be created at application initialization and be stored on your
11095   application's Ember.Router instance.
11096
11097   Ember.ObjectController derives its functionality from its superclass
11098   Ember.ObjectProxy and the Ember.ControllerMixin mixin.
11099
11100   @class ObjectController
11101   @namespace Ember
11102   @extends Ember.ObjectProxy
11103   @uses Ember.ControllerMixin
11104 **/
11105 Ember.ObjectController = Ember.ObjectProxy.extend(Ember.ControllerMixin);
11106
11107 })();
11108
11109
11110
11111 (function() {
11112
11113 })();
11114
11115
11116
11117 (function() {
11118 /**
11119 Ember Runtime
11120
11121 @module ember
11122 @submodule ember-runtime
11123 @requires ember-metal
11124 */
11125
11126 })();
11127
11128 (function() {
11129 function visit(vertex, fn, visited, path) {
11130   var name = vertex.name,
11131     vertices = vertex.incoming,
11132     names = vertex.incomingNames,
11133     len = names.length,
11134     i;
11135   if (!visited) {
11136     visited = {};
11137   }
11138   if (!path) {
11139     path = [];
11140   }
11141   if (visited.hasOwnProperty(name)) {
11142     return;
11143   }
11144   path.push(name);
11145   visited[name] = true;
11146   for (i = 0; i < len; i++) {
11147     visit(vertices[names[i]], fn, visited, path);
11148   }
11149   fn(vertex, path);
11150   path.pop();
11151 }
11152
11153 function DAG() {
11154   this.names = [];
11155   this.vertices = {};
11156 }
11157
11158 DAG.prototype.add = function(name) {
11159   if (!name) { return; }
11160   if (this.vertices.hasOwnProperty(name)) {
11161     return this.vertices[name];
11162   }
11163   var vertex = {
11164     name: name, incoming: {}, incomingNames: [], hasOutgoing: false, value: null
11165   };
11166   this.vertices[name] = vertex;
11167   this.names.push(name);
11168   return vertex;
11169 };
11170
11171 DAG.prototype.map = function(name, value) {
11172   this.add(name).value = value;
11173 };
11174
11175 DAG.prototype.addEdge = function(fromName, toName) {
11176   if (!fromName || !toName || fromName === toName) {
11177     return;
11178   }
11179   var from = this.add(fromName), to = this.add(toName);
11180   if (to.incoming.hasOwnProperty(fromName)) {
11181     return;
11182   }
11183   function checkCycle(vertex, path) {
11184     if (vertex.name === toName) {
11185       throw new Error("cycle detected: " + toName + " <- " + path.join(" <- "));
11186     }
11187   }
11188   visit(from, checkCycle);
11189   from.hasOutgoing = true;
11190   to.incoming[fromName] = from;
11191   to.incomingNames.push(fromName);
11192 };
11193
11194 DAG.prototype.topsort = function(fn) {
11195   var visited = {},
11196     vertices = this.vertices,
11197     names = this.names,
11198     len = names.length,
11199     i, vertex;
11200   for (i = 0; i < len; i++) {
11201     vertex = vertices[names[i]];
11202     if (!vertex.hasOutgoing) {
11203       visit(vertex, fn, visited);
11204     }
11205   }
11206 };
11207
11208 DAG.prototype.addEdges = function(name, value, before, after) {
11209   var i;
11210   this.map(name, value);
11211   if (before) {
11212     if (typeof before === 'string') {
11213       this.addEdge(name, before);
11214     } else {
11215       for (i = 0; i < before.length; i++) {
11216         this.addEdge(name, before[i]);
11217       }
11218     }
11219   }
11220   if (after) {
11221     if (typeof after === 'string') {
11222       this.addEdge(after, name);
11223     } else {
11224       for (i = 0; i < after.length; i++) {
11225         this.addEdge(after[i], name);
11226       }
11227     }
11228   }
11229 };
11230
11231 Ember.DAG = DAG;
11232
11233 })();
11234
11235
11236
11237 (function() {
11238 /**
11239 @module ember
11240 @submodule ember-application
11241 */
11242
11243 var get = Ember.get, set = Ember.set;
11244
11245 /**
11246   An instance of `Ember.Application` is the starting point for every Ember.js
11247   application. It helps to instantiate, initialize and coordinate the many
11248   objects that make up your app.
11249
11250   Each Ember.js app has one and only one `Ember.Application` object. In fact, the very
11251   first thing you should do in your application is create the instance:
11252
11253   ```javascript
11254   window.App = Ember.Application.create();
11255   ```
11256
11257   Typically, the application object is the only global variable. All other
11258   classes in your app should be properties on the `Ember.Application` instance,
11259   which highlights its first role: a global namespace.
11260
11261   For example, if you define a view class, it might look like this:
11262
11263   ```javascript
11264   App.MyView = Ember.View.extend();
11265   ```
11266
11267   After all of your classes are defined, call `App.initialize()` to start the
11268   application.
11269
11270   Because `Ember.Application` inherits from `Ember.Namespace`, any classes
11271   you create will have useful string representations when calling `toString()`;
11272   see the `Ember.Namespace` documentation for more information.
11273
11274   While you can think of your `Ember.Application` as a container that holds the
11275   other classes in your application, there are several other responsibilities
11276   going on under-the-hood that you may want to understand.
11277
11278   ### Event Delegation
11279
11280   Ember.js uses a technique called _event delegation_. This allows the framework
11281   to set up a global, shared event listener instead of requiring each view to do
11282   it manually. For example, instead of each view registering its own `mousedown`
11283   listener on its associated element, Ember.js sets up a `mousedown` listener on
11284   the `body`.
11285
11286   If a `mousedown` event occurs, Ember.js will look at the target of the event and
11287   start walking up the DOM node tree, finding corresponding views and invoking their
11288   `mouseDown` method as it goes.
11289
11290   `Ember.Application` has a number of default events that it listens for, as well
11291   as a mapping from lowercase events to camel-cased view method names. For
11292   example, the `keypress` event causes the `keyPress` method on the view to be
11293   called, the `dblclick` event causes `doubleClick` to be called, and so on.
11294
11295   If there is a browser event that Ember.js does not listen for by default, you
11296   can specify custom events and their corresponding view method names by setting
11297   the application's `customEvents` property:
11298
11299   ```javascript
11300   App = Ember.Application.create({
11301     customEvents: {
11302       // add support for the loadedmetadata media
11303       // player event
11304       'loadedmetadata': "loadedMetadata"
11305     }
11306   });
11307   ```
11308
11309   By default, the application sets up these event listeners on the document body.
11310   However, in cases where you are embedding an Ember.js application inside an
11311   existing page, you may want it to set up the listeners on an element inside
11312   the body.
11313
11314   For example, if only events inside a DOM element with the ID of `ember-app` should
11315   be delegated, set your application's `rootElement` property:
11316
11317   ```javascript
11318   window.App = Ember.Application.create({
11319     rootElement: '#ember-app'
11320   });
11321   ```
11322
11323   The `rootElement` can be either a DOM element or a jQuery-compatible selector
11324   string. Note that *views appended to the DOM outside the root element will not
11325   receive events.* If you specify a custom root element, make sure you only append
11326   views inside it!
11327
11328   To learn more about the advantages of event delegation and the Ember.js view layer,
11329   and a list of the event listeners that are setup by default, visit the
11330   [Ember.js View Layer guide](http://emberjs.com/guides/view_layer#toc_event-delegation).
11331
11332   ### Dependency Injection
11333
11334   One thing you may have noticed while using Ember.js is that you define *classes*, not
11335   *instances*. When your application loads, all of the instances are created for you.
11336   Creating these instances is the responsibility of `Ember.Application`.
11337
11338   When the `Ember.Application` initializes, it will look for an `Ember.Router` class
11339   defined on the applications's `Router` property, like this:
11340
11341   ```javascript
11342   App.Router = Ember.Router.extend({
11343   // ...
11344   });
11345   ```
11346
11347   If found, the router is instantiated and saved on the application's `router`
11348   property (note the lowercase 'r'). While you should *not* reference this router
11349   instance directly from your application code, having access to `App.router`
11350   from the console can be useful during debugging.
11351
11352   After the router is created, the application loops through all of the
11353   registered _injections_ and invokes them once for each property on the
11354   `Ember.Application` object.
11355
11356   An injection is a function that is responsible for instantiating objects from
11357   classes defined on the application. By default, the only injection registered
11358   instantiates controllers and makes them available on the router.
11359
11360   For example, if you define a controller class:
11361
11362   ```javascript
11363   App.MyController = Ember.Controller.extend({
11364     // ...
11365   });
11366   ```
11367
11368   Your router will receive an instance of `App.MyController` saved on its
11369   `myController` property.
11370
11371   Libraries on top of Ember.js can register additional injections. For example,
11372   if your application is using Ember Data, it registers an injection that
11373   instantiates `DS.Store`:
11374
11375   ```javascript
11376   Ember.Application.registerInjection({
11377     name: 'store',
11378     before: 'controllers',
11379
11380     injection: function(app, router, property) {
11381       if (property === 'Store') {
11382         set(router, 'store', app[property].create());
11383       }
11384     }
11385   });
11386   ```
11387
11388   ### Routing
11389
11390   In addition to creating your application's router, `Ember.Application` is also
11391   responsible for telling the router when to start routing.
11392
11393   By default, the router will begin trying to translate the current URL into
11394   application state once the browser emits the `DOMContentReady` event. If you
11395   need to defer routing, you can call the application's `deferReadiness()` method.
11396   Once routing can begin, call the `advanceReadiness()` method.
11397
11398   If there is any setup required before routing begins, you can implement a `ready()`
11399   method on your app that will be invoked immediately before routing begins:
11400
11401   ```javascript
11402   window.App = Ember.Application.create({
11403     ready: function() {
11404       this.set('router.enableLogging', true);
11405     }
11406   });
11407
11408   To begin routing, you must have at a minimum a top-level controller and view.
11409   You define these as `App.ApplicationController` and `App.ApplicationView`,
11410   respectively. Your application will not work if you do not define these two
11411   mandatory classes. For example:
11412
11413   ```javascript
11414   App.ApplicationView = Ember.View.extend({
11415     templateName: 'application'
11416   });
11417   App.ApplicationController = Ember.Controller.extend();
11418   ```
11419
11420   @class Application
11421   @namespace Ember
11422   @extends Ember.Namespace
11423 */
11424 Ember.Application = Ember.Namespace.extend(
11425 /** @scope Ember.Application.prototype */{
11426
11427   /**
11428     The root DOM element of the Application. This can be specified as an
11429     element or a
11430     [jQuery-compatible selector string](http://api.jquery.com/category/selectors/).
11431
11432     This is the element that will be passed to the Application's,
11433     `eventDispatcher`, which sets up the listeners for event delegation. Every
11434     view in your application should be a child of the element you specify here.
11435
11436     @property rootElement
11437     @type DOMElement
11438     @default 'body'
11439   */
11440   rootElement: 'body',
11441
11442   /**
11443     The `Ember.EventDispatcher` responsible for delegating events to this
11444     application's views.
11445
11446     The event dispatcher is created by the application at initialization time
11447     and sets up event listeners on the DOM element described by the
11448     application's `rootElement` property.
11449
11450     See the documentation for `Ember.EventDispatcher` for more information.
11451
11452     @property eventDispatcher
11453     @type Ember.EventDispatcher
11454     @default null
11455   */
11456   eventDispatcher: null,
11457
11458   /**
11459     The DOM events for which the event dispatcher should listen.
11460
11461     By default, the application's `Ember.EventDispatcher` listens
11462     for a set of standard DOM events, such as `mousedown` and
11463     `keyup`, and delegates them to your application's `Ember.View`
11464     instances.
11465
11466     If you would like additional events to be delegated to your
11467     views, set your `Ember.Application`'s `customEvents` property
11468     to a hash containing the DOM event name as the key and the
11469     corresponding view method name as the value. For example:
11470
11471         App = Ember.Application.create({
11472           customEvents: {
11473             // add support for the loadedmetadata media
11474             // player event
11475             'loadedmetadata': "loadedMetadata"
11476           }
11477         });
11478
11479     @property customEvents
11480     @type Object
11481     @default null
11482   */
11483   customEvents: null,
11484
11485   autoinit: !Ember.testing,
11486
11487   isInitialized: false,
11488
11489   init: function() {
11490     if (!this.$) { this.$ = Ember.$; }
11491
11492     this._super();
11493
11494     this.createEventDispatcher();
11495
11496     // Start off the number of deferrals at 1. This will be
11497     // decremented by the Application's own `initialize` method.
11498     this._readinessDeferrals = 1;
11499
11500     this.waitForDOMContentLoaded();
11501
11502     if (this.autoinit) {
11503       var self = this;
11504       this.$().ready(function() {
11505         if (self.isDestroyed || self.isInitialized) return;
11506         self.initialize();
11507       });
11508     }
11509   },
11510
11511   /** @private */
11512   createEventDispatcher: function() {
11513     var rootElement = get(this, 'rootElement'),
11514         eventDispatcher = Ember.EventDispatcher.create({
11515           rootElement: rootElement
11516         });
11517
11518     set(this, 'eventDispatcher', eventDispatcher);
11519   },
11520
11521   waitForDOMContentLoaded: function() {
11522     this.deferReadiness();
11523
11524     var self = this;
11525     this.$().ready(function() {
11526       self.advanceReadiness();
11527     });
11528   },
11529
11530   deferReadiness: function() {
11531     Ember.assert("You cannot defer readiness since the `ready()` hook has already been called.", this._readinessDeferrals > 0);
11532     this._readinessDeferrals++;
11533   },
11534
11535   advanceReadiness: function() {
11536     this._readinessDeferrals--;
11537
11538     if (this._readinessDeferrals === 0) {
11539       Ember.run.once(this, this.didBecomeReady);
11540     }
11541   },
11542
11543   /**
11544     Instantiate all controllers currently available on the namespace
11545     and inject them onto a router.
11546
11547     Example:
11548
11549         App.PostsController = Ember.ArrayController.extend();
11550         App.CommentsController = Ember.ArrayController.extend();
11551
11552         var router = Ember.Router.create({
11553           ...
11554         });
11555
11556         App.initialize(router);
11557
11558         router.get('postsController')     // <App.PostsController:ember1234>
11559         router.get('commentsController')  // <App.CommentsController:ember1235>
11560
11561     @method initialize
11562     @param router {Ember.Router}
11563   */
11564   initialize: function(router) {
11565     Ember.assert("Application initialize may only be call once", !this.isInitialized);
11566     Ember.assert("Application not destroyed", !this.isDestroyed);
11567
11568     router = this.setupRouter(router);
11569
11570     this.runInjections(router);
11571
11572     Ember.runLoadHooks('application', this);
11573
11574     this.isInitialized = true;
11575
11576     // At this point, any injections or load hooks that would have wanted
11577     // to defer readiness have fired.
11578     this.advanceReadiness();
11579
11580     return this;
11581   },
11582
11583   /** @private */
11584   runInjections: function(router) {
11585     var injections = get(this.constructor, 'injections'),
11586         graph = new Ember.DAG(),
11587         namespace = this,
11588         properties, i, injection;
11589
11590     for (i=0; i<injections.length; i++) {
11591       injection = injections[i];
11592       graph.addEdges(injection.name, injection.injection, injection.before, injection.after);
11593     }
11594
11595     graph.topsort(function (vertex) {
11596       var injection = vertex.value,
11597           properties = Ember.A(Ember.keys(namespace));
11598       properties.forEach(function(property) {
11599         injection(namespace, router, property);
11600       });
11601     });
11602   },
11603
11604   /** @private */
11605   setupRouter: function(router) {
11606     if (!router && Ember.Router.detect(this.Router)) {
11607       router = this.Router.create();
11608       this._createdRouter = router;
11609     }
11610
11611     if (router) {
11612       set(this, 'router', router);
11613
11614       // By default, the router's namespace is the current application.
11615       //
11616       // This allows it to find model classes when a state has a
11617       // route like `/posts/:post_id`. In that case, it would first
11618       // convert `post_id` into `Post`, and then look it up on its
11619       // namespace.
11620       set(router, 'namespace', this);
11621     }
11622
11623     return router;
11624   },
11625
11626   /** @private */
11627   didBecomeReady: function() {
11628     var eventDispatcher = get(this, 'eventDispatcher'),
11629         customEvents    = get(this, 'customEvents'),
11630         router;
11631
11632     eventDispatcher.setup(customEvents);
11633
11634     this.ready();
11635
11636
11637     router = get(this, 'router');
11638
11639     this.createApplicationView(router);
11640
11641     if (router && router instanceof Ember.Router) {
11642       this.startRouting(router);
11643     }
11644   },
11645
11646   createApplicationView: function (router) {
11647     var rootElement = get(this, 'rootElement'),
11648         applicationViewOptions = {},
11649         applicationViewClass = this.ApplicationView,
11650         applicationTemplate = Ember.TEMPLATES.application,
11651         applicationController, applicationView;
11652
11653     // don't do anything unless there is an ApplicationView or application template
11654     if (!applicationViewClass && !applicationTemplate) return;
11655
11656     if (router) {
11657       applicationController = get(router, 'applicationController');
11658       if (applicationController) {
11659         applicationViewOptions.controller = applicationController;
11660       }
11661     }
11662
11663     if (applicationTemplate) {
11664       applicationViewOptions.template = applicationTemplate;
11665     }
11666
11667     if (!applicationViewClass) {
11668       applicationViewClass = Ember.View;
11669     }
11670
11671     applicationView = applicationViewClass.create(applicationViewOptions);
11672
11673     this._createdApplicationView = applicationView;
11674
11675     if (router) {
11676       set(router, 'applicationView', applicationView);
11677     }
11678
11679     applicationView.appendTo(rootElement);
11680   },
11681
11682   /**
11683     @private
11684
11685     If the application has a router, use it to route to the current URL, and
11686     trigger a new call to `route` whenever the URL changes.
11687
11688     @method startRouting
11689     @property router {Ember.Router}
11690   */
11691   startRouting: function(router) {
11692     var location = get(router, 'location');
11693
11694     Ember.assert("You must have an application template or ApplicationView defined on your application", get(router, 'applicationView') );
11695     Ember.assert("You must have an ApplicationController defined on your application", get(router, 'applicationController') );
11696
11697     router.route(location.getURL());
11698     location.onUpdateURL(function(url) {
11699       router.route(url);
11700     });
11701   },
11702
11703   /**
11704     Called when the Application has become ready.
11705     The call will be delayed until the DOM has become ready.
11706
11707     @event ready
11708   */
11709   ready: Ember.K,
11710
11711   willDestroy: function() {
11712     get(this, 'eventDispatcher').destroy();
11713     if (this._createdRouter)          { this._createdRouter.destroy(); }
11714     if (this._createdApplicationView) { this._createdApplicationView.destroy(); }
11715   },
11716
11717   registerInjection: function(options) {
11718     this.constructor.registerInjection(options);
11719   }
11720 });
11721
11722 Ember.Application.reopenClass({
11723   concatenatedProperties: ['injections'],
11724   injections: Ember.A(),
11725   registerInjection: function(injection) {
11726     var injections = get(this, 'injections');
11727
11728     Ember.assert("The injection '" + injection.name + "' has already been registered", !injections.findProperty('name', injection.name));
11729     Ember.assert("An injection cannot be registered with both a before and an after", !(injection.before && injection.after));
11730     Ember.assert("An injection cannot be registered without an injection function", Ember.canInvoke(injection, 'injection'));
11731
11732     injections.push(injection);
11733   }
11734 });
11735
11736 Ember.Application.registerInjection({
11737   name: 'controllers',
11738   injection: function(app, router, property) {
11739     if (!router) { return; }
11740     if (!/^[A-Z].*Controller$/.test(property)) { return; }
11741
11742     var name = property.charAt(0).toLowerCase() + property.substr(1),
11743         controllerClass = app[property], controller;
11744
11745     if(!Ember.Object.detect(controllerClass)){ return; }
11746     controller = app[property].create();
11747
11748     router.set(name, controller);
11749
11750     controller.setProperties({
11751       target: router,
11752       controllers: router,
11753       namespace: app
11754     });
11755   }
11756 });
11757
11758 Ember.runLoadHooks('Ember.Application', Ember.Application);
11759
11760
11761 })();
11762
11763
11764
11765 (function() {
11766
11767 })();
11768
11769
11770
11771 (function() {
11772 /**
11773 Ember Application
11774
11775 @module ember
11776 @submodule ember-application
11777 @requires ember-views, ember-states, ember-routing
11778 */
11779
11780 })();
11781
11782 (function() {
11783 /**
11784 @module ember
11785 @submodule ember-views
11786 */
11787
11788 var jQuery = Ember.imports.jQuery;
11789 Ember.assert("Ember Views require jQuery 1.7 or 1.8", jQuery && (jQuery().jquery.match(/^1\.(7(?!$)(?!\.[01])|8)(\.\d+)?(pre|rc\d?)?/) || Ember.ENV.FORCE_JQUERY));
11790
11791 /**
11792   Alias for jQuery
11793
11794   @method $
11795   @for Ember
11796 */
11797 Ember.$ = jQuery;
11798
11799 })();
11800
11801
11802
11803 (function() {
11804 /**
11805 @module ember
11806 @submodule ember-views
11807 */
11808
11809 // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#dndevents
11810 var dragEvents = Ember.String.w('dragstart drag dragenter dragleave dragover drop dragend');
11811
11812 // Copies the `dataTransfer` property from a browser event object onto the
11813 // jQuery event object for the specified events
11814 Ember.EnumerableUtils.forEach(dragEvents, function(eventName) {
11815   Ember.$.event.fixHooks[eventName] = { props: ['dataTransfer'] };
11816 });
11817
11818 })();
11819
11820
11821
11822 (function() {
11823 /**
11824 @module ember
11825 @submodule ember-views
11826 */
11827
11828 var get = Ember.get, set = Ember.set;
11829 var indexOf = Ember.ArrayPolyfills.indexOf;
11830
11831 var ClassSet = function() {
11832   this.seen = {};
11833   this.list = [];
11834 };
11835
11836 ClassSet.prototype = {
11837   add: function(string) {
11838     if (string in this.seen) { return; }
11839     this.seen[string] = true;
11840
11841     this.list.push(string);
11842   },
11843
11844   toDOM: function() {
11845     return this.list.join(" ");
11846   }
11847 };
11848
11849 /**
11850   Ember.RenderBuffer gathers information regarding the a view and generates the
11851   final representation. Ember.RenderBuffer will generate HTML which can be pushed
11852   to the DOM.
11853
11854   @class RenderBuffer
11855   @namespace Ember
11856   @constructor
11857 */
11858 Ember.RenderBuffer = function(tagName) {
11859   return new Ember._RenderBuffer(tagName);
11860 };
11861
11862 Ember._RenderBuffer = function(tagName) {
11863   this.elementTag = tagName;
11864   this.childBuffers = [];
11865 };
11866
11867 Ember._RenderBuffer.prototype =
11868 /** @scope Ember.RenderBuffer.prototype */ {
11869
11870   /**
11871     Array of class-names which will be applied in the class="" attribute
11872
11873     You should not maintain this array yourself, rather, you should use
11874     the addClass() method of Ember.RenderBuffer.
11875
11876     @property elementClasses
11877     @type Array
11878     @default []
11879   */
11880   elementClasses: null,
11881
11882   /**
11883     The id in of the element, to be applied in the id="" attribute
11884
11885     You should not set this property yourself, rather, you should use
11886     the id() method of Ember.RenderBuffer.
11887
11888     @property elementId
11889     @type String
11890     @default null
11891   */
11892   elementId: null,
11893
11894   /**
11895     A hash keyed on the name of the attribute and whose value will be
11896     applied to that attribute. For example, if you wanted to apply a
11897     data-view="Foo.bar" property to an element, you would set the
11898     elementAttributes hash to {'data-view':'Foo.bar'}
11899
11900     You should not maintain this hash yourself, rather, you should use
11901     the attr() method of Ember.RenderBuffer.
11902
11903     @property elementAttributes
11904     @type Hash
11905     @default {}
11906   */
11907   elementAttributes: null,
11908
11909   /**
11910     The tagname of the element an instance of Ember.RenderBuffer represents.
11911
11912     Usually, this gets set as the first parameter to Ember.RenderBuffer. For
11913     example, if you wanted to create a `p` tag, then you would call
11914
11915       Ember.RenderBuffer('p')
11916
11917     @property elementTag
11918     @type String
11919     @default null
11920   */
11921   elementTag: null,
11922
11923   /**
11924     A hash keyed on the name of the style attribute and whose value will
11925     be applied to that attribute. For example, if you wanted to apply a
11926     background-color:black;" style to an element, you would set the
11927     elementStyle hash to {'background-color':'black'}
11928
11929     You should not maintain this hash yourself, rather, you should use
11930     the style() method of Ember.RenderBuffer.
11931
11932     @property elementStyle
11933     @type Hash
11934     @default {}
11935   */
11936   elementStyle: null,
11937
11938   /**
11939     Nested RenderBuffers will set this to their parent RenderBuffer
11940     instance.
11941
11942     @property parentBuffer
11943     @type Ember._RenderBuffer
11944   */
11945   parentBuffer: null,
11946
11947   /**
11948     Adds a string of HTML to the RenderBuffer.
11949
11950     @method push
11951     @param {String} string HTML to push into the buffer
11952     @chainable
11953   */
11954   push: function(string) {
11955     this.childBuffers.push(String(string));
11956     return this;
11957   },
11958
11959   /**
11960     Adds a class to the buffer, which will be rendered to the class attribute.
11961
11962     @method addClass
11963     @param {String} className Class name to add to the buffer
11964     @chainable
11965   */
11966   addClass: function(className) {
11967     // lazily create elementClasses
11968     var elementClasses = this.elementClasses = (this.elementClasses || new ClassSet());
11969     this.elementClasses.add(className);
11970
11971     return this;
11972   },
11973
11974   /**
11975     Sets the elementID to be used for the element.
11976
11977     @method id
11978     @param {String} id
11979     @chainable
11980   */
11981   id: function(id) {
11982     this.elementId = id;
11983     return this;
11984   },
11985
11986   // duck type attribute functionality like jQuery so a render buffer
11987   // can be used like a jQuery object in attribute binding scenarios.
11988
11989   /**
11990     Adds an attribute which will be rendered to the element.
11991
11992     @method attr
11993     @param {String} name The name of the attribute
11994     @param {String} value The value to add to the attribute
11995     @chainable
11996     @return {Ember.RenderBuffer|String} this or the current attribute value
11997   */
11998   attr: function(name, value) {
11999     var attributes = this.elementAttributes = (this.elementAttributes || {});
12000
12001     if (arguments.length === 1) {
12002       return attributes[name];
12003     } else {
12004       attributes[name] = value;
12005     }
12006
12007     return this;
12008   },
12009
12010   /**
12011     Remove an attribute from the list of attributes to render.
12012
12013     @method removeAttr
12014     @param {String} name The name of the attribute
12015     @chainable
12016   */
12017   removeAttr: function(name) {
12018     var attributes = this.elementAttributes;
12019     if (attributes) { delete attributes[name]; }
12020
12021     return this;
12022   },
12023
12024   /**
12025     Adds a style to the style attribute which will be rendered to the element.
12026
12027     @method style
12028     @param {String} name Name of the style
12029     @param {String} value
12030     @chainable
12031   */
12032   style: function(name, value) {
12033     var style = this.elementStyle = (this.elementStyle || {});
12034
12035     this.elementStyle[name] = value;
12036     return this;
12037   },
12038
12039   /**
12040     @private
12041
12042     Create a new child render buffer from a parent buffer. Optionally set
12043     additional properties on the buffer. Optionally invoke a callback
12044     with the newly created buffer.
12045
12046     This is a primitive method used by other public methods: `begin`,
12047     `prepend`, `replaceWith`, `insertAfter`.
12048
12049     @method newBuffer
12050     @param {String} tagName Tag name to use for the child buffer's element
12051     @param {Ember._RenderBuffer} parent The parent render buffer that this
12052       buffer should be appended to.
12053     @param {Function} fn A callback to invoke with the newly created buffer.
12054     @param {Object} other Additional properties to add to the newly created
12055       buffer.
12056   */
12057   newBuffer: function(tagName, parent, fn, other) {
12058     var buffer = new Ember._RenderBuffer(tagName);
12059     buffer.parentBuffer = parent;
12060
12061     if (other) { Ember.$.extend(buffer, other); }
12062     if (fn) { fn.call(this, buffer); }
12063
12064     return buffer;
12065   },
12066
12067   /**
12068     @private
12069
12070     Replace the current buffer with a new buffer. This is a primitive
12071     used by `remove`, which passes `null` for `newBuffer`, and `replaceWith`,
12072     which passes the new buffer it created.
12073
12074     @method replaceWithBuffer
12075     @param {Ember._RenderBuffer} buffer The buffer to insert in place of
12076       the existing buffer.
12077   */
12078   replaceWithBuffer: function(newBuffer) {
12079     var parent = this.parentBuffer;
12080     if (!parent) { return; }
12081
12082     var childBuffers = parent.childBuffers;
12083
12084     var index = indexOf.call(childBuffers, this);
12085
12086     if (newBuffer) {
12087       childBuffers.splice(index, 1, newBuffer);
12088     } else {
12089       childBuffers.splice(index, 1);
12090     }
12091   },
12092
12093   /**
12094     Creates a new Ember.RenderBuffer object with the provided tagName as
12095     the element tag and with its parentBuffer property set to the current
12096     Ember.RenderBuffer.
12097
12098     @method begin
12099     @param {String} tagName Tag name to use for the child buffer's element
12100     @return {Ember.RenderBuffer} A new RenderBuffer object
12101   */
12102   begin: function(tagName) {
12103     return this.newBuffer(tagName, this, function(buffer) {
12104       this.childBuffers.push(buffer);
12105     });
12106   },
12107
12108   /**
12109     Prepend a new child buffer to the current render buffer.
12110
12111     @method prepend
12112     @param {String} tagName Tag name to use for the child buffer's element
12113   */
12114   prepend: function(tagName) {
12115     return this.newBuffer(tagName, this, function(buffer) {
12116       this.childBuffers.splice(0, 0, buffer);
12117     });
12118   },
12119
12120   /**
12121     Replace the current buffer with a new render buffer.
12122
12123     @method replaceWith
12124     @param {String} tagName Tag name to use for the new buffer's element
12125   */
12126   replaceWith: function(tagName) {
12127     var parentBuffer = this.parentBuffer;
12128
12129     return this.newBuffer(tagName, parentBuffer, function(buffer) {
12130       this.replaceWithBuffer(buffer);
12131     });
12132   },
12133
12134   /**
12135     Insert a new render buffer after the current render buffer.
12136
12137     @method insertAfter
12138     @param {String} tagName Tag name to use for the new buffer's element
12139   */
12140   insertAfter: function(tagName) {
12141     var parentBuffer = get(this, 'parentBuffer');
12142
12143     return this.newBuffer(tagName, parentBuffer, function(buffer) {
12144       var siblings = parentBuffer.childBuffers;
12145       var index = indexOf.call(siblings, this);
12146       siblings.splice(index + 1, 0, buffer);
12147     });
12148   },
12149
12150   /**
12151     Closes the current buffer and adds its content to the parentBuffer.
12152
12153     @method end
12154     @return {Ember.RenderBuffer} The parentBuffer, if one exists. Otherwise, this
12155   */
12156   end: function() {
12157     var parent = this.parentBuffer;
12158     return parent || this;
12159   },
12160
12161   remove: function() {
12162     this.replaceWithBuffer(null);
12163   },
12164
12165   /**
12166     @method element
12167     @return {DOMElement} The element corresponding to the generated HTML
12168       of this buffer
12169   */
12170   element: function() {
12171     return Ember.$(this.string())[0];
12172   },
12173
12174   /**
12175     Generates the HTML content for this buffer.
12176
12177     @method string
12178     @return {String} The generated HTMl
12179   */
12180   string: function() {
12181     var content = '', tag = this.elementTag, openTag;
12182
12183     if (tag) {
12184       var id = this.elementId,
12185           classes = this.elementClasses,
12186           attrs = this.elementAttributes,
12187           style = this.elementStyle,
12188           styleBuffer = '', prop;
12189
12190       openTag = ["<" + tag];
12191
12192       if (id) { openTag.push('id="' + this._escapeAttribute(id) + '"'); }
12193       if (classes) { openTag.push('class="' + this._escapeAttribute(classes.toDOM()) + '"'); }
12194
12195       if (style) {
12196         for (prop in style) {
12197           if (style.hasOwnProperty(prop)) {
12198             styleBuffer += (prop + ':' + this._escapeAttribute(style[prop]) + ';');
12199           }
12200         }
12201
12202         openTag.push('style="' + styleBuffer + '"');
12203       }
12204
12205       if (attrs) {
12206         for (prop in attrs) {
12207           if (attrs.hasOwnProperty(prop)) {
12208             openTag.push(prop + '="' + this._escapeAttribute(attrs[prop]) + '"');
12209           }
12210         }
12211       }
12212
12213       openTag = openTag.join(" ") + '>';
12214     }
12215
12216     var childBuffers = this.childBuffers;
12217
12218     Ember.ArrayPolyfills.forEach.call(childBuffers, function(buffer) {
12219       var stringy = typeof buffer === 'string';
12220       content += (stringy ? buffer : buffer.string());
12221     });
12222
12223     if (tag) {
12224       return openTag + content + "</" + tag + ">";
12225     } else {
12226       return content;
12227     }
12228   },
12229
12230   _escapeAttribute: function(value) {
12231     // Stolen shamelessly from Handlebars
12232
12233     var escape = {
12234       "<": "&lt;",
12235       ">": "&gt;",
12236       '"': "&quot;",
12237       "'": "&#x27;",
12238       "`": "&#x60;"
12239     };
12240
12241     var badChars = /&(?!\w+;)|[<>"'`]/g;
12242     var possible = /[&<>"'`]/;
12243
12244     var escapeChar = function(chr) {
12245       return escape[chr] || "&amp;";
12246     };
12247
12248     var string = value.toString();
12249
12250     if(!possible.test(string)) { return string; }
12251     return string.replace(badChars, escapeChar);
12252   }
12253
12254 };
12255
12256 })();
12257
12258
12259
12260 (function() {
12261 /**
12262 @module ember
12263 @submodule ember-views
12264 */
12265
12266 var get = Ember.get, set = Ember.set, fmt = Ember.String.fmt;
12267
12268 /**
12269   Ember.EventDispatcher handles delegating browser events to their corresponding
12270   Ember.Views. For example, when you click on a view, Ember.EventDispatcher ensures
12271   that that view's `mouseDown` method gets called.
12272
12273   @class EventDispatcher
12274   @namespace Ember
12275   @private
12276   @extends Ember.Object
12277 */
12278 Ember.EventDispatcher = Ember.Object.extend(
12279 /** @scope Ember.EventDispatcher.prototype */{
12280
12281   /**
12282     @private
12283
12284     The root DOM element to which event listeners should be attached. Event
12285     listeners will be attached to the document unless this is overridden.
12286
12287     Can be specified as a DOMElement or a selector string.
12288
12289     The default body is a string since this may be evaluated before document.body
12290     exists in the DOM.
12291
12292     @property rootElement
12293     @type DOMElement
12294     @default 'body'
12295   */
12296   rootElement: 'body',
12297
12298   /**
12299     @private
12300
12301     Sets up event listeners for standard browser events.
12302
12303     This will be called after the browser sends a DOMContentReady event. By
12304     default, it will set up all of the listeners on the document body. If you
12305     would like to register the listeners on a different element, set the event
12306     dispatcher's `root` property.
12307
12308     @method setup
12309     @param addedEvents {Hash}
12310   */
12311   setup: function(addedEvents) {
12312     var event, events = {
12313       touchstart  : 'touchStart',
12314       touchmove   : 'touchMove',
12315       touchend    : 'touchEnd',
12316       touchcancel : 'touchCancel',
12317       keydown     : 'keyDown',
12318       keyup       : 'keyUp',
12319       keypress    : 'keyPress',
12320       mousedown   : 'mouseDown',
12321       mouseup     : 'mouseUp',
12322       contextmenu : 'contextMenu',
12323       click       : 'click',
12324       dblclick    : 'doubleClick',
12325       mousemove   : 'mouseMove',
12326       focusin     : 'focusIn',
12327       focusout    : 'focusOut',
12328       mouseenter  : 'mouseEnter',
12329       mouseleave  : 'mouseLeave',
12330       submit      : 'submit',
12331       input       : 'input',
12332       change      : 'change',
12333       dragstart   : 'dragStart',
12334       drag        : 'drag',
12335       dragenter   : 'dragEnter',
12336       dragleave   : 'dragLeave',
12337       dragover    : 'dragOver',
12338       drop        : 'drop',
12339       dragend     : 'dragEnd'
12340     };
12341
12342     Ember.$.extend(events, addedEvents || {});
12343
12344     var rootElement = Ember.$(get(this, 'rootElement'));
12345
12346     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'));
12347     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);
12348     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);
12349
12350     rootElement.addClass('ember-application');
12351
12352     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'));
12353
12354     for (event in events) {
12355       if (events.hasOwnProperty(event)) {
12356         this.setupHandler(rootElement, event, events[event]);
12357       }
12358     }
12359   },
12360
12361   /**
12362     @private
12363
12364     Registers an event listener on the document. If the given event is
12365     triggered, the provided event handler will be triggered on the target
12366     view.
12367
12368     If the target view does not implement the event handler, or if the handler
12369     returns false, the parent view will be called. The event will continue to
12370     bubble to each successive parent view until it reaches the top.
12371
12372     For example, to have the `mouseDown` method called on the target view when
12373     a `mousedown` event is received from the browser, do the following:
12374
12375         setupHandler('mousedown', 'mouseDown');
12376
12377     @method setupHandler
12378     @param {Element} rootElement
12379     @param {String} event the browser-originated event to listen to
12380     @param {String} eventName the name of the method to call on the view
12381   */
12382   setupHandler: function(rootElement, event, eventName) {
12383     var self = this;
12384
12385     rootElement.delegate('.ember-view', event + '.ember', function(evt, triggeringManager) {
12386       return Ember.handleErrors(function() {
12387         var view = Ember.View.views[this.id],
12388             result = true, manager = null;
12389
12390         manager = self._findNearestEventManager(view,eventName);
12391
12392         if (manager && manager !== triggeringManager) {
12393           result = self._dispatchEvent(manager, evt, eventName, view);
12394         } else if (view) {
12395           result = self._bubbleEvent(view,evt,eventName);
12396         } else {
12397           evt.stopPropagation();
12398         }
12399
12400         return result;
12401       }, this);
12402     });
12403
12404     rootElement.delegate('[data-ember-action]', event + '.ember', function(evt) {
12405       return Ember.handleErrors(function() {
12406         var actionId = Ember.$(evt.currentTarget).attr('data-ember-action'),
12407             action   = Ember.Handlebars.ActionHelper.registeredActions[actionId],
12408             handler  = action.handler;
12409
12410         if (action.eventName === eventName) {
12411           return handler(evt);
12412         }
12413       }, this);
12414     });
12415   },
12416
12417   _findNearestEventManager: function(view, eventName) {
12418     var manager = null;
12419
12420     while (view) {
12421       manager = get(view, 'eventManager');
12422       if (manager && manager[eventName]) { break; }
12423
12424       view = get(view, 'parentView');
12425     }
12426
12427     return manager;
12428   },
12429
12430   _dispatchEvent: function(object, evt, eventName, view) {
12431     var result = true;
12432
12433     var handler = object[eventName];
12434     if (Ember.typeOf(handler) === 'function') {
12435       result = handler.call(object, evt, view);
12436       // Do not preventDefault in eventManagers.
12437       evt.stopPropagation();
12438     }
12439     else {
12440       result = this._bubbleEvent(view, evt, eventName);
12441     }
12442
12443     return result;
12444   },
12445
12446   _bubbleEvent: function(view, evt, eventName) {
12447     return Ember.run(function() {
12448       return view.handleEvent(eventName, evt);
12449     });
12450   },
12451
12452   destroy: function() {
12453     var rootElement = get(this, 'rootElement');
12454     Ember.$(rootElement).undelegate('.ember').removeClass('ember-application');
12455     return this._super();
12456   }
12457 });
12458
12459 })();
12460
12461
12462
12463 (function() {
12464 /**
12465 @module ember
12466 @submodule ember-views
12467 */
12468
12469 // Add a new named queue for rendering views that happens
12470 // after bindings have synced.
12471 var queues = Ember.run.queues;
12472 queues.splice(Ember.$.inArray('actions', queues)+1, 0, 'render');
12473
12474 })();
12475
12476
12477
12478 (function() {
12479 /**
12480 @module ember
12481 @submodule ember-views
12482 */
12483
12484 var get = Ember.get, set = Ember.set;
12485
12486 // Original class declaration and documentation in runtime/lib/controllers/controller.js
12487 // NOTE: It may be possible with YUIDoc to combine docs in two locations
12488
12489 /**
12490 Additional methods for the ControllerMixin
12491
12492 @class ControllerMixin
12493 @namespace Ember
12494 */
12495 Ember.ControllerMixin.reopen({
12496
12497   target: null,
12498   controllers: null,
12499   namespace: null,
12500   view: null,
12501
12502   /**
12503     `connectOutlet` creates a new instance of a provided view
12504     class, wires it up to its associated controller, and
12505     assigns the new view to a property on the current controller.
12506
12507     The purpose of this method is to enable views that use
12508     outlets to quickly assign new views for a given outlet.
12509
12510     For example, an application view's template may look like
12511     this:
12512
12513     ``` handlebars
12514     <h1>My Blog</h1>
12515     {{outlet}}
12516     ```
12517
12518     The view for this outlet is specified by assigning a
12519     `view` property to the application's controller. The
12520     following code will assign a new `App.PostsView` to
12521     that outlet:
12522
12523     ``` javascript
12524     applicationController.connectOutlet('posts');
12525     ```
12526
12527     In general, you will also want to assign a controller
12528     to the newly created view. By convention, a controller
12529     named `postsController` will be assigned as the view's
12530     controller.
12531
12532     In an application initialized using `app.initialize(router)`,
12533     `connectOutlet` will look for `postsController` on the
12534     router. The initialization process will automatically
12535     create an instance of `App.PostsController` called
12536     `postsController`, so you don't need to do anything
12537     beyond `connectOutlet` to assign your view and wire it
12538     up to its associated controller.
12539
12540     You can supply a `content` for the controller by supplying
12541     a final argument after the view class:
12542
12543     ``` javascript
12544     applicationController.connectOutlet('posts', App.Post.find());
12545     ```
12546
12547     You can specify a particular outlet to use. For example, if your main
12548     template looks like:
12549
12550     ``` handlebars
12551     <h1>My Blog</h1>
12552     {{outlet masterView}}
12553     {{outlet detailView}}
12554     ```
12555
12556     You can assign an `App.PostsView` to the masterView outlet:
12557
12558     ``` javascript
12559     applicationController.connectOutlet({
12560       outletName: 'masterView',
12561       name: 'posts',
12562       context: App.Post.find()
12563     });
12564     ```
12565
12566     You can write this as:
12567
12568     ``` javascript
12569     applicationController.connectOutlet('masterView', 'posts', App.Post.find());
12570     ```
12571
12572
12573     @method connectOutlet
12574     @param {String} outletName a name for the outlet to set
12575     @param {String} name a view/controller pair name
12576     @param {Object} context a context object to assign to the
12577       controller's `content` property, if a controller can be
12578       found (optional)
12579   */
12580   connectOutlet: function(name, context) {
12581     // Normalize arguments. Supported arguments:
12582     //
12583     // name
12584     // name, context
12585     // outletName, name
12586     // outletName, name, context
12587     // options
12588     //
12589     // The options hash has the following keys:
12590     //
12591     //   name: the name of the controller and view
12592     //     to use. If this is passed, the name
12593     //     determines the view and controller.
12594     //   outletName: the name of the outlet to
12595     //     fill in. default: 'view'
12596     //   viewClass: the class of the view to instantiate
12597     //   controller: the controller instance to pass
12598     //     to the view
12599     //   context: an object that should become the
12600     //     controller's `content` and thus the
12601     //     template's context.
12602
12603     var outletName, viewClass, view, controller, options;
12604
12605     if (Ember.typeOf(context) === 'string') {
12606       outletName = name;
12607       name = context;
12608       context = arguments[2];
12609     }
12610
12611     if (arguments.length === 1) {
12612       if (Ember.typeOf(name) === 'object') {
12613         options = name;
12614         outletName = options.outletName;
12615         name = options.name;
12616         viewClass = options.viewClass;
12617         controller = options.controller;
12618         context = options.context;
12619       }
12620     } else {
12621       options = {};
12622     }
12623
12624     outletName = outletName || 'view';
12625
12626     Ember.assert("The viewClass is either missing or the one provided did not resolve to a view", !!name || (!name && !!viewClass));
12627
12628     Ember.assert("You must supply a name or a viewClass to connectOutlet, but not both", (!!name && !viewClass && !controller) || (!name && !!viewClass));
12629
12630     if (name) {
12631       var namespace = get(this, 'namespace'),
12632           controllers = get(this, 'controllers');
12633
12634       var viewClassName = name.charAt(0).toUpperCase() + name.substr(1) + "View";
12635       viewClass = get(namespace, viewClassName);
12636       controller = get(controllers, name + 'Controller');
12637
12638       Ember.assert("The name you supplied " + name + " did not resolve to a view " + viewClassName, !!viewClass);
12639       Ember.assert("The name you supplied " + name + " did not resolve to a controller " + name + 'Controller', (!!controller && !!context) || !context);
12640     }
12641
12642     if (controller && context) { set(controller, 'content', context); }
12643
12644     view = this.createOutletView(outletName, viewClass);
12645
12646     if (controller) { set(view, 'controller', controller); }
12647     set(this, outletName, view);
12648
12649     return view;
12650   },
12651
12652   /**
12653     Convenience method to connect controllers. This method makes other controllers
12654     available on the controller the method was invoked on.
12655
12656     For example, to make the `personController` and the `postController` available
12657     on the `overviewController`, you would call:
12658
12659         overviewController.connectControllers('person', 'post');
12660
12661     @method connectControllers
12662     @param {String...} controllerNames the controllers to make available
12663   */
12664   connectControllers: function() {
12665     var controllers = get(this, 'controllers'),
12666         controllerNames = Array.prototype.slice.apply(arguments),
12667         controllerName;
12668
12669     for (var i=0, l=controllerNames.length; i<l; i++) {
12670       controllerName = controllerNames[i] + 'Controller';
12671       set(this, controllerName, get(controllers, controllerName));
12672     }
12673   },
12674
12675   /**
12676     `disconnectOutlet` removes previously attached view from given outlet.
12677
12678     @method disconnectOutlet
12679     @param  {String} outletName the outlet name. (optional)
12680    */
12681   disconnectOutlet: function(outletName) {
12682     outletName = outletName || 'view';
12683
12684     set(this, outletName, null);
12685   },
12686
12687   /**
12688     `createOutletView` is a hook you may want to override if you need to do
12689     something special with the view created for the outlet. For example
12690     you may want to implement views sharing across outlets.
12691
12692     @method createOutletView
12693     @param outletName {String}
12694     @param viewClass {Ember.View}
12695   */
12696   createOutletView: function(outletName, viewClass) {
12697     return viewClass.create();
12698   }
12699 });
12700
12701 })();
12702
12703
12704
12705 (function() {
12706
12707 })();
12708
12709
12710
12711 (function() {
12712 /**
12713 @module ember
12714 @submodule ember-views
12715 */
12716
12717 var get = Ember.get, set = Ember.set, addObserver = Ember.addObserver, removeObserver = Ember.removeObserver;
12718 var meta = Ember.meta, fmt = Ember.String.fmt;
12719 var a_slice = [].slice;
12720 var a_forEach = Ember.EnumerableUtils.forEach;
12721
12722 var childViewsProperty = Ember.computed(function() {
12723   var childViews = this._childViews;
12724
12725   var ret = Ember.A();
12726
12727   a_forEach(childViews, function(view) {
12728     if (view.isVirtual) {
12729       ret.pushObjects(get(view, 'childViews'));
12730     } else {
12731       ret.push(view);
12732     }
12733   });
12734
12735   return ret;
12736 }).property();
12737
12738 Ember.warn("The VIEW_PRESERVES_CONTEXT flag has been removed and the functionality can no longer be disabled.", Ember.ENV.VIEW_PRESERVES_CONTEXT !== false);
12739
12740 /**
12741   Global hash of shared templates. This will automatically be populated
12742   by the build tools so that you can store your Handlebars templates in
12743   separate files that get loaded into JavaScript at buildtime.
12744
12745   @property TEMPLATES
12746   @for Ember
12747   @type Hash
12748 */
12749 Ember.TEMPLATES = {};
12750
12751 var invokeForState = {
12752   preRender: {},
12753   inBuffer: {},
12754   hasElement: {},
12755   inDOM: {},
12756   destroyed: {}
12757 };
12758
12759 Ember.CoreView = Ember.Object.extend(Ember.Evented, {
12760   init: function() {
12761     this._super();
12762
12763     // Register the view for event handling. This hash is used by
12764     // Ember.EventDispatcher to dispatch incoming events.
12765     if (!this.isVirtual) Ember.View.views[get(this, 'elementId')] = this;
12766   },
12767
12768   /**
12769     If the view is currently inserted into the DOM of a parent view, this
12770     property will point to the parent of the view.
12771
12772     @property parentView
12773     @type Ember.View
12774     @default null
12775   */
12776   parentView: Ember.computed(function() {
12777     var parent = get(this, '_parentView');
12778
12779     if (parent && parent.isVirtual) {
12780       return get(parent, 'parentView');
12781     } else {
12782       return parent;
12783     }
12784   }).property('_parentView').volatile(),
12785
12786   state: 'preRender',
12787
12788   _parentView: null,
12789
12790   // return the current view, not including virtual views
12791   concreteView: Ember.computed(function() {
12792     if (!this.isVirtual) { return this; }
12793     else { return get(this, 'parentView'); }
12794   }).property('_parentView').volatile(),
12795
12796   /**
12797     Creates a new renderBuffer with the passed tagName. You can override this
12798     method to provide further customization to the buffer if needed. Normally
12799     you will not need to call or override this method.
12800
12801     @method renderBuffer
12802     @param [tagName] {String}
12803     @return {Ember.RenderBuffer}
12804   */
12805   renderBuffer: function(tagName) {
12806     tagName = tagName || get(this, 'tagName');
12807
12808     // Explicitly check for null or undefined, as tagName
12809     // may be an empty string, which would evaluate to false.
12810     if (tagName === null || tagName === undefined) {
12811       tagName = 'div';
12812     }
12813
12814     return Ember.RenderBuffer(tagName);
12815   },
12816
12817   instrumentName: 'render.core_view',
12818
12819   instrumentDetails: function(hash) {
12820     hash.type = this.constructor.toString();
12821   },
12822
12823   /**
12824     @private
12825
12826     Invoked by the view system when this view needs to produce an HTML
12827     representation. This method will create a new render buffer, if needed,
12828     then apply any default attributes, such as class names and visibility.
12829     Finally, the `render()` method is invoked, which is responsible for
12830     doing the bulk of the rendering.
12831
12832     You should not need to override this method; instead, implement the
12833     `template` property, or if you need more control, override the `render`
12834     method.
12835
12836     @method renderToBuffer
12837     @param {Ember.RenderBuffer} buffer the render buffer. If no buffer is
12838       passed, a default buffer, using the current view's `tagName`, will
12839       be used.
12840   */
12841   renderToBuffer: function(parentBuffer, bufferOperation) {
12842     var name = get(this, 'instrumentName'),
12843         details = {};
12844
12845     this.instrumentDetails(details);
12846
12847     return Ember.instrument(name, details, function() {
12848       return this._renderToBuffer(parentBuffer, bufferOperation);
12849     }, this);
12850   },
12851
12852   _renderToBuffer: function(parentBuffer, bufferOperation) {
12853     var buffer;
12854
12855     Ember.run.sync();
12856
12857     // Determine where in the parent buffer to start the new buffer.
12858     // By default, a new buffer will be appended to the parent buffer.
12859     // The buffer operation may be changed if the child views array is
12860     // mutated by Ember.ContainerView.
12861     bufferOperation = bufferOperation || 'begin';
12862
12863     // If this is the top-most view, start a new buffer. Otherwise,
12864     // create a new buffer relative to the original using the
12865     // provided buffer operation (for example, `insertAfter` will
12866     // insert a new buffer after the "parent buffer").
12867     if (parentBuffer) {
12868       var tagName = get(this, 'tagName');
12869       if (tagName === null || tagName === undefined) {
12870         tagName = 'div';
12871       }
12872
12873       buffer = parentBuffer[bufferOperation](tagName);
12874     } else {
12875       buffer = this.renderBuffer();
12876     }
12877
12878     this.buffer = buffer;
12879     this.transitionTo('inBuffer', false);
12880
12881     this.beforeRender(buffer);
12882     this.render(buffer);
12883     this.afterRender(buffer);
12884
12885     return buffer;
12886   },
12887
12888   /**
12889     @private
12890
12891     Override the default event firing from Ember.Evented to
12892     also call methods with the given name.
12893
12894     @method trigger
12895     @param name {String}
12896   */
12897   trigger: function(name) {
12898     this._super.apply(this, arguments);
12899     var method = this[name];
12900     if (method) {
12901       var args = [], i, l;
12902       for (i = 1, l = arguments.length; i < l; i++) {
12903         args.push(arguments[i]);
12904       }
12905       return method.apply(this, args);
12906     }
12907   },
12908
12909   has: function(name) {
12910     return Ember.typeOf(this[name]) === 'function' || this._super(name);
12911   },
12912
12913   willDestroy: function() {
12914     var parent = get(this, '_parentView');
12915
12916     // destroy the element -- this will avoid each child view destroying
12917     // the element over and over again...
12918     if (!this.removedFromDOM) { this.destroyElement(); }
12919
12920     // remove from parent if found. Don't call removeFromParent,
12921     // as removeFromParent will try to remove the element from
12922     // the DOM again.
12923     if (parent) { parent.removeChild(this); }
12924
12925     this.state = 'destroyed';
12926
12927     // next remove view from global hash
12928     if (!this.isVirtual) delete Ember.View.views[get(this, 'elementId')];
12929   },
12930
12931   clearRenderedChildren: Ember.K,
12932   invokeRecursively: Ember.K,
12933   invalidateRecursively: Ember.K,
12934   transitionTo: Ember.K,
12935   destroyElement: Ember.K,
12936   _notifyWillInsertElement: Ember.K,
12937   _notifyDidInsertElement: Ember.K
12938 });
12939
12940 /**
12941   `Ember.View` is the class in Ember responsible for encapsulating templates of HTML
12942   content, combining templates with data to render as sections of a page's DOM, and
12943   registering and responding to user-initiated events.
12944
12945   ## HTML Tag
12946   The default HTML tag name used for a view's DOM representation is `div`. This can be
12947   customized by setting the `tagName` property. The following view class:
12948
12949   ``` javascript
12950   ParagraphView = Ember.View.extend({
12951     tagName: 'em'
12952   });
12953   ```
12954
12955   Would result in instances with the following HTML:
12956
12957   ``` html
12958   <em id="ember1" class="ember-view"></em>
12959   ```
12960
12961   ## HTML `class` Attribute
12962   The HTML `class` attribute of a view's tag can be set by providing a `classNames` property
12963   that is set to an array of strings:
12964
12965   ``` javascript
12966   MyView = Ember.View.extend({
12967     classNames: ['my-class', 'my-other-class']
12968   });
12969   ```
12970
12971   Will result in view instances with an HTML representation of:
12972
12973   ``` html
12974   <div id="ember1" class="ember-view my-class my-other-class"></div>
12975   ```
12976
12977   `class` attribute values can also be set by providing a `classNameBindings` property
12978   set to an array of properties names for the view. The return value of these properties
12979   will be added as part of the value for the view's `class` attribute. These properties
12980   can be computed properties:
12981
12982   ``` javascript
12983   MyView = Ember.View.extend({
12984     classNameBindings: ['propertyA', 'propertyB'],
12985     propertyA: 'from-a',
12986     propertyB: function(){
12987       if(someLogic){ return 'from-b'; }
12988     }.property()
12989   });
12990   ```
12991
12992   Will result in view instances with an HTML representation of:
12993
12994   ``` html
12995   <div id="ember1" class="ember-view from-a from-b"></div>
12996   ```
12997
12998   If the value of a class name binding returns a boolean the property name itself
12999   will be used as the class name if the property is true. The class name will
13000   not be added if the value is `false` or `undefined`.
13001
13002   ``` javascript
13003   MyView = Ember.View.extend({
13004     classNameBindings: ['hovered'],
13005     hovered: true
13006   });
13007   ```
13008
13009   Will result in view instances with an HTML representation of:
13010
13011   ``` html
13012   <div id="ember1" class="ember-view hovered"></div>
13013   ```
13014
13015   When using boolean class name bindings you can supply a string value other than the
13016   property name for use as the `class` HTML attribute by appending the preferred value after
13017   a ":" character when defining the binding:
13018
13019   ``` javascript
13020   MyView = Ember.View.extend({
13021     classNameBindings: ['awesome:so-very-cool'],
13022     awesome: true
13023   });
13024   ```
13025
13026   Will result in view instances with an HTML representation of:
13027
13028   ``` html
13029   <div id="ember1" class="ember-view so-very-cool"></div>
13030   ```
13031
13032
13033   Boolean value class name bindings whose property names are in a camelCase-style
13034   format will be converted to a dasherized format:
13035
13036   ``` javascript
13037   MyView = Ember.View.extend({
13038     classNameBindings: ['isUrgent'],
13039     isUrgent: true
13040   });
13041   ```
13042
13043   Will result in view instances with an HTML representation of:
13044
13045   ``` html
13046   <div id="ember1" class="ember-view is-urgent"></div>
13047   ```
13048
13049
13050   Class name bindings can also refer to object values that are found by
13051   traversing a path relative to the view itself:
13052
13053   ``` javascript
13054   MyView = Ember.View.extend({
13055     classNameBindings: ['messages.empty']
13056     messages: Ember.Object.create({
13057       empty: true
13058     })
13059   });
13060   ```
13061
13062   Will result in view instances with an HTML representation of:
13063
13064   ``` html
13065   <div id="ember1" class="ember-view empty"></div>
13066   ```
13067
13068
13069   If you want to add a class name for a property which evaluates to true and
13070   and a different class name if it evaluates to false, you can pass a binding
13071   like this:
13072
13073   ```
13074   // Applies 'enabled' class when isEnabled is true and 'disabled' when isEnabled is false
13075   Ember.View.create({
13076     classNameBindings: ['isEnabled:enabled:disabled']
13077     isEnabled: true
13078   });
13079   ```
13080
13081   Will result in view instances with an HTML representation of:
13082
13083   ``` html
13084   <div id="ember1" class="ember-view enabled"></div>
13085   ```
13086
13087   When isEnabled is `false`, the resulting HTML reprensentation looks like this:
13088
13089   ``` html
13090   <div id="ember1" class="ember-view disabled"></div>
13091   ```
13092
13093   This syntax offers the convenience to add a class if a property is `false`:
13094
13095   ``` javascript
13096   // Applies no class when isEnabled is true and class 'disabled' when isEnabled is false
13097   Ember.View.create({
13098     classNameBindings: ['isEnabled::disabled']
13099     isEnabled: true
13100   });
13101   ```
13102
13103   Will result in view instances with an HTML representation of:
13104
13105   ``` html
13106   <div id="ember1" class="ember-view"></div>
13107   ```
13108
13109   When the `isEnabled` property on the view is set to `false`, it will result
13110   in view instances with an HTML representation of:
13111
13112   ``` html
13113   <div id="ember1" class="ember-view disabled"></div>
13114   ```
13115
13116   Updates to the the value of a class name binding will result in automatic update
13117   of the  HTML `class` attribute in the view's rendered HTML representation.
13118   If the value becomes  `false` or `undefined` the class name will be removed.
13119
13120   Both `classNames` and `classNameBindings` are concatenated properties.
13121   See `Ember.Object` documentation for more information about concatenated properties.
13122
13123   ## HTML Attributes
13124
13125   The HTML attribute section of a view's tag can be set by providing an `attributeBindings`
13126   property set to an array of property names on the view. The return value of these properties
13127   will be used as the value of the view's HTML associated attribute:
13128
13129   ``` javascript
13130   AnchorView = Ember.View.extend({
13131     tagName: 'a',
13132     attributeBindings: ['href'],
13133     href: 'http://google.com'
13134   });
13135   ```
13136
13137   Will result in view instances with an HTML representation of:
13138
13139   ``` html
13140   <a id="ember1" class="ember-view" href="http://google.com"></a>
13141   ```
13142
13143   If the return value of an `attributeBindings` monitored property is a boolean
13144   the property will follow HTML's pattern of repeating the attribute's name as
13145   its value:
13146
13147   ``` javascript
13148   MyTextInput = Ember.View.extend({
13149     tagName: 'input',
13150     attributeBindings: ['disabled'],
13151     disabled: true
13152   });
13153   ```
13154
13155   Will result in view instances with an HTML representation of:
13156
13157   ``` html
13158   <input id="ember1" class="ember-view" disabled="disabled" />
13159   ```
13160
13161   `attributeBindings` can refer to computed properties:
13162
13163   ``` javascript
13164   MyTextInput = Ember.View.extend({
13165     tagName: 'input',
13166     attributeBindings: ['disabled'],
13167     disabled: function(){
13168       if (someLogic) {
13169         return true;
13170       } else {
13171         return false;
13172       }
13173     }.property()
13174   });
13175   ```
13176
13177   Updates to the the property of an attribute binding will result in automatic update
13178   of the  HTML attribute in the view's rendered HTML representation.
13179
13180   `attributeBindings` is a concatenated property. See `Ember.Object` documentation
13181   for more information about concatenated properties.
13182
13183   ## Templates
13184
13185   The HTML contents of a view's rendered representation are determined by its template.
13186   Templates can be any function that accepts an optional context parameter and returns
13187   a string of HTML that will be inserted within the view's tag. Most
13188   typically in Ember this function will be a compiled Ember.Handlebars template.
13189
13190   ``` javascript
13191   AView = Ember.View.extend({
13192     template: Ember.Handlebars.compile('I am the template')
13193   });
13194   ```
13195
13196   Will result in view instances with an HTML representation of:
13197
13198   ``` html
13199   <div id="ember1" class="ember-view">I am the template</div>
13200   ```
13201
13202   Within an Ember application is more common to define a Handlebars templates as
13203   part of a page:
13204
13205   ``` handlebars
13206   <script type='text/x-handlebars' data-template-name='some-template'>
13207     Hello
13208   </script>
13209   ```
13210
13211   And associate it by name using a view's `templateName` property:
13212
13213   ``` javascript
13214   AView = Ember.View.extend({
13215     templateName: 'some-template'
13216   });
13217   ```
13218
13219   Using a value for `templateName` that does not have a Handlebars template with a
13220   matching `data-template-name` attribute will throw an error.
13221
13222   Assigning a value to both `template` and `templateName` properties will throw an error.
13223
13224   For views classes that may have a template later defined (e.g. as the block portion of a `{{view}}`
13225   Handlebars helper call in another template or in a subclass), you can provide a `defaultTemplate`
13226   property set to compiled template function. If a template is not later provided for the view
13227   instance the `defaultTemplate` value will be used:
13228
13229   ``` javascript
13230   AView = Ember.View.extend({
13231     defaultTemplate: Ember.Handlebars.compile('I was the default'),
13232     template: null,
13233     templateName: null
13234   });
13235   ```
13236
13237   Will result in instances with an HTML representation of:
13238
13239   ``` html
13240   <div id="ember1" class="ember-view">I was the default</div>
13241   ```
13242
13243   If a `template` or `templateName` is provided it will take precedence over `defaultTemplate`:
13244
13245   ``` javascript
13246   AView = Ember.View.extend({
13247     defaultTemplate: Ember.Handlebars.compile('I was the default')
13248   });
13249
13250   aView = AView.create({
13251     template: Ember.Handlebars.compile('I was the template, not default')
13252   });
13253   ```
13254
13255   Will result in the following HTML representation when rendered:
13256
13257   ``` html
13258   <div id="ember1" class="ember-view">I was the template, not default</div>
13259   ```
13260
13261   ## View Context
13262
13263   The default context of the compiled template is the view's controller:
13264
13265   ``` javascript
13266   AView = Ember.View.extend({
13267     template: Ember.Handlebars.compile('Hello {{excitedGreeting}}')
13268   });
13269
13270   aController = Ember.Object.create({
13271     firstName: 'Barry',
13272     excitedGreeting: function(){
13273       return this.get("content.firstName") + "!!!"
13274     }.property()
13275   });
13276
13277   aView = AView.create({
13278     controller: aController,
13279   });
13280   ```
13281
13282   Will result in an HTML representation of:
13283
13284   ``` html
13285   <div id="ember1" class="ember-view">Hello Barry!!!</div>
13286   ```
13287
13288   A context can also be explicitly supplied through the view's `context` property.
13289   If the view has neither `context` nor `controller` properties, the parentView's
13290   context will be used.
13291
13292   ## Layouts
13293
13294   Views can have a secondary template that wraps their main template. Like
13295   primary templates, layouts can be any function that  accepts an optional context
13296   parameter and returns a string of HTML that will be inserted inside view's tag. Views whose HTML
13297   element is self closing (e.g. `<input />`) cannot have a layout and this property will be ignored.
13298
13299   Most typically in Ember a layout will be a compiled Ember.Handlebars template.
13300
13301   A view's layout can be set directly with the `layout` property or reference an
13302   existing Handlebars template by name with the `layoutName` property.
13303
13304   A template used as a layout must contain a single use of the Handlebars `{{yield}}`
13305   helper. The HTML contents of a view's rendered `template` will be inserted at this location:
13306
13307   ``` javascript
13308   AViewWithLayout = Ember.View.extend({
13309     layout: Ember.Handlebars.compile("<div class='my-decorative-class'>{{yield}}</div>")
13310     template: Ember.Handlebars.compile("I got wrapped"),
13311   });
13312   ```
13313
13314   Will result in view instances with an HTML representation of:
13315
13316   ``` html
13317   <div id="ember1" class="ember-view">
13318     <div class="my-decorative-class">
13319       I got wrapped
13320     </div>
13321   </div>
13322   ```
13323
13324   See `Handlebars.helpers.yield` for more information.
13325
13326   ## Responding to Browser Events
13327
13328   Views can respond to user-initiated events in one of three ways: method implementation,
13329   through an event manager, and through `{{action}}` helper use in their template or layout.
13330
13331   ### Method Implementation
13332
13333   Views can respond to user-initiated events by implementing a method that matches the
13334   event name. A `jQuery.Event` object will be passed as the argument to this method.
13335
13336   ``` javascript
13337   AView = Ember.View.extend({
13338     click: function(event){
13339       // will be called when when an instance's
13340       // rendered element is clicked
13341     }
13342   });
13343   ```
13344
13345   ### Event Managers
13346
13347   Views can define an object as their `eventManager` property. This object can then
13348   implement methods that match the desired event names. Matching events that occur
13349   on the view's rendered HTML or the rendered HTML of any of its DOM descendants
13350   will trigger this method.  A `jQuery.Event` object will be passed as the first
13351   argument to the method and an  `Ember.View` object as the second. The `Ember.View`
13352   will be the view whose rendered HTML was interacted with. This may be the view with
13353   the `eventManager` property or one of its descendent views.
13354
13355   ``` javascript
13356   AView = Ember.View.extend({
13357     eventManager: Ember.Object.create({
13358       doubleClick: function(event, view){
13359         // will be called when when an instance's
13360         // rendered element or any rendering
13361         // of this views's descendent
13362         // elements is clicked
13363       }
13364     })
13365   });
13366   ```
13367
13368   An event defined for an event manager takes precedence over events of the same
13369   name handled through methods on the view.
13370
13371   ``` javascript
13372   AView = Ember.View.extend({
13373     mouseEnter: function(event){
13374       // will never trigger.
13375     },
13376     eventManager: Ember.Object.create({
13377       mouseEnter: function(event, view){
13378         // takes presedence over AView#mouseEnter
13379       }
13380     })
13381   });
13382   ```
13383
13384   Similarly a view's event manager will take precedence for events of any views
13385   rendered as a descendent. A method name that matches an event name will not be called
13386   if the view instance was rendered inside the HTML representation of a view that has
13387   an `eventManager` property defined that handles events of the name.  Events not handled
13388   by the event manager will still trigger method calls on the descendent.
13389
13390   ``` javascript
13391   OuterView = Ember.View.extend({
13392     template: Ember.Handlebars.compile("outer {{#view InnerView}}inner{{/view}} outer"),
13393     eventManager: Ember.Object.create({
13394       mouseEnter: function(event, view){
13395         // view might be instance of either
13396         // OutsideView or InnerView depending on
13397         // where on the page the user interaction occured
13398       }
13399     })
13400   });
13401
13402   InnerView = Ember.View.extend({
13403     click: function(event){
13404       // will be called if rendered inside
13405       // an OuterView because OuterView's
13406       // eventManager doesn't handle click events
13407     },
13408     mouseEnter: function(event){
13409       // will never be called if rendered inside
13410       // an OuterView.
13411     }
13412   });
13413   ```
13414
13415   ### Handlebars `{{action}}` Helper
13416
13417   See `Handlebars.helpers.action`.
13418
13419   ### Event Names
13420
13421   Possible events names for any of the responding approaches described above are:
13422
13423   Touch events: 'touchStart', 'touchMove', 'touchEnd', 'touchCancel'
13424
13425   Keyboard events: 'keyDown', 'keyUp', 'keyPress'
13426
13427   Mouse events: 'mouseDown', 'mouseUp', 'contextMenu', 'click', 'doubleClick', 'mouseMove',
13428   'focusIn', 'focusOut', 'mouseEnter', 'mouseLeave'
13429
13430   Form events: 'submit', 'change', 'focusIn', 'focusOut', 'input'
13431
13432   HTML5 drag and drop events: 'dragStart', 'drag', 'dragEnter', 'dragLeave', 'drop', 'dragEnd'
13433
13434   ## Handlebars `{{view}}` Helper
13435
13436   Other `Ember.View` instances can be included as part of a view's template by using the `{{view}}`
13437   Handlebars helper. See `Handlebars.helpers.view` for additional information.
13438
13439   @class View
13440   @namespace Ember
13441   @extends Ember.Object
13442   @uses Ember.Evented
13443 */
13444 Ember.View = Ember.CoreView.extend(
13445 /** @scope Ember.View.prototype */ {
13446
13447   concatenatedProperties: ['classNames', 'classNameBindings', 'attributeBindings'],
13448
13449   /**
13450     @property isView
13451     @type Boolean
13452     @default true
13453     @final
13454   */
13455   isView: true,
13456
13457   // ..........................................................
13458   // TEMPLATE SUPPORT
13459   //
13460
13461   /**
13462     The name of the template to lookup if no template is provided.
13463
13464     Ember.View will look for a template with this name in this view's
13465     `templates` object. By default, this will be a global object
13466     shared in `Ember.TEMPLATES`.
13467
13468     @property templateName
13469     @type String
13470     @default null
13471   */
13472   templateName: null,
13473
13474   /**
13475     The name of the layout to lookup if no layout is provided.
13476
13477     Ember.View will look for a template with this name in this view's
13478     `templates` object. By default, this will be a global object
13479     shared in `Ember.TEMPLATES`.
13480
13481     @property layoutName
13482     @type String
13483     @default null
13484   */
13485   layoutName: null,
13486
13487   /**
13488     The hash in which to look for `templateName`.
13489
13490     @property templates
13491     @type Ember.Object
13492     @default Ember.TEMPLATES
13493   */
13494   templates: Ember.TEMPLATES,
13495
13496   /**
13497     The template used to render the view. This should be a function that
13498     accepts an optional context parameter and returns a string of HTML that
13499     will be inserted into the DOM relative to its parent view.
13500
13501     In general, you should set the `templateName` property instead of setting
13502     the template yourself.
13503
13504     @property template
13505     @type Function
13506   */
13507   template: Ember.computed(function(key, value) {
13508     if (value !== undefined) { return value; }
13509
13510     var templateName = get(this, 'templateName'),
13511         template = this.templateForName(templateName, 'template');
13512
13513     return template || get(this, 'defaultTemplate');
13514   }).property('templateName'),
13515
13516   /**
13517     The controller managing this view. If this property is set, it will be
13518     made available for use by the template.
13519
13520     @property controller
13521     @type Object
13522   */
13523   controller: Ember.computed(function(key, value) {
13524     var parentView;
13525
13526     if (arguments.length === 2) {
13527       return value;
13528     } else {
13529       parentView = get(this, 'parentView');
13530       return parentView ? get(parentView, 'controller') : null;
13531     }
13532   }).property(),
13533
13534   /**
13535     A view may contain a layout. A layout is a regular template but
13536     supersedes the `template` property during rendering. It is the
13537     responsibility of the layout template to retrieve the `template`
13538     property from the view (or alternatively, call `Handlebars.helpers.yield`,
13539     `{{yield}}`) to render it in the correct location.
13540
13541     This is useful for a view that has a shared wrapper, but which delegates
13542     the rendering of the contents of the wrapper to the `template` property
13543     on a subclass.
13544
13545     @property layout
13546     @type Function
13547   */
13548   layout: Ember.computed(function(key, value) {
13549     if (arguments.length === 2) { return value; }
13550
13551     var layoutName = get(this, 'layoutName'),
13552         layout = this.templateForName(layoutName, 'layout');
13553
13554     return layout || get(this, 'defaultLayout');
13555   }).property('layoutName'),
13556
13557   templateForName: function(name, type) {
13558     if (!name) { return; }
13559
13560     var templates = get(this, 'templates'),
13561         template = get(templates, name);
13562
13563     if (!template) {
13564      throw new Ember.Error(fmt('%@ - Unable to find %@ "%@".', [this, type, name]));
13565     }
13566
13567     return template;
13568   },
13569
13570   /**
13571     The object from which templates should access properties.
13572
13573     This object will be passed to the template function each time the render
13574     method is called, but it is up to the individual function to decide what
13575     to do with it.
13576
13577     By default, this will be the view's controller.
13578
13579     @property context
13580     @type Object
13581   */
13582   context: Ember.computed(function(key, value) {
13583     if (arguments.length === 2) {
13584       set(this, '_context', value);
13585       return value;
13586     } else {
13587       return get(this, '_context');
13588     }
13589   }).volatile(),
13590
13591   /**
13592     @private
13593
13594     Private copy of the view's template context. This can be set directly
13595     by Handlebars without triggering the observer that causes the view
13596     to be re-rendered.
13597
13598     The context of a view is looked up as follows:
13599
13600     1. Supplied context (usually by Handlebars)
13601     2. Specified controller
13602     3. `parentView`'s context (for a child of a ContainerView)
13603
13604     The code in Handlebars that overrides the `_context` property first
13605     checks to see whether the view has a specified controller. This is
13606     something of a hack and should be revisited.
13607
13608     @property _context
13609   */
13610   _context: Ember.computed(function(key, value) {
13611     var parentView, controller;
13612
13613     if (arguments.length === 2) {
13614       return value;
13615     }
13616
13617     if (controller = get(this, 'controller')) {
13618       return controller;
13619     }
13620
13621     parentView = get(this, '_parentView');
13622     if (parentView) {
13623       return get(parentView, '_context');
13624     }
13625
13626     return this;
13627   }),
13628
13629   /**
13630     @private
13631
13632     If a value that affects template rendering changes, the view should be
13633     re-rendered to reflect the new value.
13634
13635     @method _displayPropertyDidChange
13636   */
13637   _displayPropertyDidChange: Ember.observer(function() {
13638     this.rerender();
13639   }, 'context', 'controller'),
13640
13641   /**
13642     If false, the view will appear hidden in DOM.
13643
13644     @property isVisible
13645     @type Boolean
13646     @default null
13647   */
13648   isVisible: true,
13649
13650   /**
13651     @private
13652
13653     Array of child views. You should never edit this array directly.
13654     Instead, use appendChild and removeFromParent.
13655
13656     @property childViews
13657     @type Array
13658     @default []
13659   */
13660   childViews: childViewsProperty,
13661
13662   _childViews: [],
13663
13664   // When it's a virtual view, we need to notify the parent that their
13665   // childViews will change.
13666   _childViewsWillChange: Ember.beforeObserver(function() {
13667     if (this.isVirtual) {
13668       var parentView = get(this, 'parentView');
13669       if (parentView) { Ember.propertyWillChange(parentView, 'childViews'); }
13670     }
13671   }, 'childViews'),
13672
13673   // When it's a virtual view, we need to notify the parent that their
13674   // childViews did change.
13675   _childViewsDidChange: Ember.observer(function() {
13676     if (this.isVirtual) {
13677       var parentView = get(this, 'parentView');
13678       if (parentView) { Ember.propertyDidChange(parentView, 'childViews'); }
13679     }
13680   }, 'childViews'),
13681
13682   /**
13683     Return the nearest ancestor that is an instance of the provided
13684     class.
13685
13686     @property nearestInstanceOf
13687     @param {Class} klass Subclass of Ember.View (or Ember.View itself)
13688     @return Ember.View
13689     @deprecated
13690   */
13691   nearestInstanceOf: function(klass) {
13692     Ember.deprecate("nearestInstanceOf is deprecated and will be removed from future releases. Use nearestOfType.");
13693     var view = get(this, 'parentView');
13694
13695     while (view) {
13696       if(view instanceof klass) { return view; }
13697       view = get(view, 'parentView');
13698     }
13699   },
13700
13701   /**
13702     Return the nearest ancestor that is an instance of the provided
13703     class or mixin.
13704
13705     @property nearestOfType
13706     @param {Class,Mixin} klass Subclass of Ember.View (or Ember.View itself),
13707            or an instance of Ember.Mixin.
13708     @return Ember.View
13709   */
13710   nearestOfType: function(klass) {
13711     var view = get(this, 'parentView'),
13712         isOfType = klass instanceof Ember.Mixin ?
13713                    function(view) { return klass.detect(view); } :
13714                    function(view) { return klass.detect(view.constructor); };
13715
13716     while (view) {
13717       if( isOfType(view) ) { return view; }
13718       view = get(view, 'parentView');
13719     }
13720   },
13721
13722   /**
13723     Return the nearest ancestor that has a given property.
13724
13725     @property nearestWithProperty
13726     @param {String} property A property name
13727     @return Ember.View
13728   */
13729   nearestWithProperty: function(property) {
13730     var view = get(this, 'parentView');
13731
13732     while (view) {
13733       if (property in view) { return view; }
13734       view = get(view, 'parentView');
13735     }
13736   },
13737
13738   /**
13739     Return the nearest ancestor whose parent is an instance of
13740     `klass`.
13741
13742     @property nearestChildOf
13743     @param {Class} klass Subclass of Ember.View (or Ember.View itself)
13744     @return Ember.View
13745   */
13746   nearestChildOf: function(klass) {
13747     var view = get(this, 'parentView');
13748
13749     while (view) {
13750       if(get(view, 'parentView') instanceof klass) { return view; }
13751       view = get(view, 'parentView');
13752     }
13753   },
13754
13755   /**
13756     Return the nearest ancestor that is an Ember.CollectionView
13757
13758     @property collectionView
13759     @return Ember.CollectionView
13760   */
13761   collectionView: Ember.computed(function() {
13762     return this.nearestOfType(Ember.CollectionView);
13763   }),
13764
13765   /**
13766     Return the nearest ancestor that is a direct child of
13767     an Ember.CollectionView
13768
13769     @property itemView
13770     @return Ember.View
13771   */
13772   itemView: Ember.computed(function() {
13773     return this.nearestChildOf(Ember.CollectionView);
13774   }),
13775
13776   /**
13777     Return the nearest ancestor that has the property
13778     `content`.
13779
13780     @property contentView
13781     @return Ember.View
13782   */
13783   contentView: Ember.computed(function() {
13784     return this.nearestWithProperty('content');
13785   }),
13786
13787   /**
13788     @private
13789
13790     When the parent view changes, recursively invalidate
13791     collectionView, itemView, and contentView
13792
13793     @method _parentViewDidChange
13794   */
13795   _parentViewDidChange: Ember.observer(function() {
13796     if (this.isDestroying) { return; }
13797
13798     this.invokeRecursively(function(view) {
13799       view.propertyDidChange('collectionView');
13800       view.propertyDidChange('itemView');
13801       view.propertyDidChange('contentView');
13802     });
13803
13804     if (get(this, 'parentView.controller') && !get(this, 'controller')) {
13805       this.notifyPropertyChange('controller');
13806     }
13807   }, '_parentView'),
13808
13809   _controllerDidChange: Ember.observer(function() {
13810     if (this.isDestroying) { return; }
13811
13812     this.forEachChildView(function(view) {
13813       view.propertyDidChange('controller');
13814     });
13815   }, 'controller'),
13816
13817   cloneKeywords: function() {
13818     var templateData = get(this, 'templateData');
13819
13820     var keywords = templateData ? Ember.copy(templateData.keywords) : {};
13821     set(keywords, 'view', get(this, 'concreteView'));
13822     set(keywords, 'controller', get(this, 'controller'));
13823
13824     return keywords;
13825   },
13826
13827   /**
13828     Called on your view when it should push strings of HTML into a
13829     Ember.RenderBuffer. Most users will want to override the `template`
13830     or `templateName` properties instead of this method.
13831
13832     By default, Ember.View will look for a function in the `template`
13833     property and invoke it with the value of `context`. The value of
13834     `context` will be the view's controller unless you override it.
13835
13836     @method render
13837     @param {Ember.RenderBuffer} buffer The render buffer
13838   */
13839   render: function(buffer) {
13840     // If this view has a layout, it is the responsibility of the
13841     // the layout to render the view's template. Otherwise, render the template
13842     // directly.
13843     var template = get(this, 'layout') || get(this, 'template');
13844
13845     if (template) {
13846       var context = get(this, 'context');
13847       var keywords = this.cloneKeywords();
13848
13849       var data = {
13850         view: this,
13851         buffer: buffer,
13852         isRenderData: true,
13853         keywords: keywords
13854       };
13855
13856       // Invoke the template with the provided template context, which
13857       // is the view's controller by default. A hash of data is also passed that provides
13858       // the template with access to the view and render buffer.
13859
13860       Ember.assert('template must be a function. Did you mean to call Ember.Handlebars.compile("...") or specify templateName instead?', typeof template === 'function');
13861       // The template should write directly to the render buffer instead
13862       // of returning a string.
13863       var output = template(context, { data: data });
13864
13865       // If the template returned a string instead of writing to the buffer,
13866       // push the string onto the buffer.
13867       if (output !== undefined) { buffer.push(output); }
13868     }
13869   },
13870
13871   invokeForState: function(name) {
13872     var stateName = this.state, args, fn;
13873
13874     // try to find the function for the state in the cache
13875     if (fn = invokeForState[stateName][name]) {
13876       args = a_slice.call(arguments);
13877       args[0] = this;
13878
13879       return fn.apply(this, args);
13880     }
13881
13882     // otherwise, find and cache the function for this state
13883     var parent = this, states = parent.states, state;
13884
13885     while (states) {
13886       state = states[stateName];
13887
13888       while (state) {
13889         fn = state[name];
13890
13891         if (fn) {
13892           invokeForState[stateName][name] = fn;
13893
13894           args = a_slice.call(arguments, 1);
13895           args.unshift(this);
13896
13897           return fn.apply(this, args);
13898         }
13899
13900         state = state.parentState;
13901       }
13902
13903       states = states.parent;
13904     }
13905   },
13906
13907   /**
13908     Renders the view again. This will work regardless of whether the
13909     view is already in the DOM or not. If the view is in the DOM, the
13910     rendering process will be deferred to give bindings a chance
13911     to synchronize.
13912
13913     If children were added during the rendering process using `appendChild`,
13914     `rerender` will remove them, because they will be added again
13915     if needed by the next `render`.
13916
13917     In general, if the display of your view changes, you should modify
13918     the DOM element directly instead of manually calling `rerender`, which can
13919     be slow.
13920
13921     @method rerender
13922   */
13923   rerender: function() {
13924     return this.invokeForState('rerender');
13925   },
13926
13927   clearRenderedChildren: function() {
13928     var lengthBefore = this.lengthBeforeRender,
13929         lengthAfter  = this.lengthAfterRender;
13930
13931     // If there were child views created during the last call to render(),
13932     // remove them under the assumption that they will be re-created when
13933     // we re-render.
13934
13935     // VIEW-TODO: Unit test this path.
13936     var childViews = this._childViews;
13937     for (var i=lengthAfter-1; i>=lengthBefore; i--) {
13938       if (childViews[i]) { childViews[i].destroy(); }
13939     }
13940   },
13941
13942   /**
13943     @private
13944
13945     Iterates over the view's `classNameBindings` array, inserts the value
13946     of the specified property into the `classNames` array, then creates an
13947     observer to update the view's element if the bound property ever changes
13948     in the future.
13949
13950     @method _applyClassNameBindings
13951   */
13952   _applyClassNameBindings: function() {
13953     var classBindings = get(this, 'classNameBindings'),
13954         classNames = get(this, 'classNames'),
13955         elem, newClass, dasherizedClass;
13956
13957     if (!classBindings) { return; }
13958
13959     // Loop through all of the configured bindings. These will be either
13960     // property names ('isUrgent') or property paths relative to the view
13961     // ('content.isUrgent')
13962     a_forEach(classBindings, function(binding) {
13963
13964       // Variable in which the old class value is saved. The observer function
13965       // closes over this variable, so it knows which string to remove when
13966       // the property changes.
13967       var oldClass;
13968       // Extract just the property name from bindings like 'foo:bar'
13969       var parsedPath = Ember.View._parsePropertyPath(binding);
13970
13971       // Set up an observer on the context. If the property changes, toggle the
13972       // class name.
13973       var observer = function() {
13974         // Get the current value of the property
13975         newClass = this._classStringForProperty(binding);
13976         elem = this.$();
13977         if (!elem) {
13978           removeObserver(this, parsedPath.path, observer);
13979           return;
13980         }
13981
13982         // If we had previously added a class to the element, remove it.
13983         if (oldClass) {
13984           elem.removeClass(oldClass);
13985           // Also remove from classNames so that if the view gets rerendered,
13986           // the class doesn't get added back to the DOM.
13987           classNames.removeObject(oldClass);
13988         }
13989
13990         // If necessary, add a new class. Make sure we keep track of it so
13991         // it can be removed in the future.
13992         if (newClass) {
13993           elem.addClass(newClass);
13994           oldClass = newClass;
13995         } else {
13996           oldClass = null;
13997         }
13998       };
13999
14000       // Get the class name for the property at its current value
14001       dasherizedClass = this._classStringForProperty(binding);
14002
14003       if (dasherizedClass) {
14004         // Ensure that it gets into the classNames array
14005         // so it is displayed when we render.
14006         classNames.push(dasherizedClass);
14007
14008         // Save a reference to the class name so we can remove it
14009         // if the observer fires. Remember that this variable has
14010         // been closed over by the observer.
14011         oldClass = dasherizedClass;
14012       }
14013
14014       addObserver(this, parsedPath.path, observer);
14015
14016       this.one('willClearRender', function() {
14017         removeObserver(this, parsedPath.path, observer);
14018       });
14019     }, this);
14020   },
14021
14022   /**
14023     @private
14024
14025     Iterates through the view's attribute bindings, sets up observers for each,
14026     then applies the current value of the attributes to the passed render buffer.
14027
14028     @method _applyAttributeBindings
14029     @param {Ember.RenderBuffer} buffer
14030   */
14031   _applyAttributeBindings: function(buffer) {
14032     var attributeBindings = get(this, 'attributeBindings'),
14033         attributeValue, elem, type;
14034
14035     if (!attributeBindings) { return; }
14036
14037     a_forEach(attributeBindings, function(binding) {
14038       var split = binding.split(':'),
14039           property = split[0],
14040           attributeName = split[1] || property;
14041
14042       // Create an observer to add/remove/change the attribute if the
14043       // JavaScript property changes.
14044       var observer = function() {
14045         elem = this.$();
14046         if (!elem) { return; }
14047
14048         attributeValue = get(this, property);
14049
14050         Ember.View.applyAttributeBindings(elem, attributeName, attributeValue);
14051       };
14052
14053       addObserver(this, property, observer);
14054
14055       this.one('willClearRender', function() {
14056         removeObserver(this, property, observer);
14057       });
14058
14059       // Determine the current value and add it to the render buffer
14060       // if necessary.
14061       attributeValue = get(this, property);
14062       Ember.View.applyAttributeBindings(buffer, attributeName, attributeValue);
14063     }, this);
14064   },
14065
14066   /**
14067     @private
14068
14069     Given a property name, returns a dasherized version of that
14070     property name if the property evaluates to a non-falsy value.
14071
14072     For example, if the view has property `isUrgent` that evaluates to true,
14073     passing `isUrgent` to this method will return `"is-urgent"`.
14074
14075     @method _classStringForProperty
14076     @param property
14077   */
14078   _classStringForProperty: function(property) {
14079     var parsedPath = Ember.View._parsePropertyPath(property);
14080     var path = parsedPath.path;
14081
14082     var val = get(this, path);
14083     if (val === undefined && Ember.isGlobalPath(path)) {
14084       val = get(Ember.lookup, path);
14085     }
14086
14087     return Ember.View._classStringForValue(path, val, parsedPath.className, parsedPath.falsyClassName);
14088   },
14089
14090   // ..........................................................
14091   // ELEMENT SUPPORT
14092   //
14093
14094   /**
14095     Returns the current DOM element for the view.
14096
14097     @property element
14098     @type DOMElement
14099   */
14100   element: Ember.computed(function(key, value) {
14101     if (value !== undefined) {
14102       return this.invokeForState('setElement', value);
14103     } else {
14104       return this.invokeForState('getElement');
14105     }
14106   }).property('_parentView'),
14107
14108   /**
14109     Returns a jQuery object for this view's element. If you pass in a selector
14110     string, this method will return a jQuery object, using the current element
14111     as its buffer.
14112
14113     For example, calling `view.$('li')` will return a jQuery object containing
14114     all of the `li` elements inside the DOM element of this view.
14115
14116     @property $
14117     @param {String} [selector] a jQuery-compatible selector string
14118     @return {jQuery} the CoreQuery object for the DOM node
14119   */
14120   $: function(sel) {
14121     return this.invokeForState('$', sel);
14122   },
14123
14124   mutateChildViews: function(callback) {
14125     var childViews = this._childViews,
14126         idx = childViews.length,
14127         view;
14128
14129     while(--idx >= 0) {
14130       view = childViews[idx];
14131       callback.call(this, view, idx);
14132     }
14133
14134     return this;
14135   },
14136
14137   forEachChildView: function(callback) {
14138     var childViews = this._childViews;
14139
14140     if (!childViews) { return this; }
14141
14142     var len = childViews.length,
14143         view, idx;
14144
14145     for(idx = 0; idx < len; idx++) {
14146       view = childViews[idx];
14147       callback.call(this, view);
14148     }
14149
14150     return this;
14151   },
14152
14153   /**
14154     Appends the view's element to the specified parent element.
14155
14156     If the view does not have an HTML representation yet, `createElement()`
14157     will be called automatically.
14158
14159     Note that this method just schedules the view to be appended; the DOM
14160     element will not be appended to the given element until all bindings have
14161     finished synchronizing.
14162
14163     This is not typically a function that you will need to call directly
14164     when building your application. You might consider using Ember.ContainerView
14165     instead. If you do need to use appendTo, be sure that the target element you
14166     are providing is associated with an Ember.Application and does not have an
14167     ancestor element that is associated with an Ember view.
14168
14169     @method appendTo
14170     @param {String|DOMElement|jQuery} A selector, element, HTML string, or jQuery object
14171     @return {Ember.View} receiver
14172   */
14173   appendTo: function(target) {
14174     // Schedule the DOM element to be created and appended to the given
14175     // element after bindings have synchronized.
14176     this._insertElementLater(function() {
14177       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'));
14178       this.$().appendTo(target);
14179     });
14180
14181     return this;
14182   },
14183
14184   /**
14185     Replaces the content of the specified parent element with this view's element.
14186     If the view does not have an HTML representation yet, `createElement()`
14187     will be called automatically.
14188
14189     Note that this method just schedules the view to be appended; the DOM
14190     element will not be appended to the given element until all bindings have
14191     finished synchronizing
14192
14193     @method replaceIn
14194     @param {String|DOMElement|jQuery} A selector, element, HTML string, or jQuery object
14195     @return {Ember.View} received
14196   */
14197   replaceIn: function(target) {
14198     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'));
14199
14200     this._insertElementLater(function() {
14201       Ember.$(target).empty();
14202       this.$().appendTo(target);
14203     });
14204
14205     return this;
14206   },
14207
14208   /**
14209     @private
14210
14211     Schedules a DOM operation to occur during the next render phase. This
14212     ensures that all bindings have finished synchronizing before the view is
14213     rendered.
14214
14215     To use, pass a function that performs a DOM operation..
14216
14217     Before your function is called, this view and all child views will receive
14218     the `willInsertElement` event. After your function is invoked, this view
14219     and all of its child views will receive the `didInsertElement` event.
14220
14221         view._insertElementLater(function() {
14222           this.createElement();
14223           this.$().appendTo('body');
14224         });
14225
14226     @method _insertElementLater
14227     @param {Function} fn the function that inserts the element into the DOM
14228   */
14229   _insertElementLater: function(fn) {
14230     this._scheduledInsert = Ember.run.scheduleOnce('render', this, '_insertElement', fn);
14231   },
14232
14233   /**
14234    @private
14235   */
14236   _insertElement: function (fn) {
14237     this._scheduledInsert = null;
14238     this.invokeForState('insertElement', fn);
14239   },
14240
14241   /**
14242     Appends the view's element to the document body. If the view does
14243     not have an HTML representation yet, `createElement()` will be called
14244     automatically.
14245
14246     Note that this method just schedules the view to be appended; the DOM
14247     element will not be appended to the document body until all bindings have
14248     finished synchronizing.
14249
14250     @method append
14251     @return {Ember.View} receiver
14252   */
14253   append: function() {
14254     return this.appendTo(document.body);
14255   },
14256
14257   /**
14258     Removes the view's element from the element to which it is attached.
14259
14260     @method remove
14261     @return {Ember.View} receiver
14262   */
14263   remove: function() {
14264     // What we should really do here is wait until the end of the run loop
14265     // to determine if the element has been re-appended to a different
14266     // element.
14267     // In the interim, we will just re-render if that happens. It is more
14268     // important than elements get garbage collected.
14269     this.destroyElement();
14270     this.invokeRecursively(function(view) {
14271       view.clearRenderedChildren();
14272     });
14273   },
14274
14275   /**
14276     The ID to use when trying to locate the element in the DOM. If you do not
14277     set the elementId explicitly, then the view's GUID will be used instead.
14278     This ID must be set at the time the view is created.
14279
14280     @property elementId
14281     @type String
14282   */
14283   elementId: Ember.computed(function(key, value) {
14284     return value !== undefined ? value : Ember.guidFor(this);
14285   }),
14286
14287   // TODO: Perhaps this should be removed from the production build somehow.
14288   _elementIdDidChange: Ember.beforeObserver(function() {
14289     throw "Changing a view's elementId after creation is not allowed.";
14290   }, 'elementId'),
14291
14292   /**
14293     Attempts to discover the element in the parent element. The default
14294     implementation looks for an element with an ID of elementId (or the view's
14295     guid if elementId is null). You can override this method to provide your
14296     own form of lookup. For example, if you want to discover your element
14297     using a CSS class name instead of an ID.
14298
14299     @method findElementInParentElement
14300     @param {DOMElement} parentElement The parent's DOM element
14301     @return {DOMElement} The discovered element
14302   */
14303   findElementInParentElement: function(parentElem) {
14304     var id = "#" + get(this, 'elementId');
14305     return Ember.$(id)[0] || Ember.$(id, parentElem)[0];
14306   },
14307
14308   /**
14309     Creates a DOM representation of the view and all of its
14310     child views by recursively calling the `render()` method.
14311
14312     After the element has been created, `didInsertElement` will
14313     be called on this view and all of its child views.
14314
14315     @method createElement
14316     @return {Ember.View} receiver
14317   */
14318   createElement: function() {
14319     if (get(this, 'element')) { return this; }
14320
14321     var buffer = this.renderToBuffer();
14322     set(this, 'element', buffer.element());
14323
14324     return this;
14325   },
14326
14327   /**
14328     Called when a view is going to insert an element into the DOM.
14329
14330     @event willInsertElement
14331   */
14332   willInsertElement: Ember.K,
14333
14334   /**
14335     Called when the element of the view has been inserted into the DOM.
14336     Override this function to do any set up that requires an element in the
14337     document body.
14338
14339     @event didInsertElement
14340   */
14341   didInsertElement: Ember.K,
14342
14343   /**
14344     Called when the view is about to rerender, but before anything has
14345     been torn down. This is a good opportunity to tear down any manual
14346     observers you have installed based on the DOM state
14347
14348     @event willClearRender
14349   */
14350   willClearRender: Ember.K,
14351
14352   /**
14353     @private
14354
14355     Run this callback on the current view and recursively on child views.
14356
14357     @method invokeRecursively
14358     @param fn {Function}
14359   */
14360   invokeRecursively: function(fn) {
14361     fn.call(this, this);
14362
14363     this.forEachChildView(function(view) {
14364       view.invokeRecursively(fn);
14365     });
14366   },
14367
14368   /**
14369     Invalidates the cache for a property on all child views.
14370
14371     @method invalidateRecursively
14372   */
14373   invalidateRecursively: function(key) {
14374     this.forEachChildView(function(view) {
14375       view.propertyDidChange(key);
14376     });
14377   },
14378
14379   /**
14380     @private
14381
14382     Invokes the receiver's willInsertElement() method if it exists and then
14383     invokes the same on all child views.
14384
14385     NOTE: In some cases this was called when the element existed. This no longer
14386     works so we let people know. We can remove this warning code later.
14387
14388     @method _notifyWillInsertElement
14389   */
14390   _notifyWillInsertElement: function() {
14391     this.invokeRecursively(function(view) {
14392       view.trigger('willInsertElement');
14393     });
14394   },
14395
14396   /**
14397     @private
14398
14399     Invokes the receiver's didInsertElement() method if it exists and then
14400     invokes the same on all child views.
14401
14402     @method _notifyDidInsertElement
14403   */
14404   _notifyDidInsertElement: function() {
14405     this.invokeRecursively(function(view) {
14406       view.trigger('didInsertElement');
14407     });
14408   },
14409
14410   /**
14411     @private
14412
14413     Triggers the `willClearRender` event (which invokes the `willClearRender()`
14414     method if it exists) on this view and all child views.
14415
14416     @method _notifyWillClearRender
14417   */
14418   _notifyWillClearRender: function() {
14419     this.invokeRecursively(function(view) {
14420       view.trigger('willClearRender');
14421     });
14422   },
14423
14424   /**
14425     Destroys any existing element along with the element for any child views
14426     as well. If the view does not currently have a element, then this method
14427     will do nothing.
14428
14429     If you implement willDestroyElement() on your view, then this method will
14430     be invoked on your view before your element is destroyed to give you a
14431     chance to clean up any event handlers, etc.
14432
14433     If you write a willDestroyElement() handler, you can assume that your
14434     didInsertElement() handler was called earlier for the same element.
14435
14436     Normally you will not call or override this method yourself, but you may
14437     want to implement the above callbacks when it is run.
14438
14439     @method destroyElement
14440     @return {Ember.View} receiver
14441   */
14442   destroyElement: function() {
14443     return this.invokeForState('destroyElement');
14444   },
14445
14446   /**
14447     Called when the element of the view is going to be destroyed. Override
14448     this function to do any teardown that requires an element, like removing
14449     event listeners.
14450
14451     @event willDestroyElement
14452   */
14453   willDestroyElement: function() {},
14454
14455   /**
14456     @private
14457
14458     Triggers the `willDestroyElement` event (which invokes the `willDestroyElement()`
14459     method if it exists) on this view and all child views.
14460
14461     Before triggering `willDestroyElement`, it first triggers the `willClearRender`
14462     event recursively.
14463
14464     @method _notifyWillDestroyElement
14465   */
14466   _notifyWillDestroyElement: function() {
14467     this._notifyWillClearRender();
14468
14469     this.invokeRecursively(function(view) {
14470       view.trigger('willDestroyElement');
14471     });
14472   },
14473
14474   _elementWillChange: Ember.beforeObserver(function() {
14475     this.forEachChildView(function(view) {
14476       Ember.propertyWillChange(view, 'element');
14477     });
14478   }, 'element'),
14479
14480   /**
14481     @private
14482
14483     If this view's element changes, we need to invalidate the caches of our
14484     child views so that we do not retain references to DOM elements that are
14485     no longer needed.
14486
14487     @method _elementDidChange
14488   */
14489   _elementDidChange: Ember.observer(function() {
14490     this.forEachChildView(function(view) {
14491       Ember.propertyDidChange(view, 'element');
14492     });
14493   }, 'element'),
14494
14495   /**
14496     Called when the parentView property has changed.
14497
14498     @event parentViewDidChange
14499   */
14500   parentViewDidChange: Ember.K,
14501
14502   instrumentName: 'render.view',
14503
14504   instrumentDetails: function(hash) {
14505     hash.template = get(this, 'templateName');
14506     this._super(hash);
14507   },
14508
14509   _renderToBuffer: function(parentBuffer, bufferOperation) {
14510     this.lengthBeforeRender = this._childViews.length;
14511     var buffer = this._super(parentBuffer, bufferOperation);
14512     this.lengthAfterRender = this._childViews.length;
14513
14514     return buffer;
14515   },
14516
14517   renderToBufferIfNeeded: function () {
14518     return this.invokeForState('renderToBufferIfNeeded', this);
14519   },
14520
14521   beforeRender: function(buffer) {
14522     this.applyAttributesToBuffer(buffer);
14523   },
14524
14525   afterRender: Ember.K,
14526
14527   applyAttributesToBuffer: function(buffer) {
14528     // Creates observers for all registered class name and attribute bindings,
14529     // then adds them to the element.
14530     this._applyClassNameBindings();
14531
14532     // Pass the render buffer so the method can apply attributes directly.
14533     // This isn't needed for class name bindings because they use the
14534     // existing classNames infrastructure.
14535     this._applyAttributeBindings(buffer);
14536
14537
14538     a_forEach(get(this, 'classNames'), function(name){ buffer.addClass(name); });
14539     buffer.id(get(this, 'elementId'));
14540
14541     var role = get(this, 'ariaRole');
14542     if (role) {
14543       buffer.attr('role', role);
14544     }
14545
14546     if (get(this, 'isVisible') === false) {
14547       buffer.style('display', 'none');
14548     }
14549   },
14550
14551   // ..........................................................
14552   // STANDARD RENDER PROPERTIES
14553   //
14554
14555   /**
14556     Tag name for the view's outer element. The tag name is only used when
14557     an element is first created. If you change the tagName for an element, you
14558     must destroy and recreate the view element.
14559
14560     By default, the render buffer will use a `<div>` tag for views.
14561
14562     @property tagName
14563     @type String
14564     @default null
14565   */
14566
14567   // We leave this null by default so we can tell the difference between
14568   // the default case and a user-specified tag.
14569   tagName: null,
14570
14571   /**
14572     The WAI-ARIA role of the control represented by this view. For example, a
14573     button may have a role of type 'button', or a pane may have a role of
14574     type 'alertdialog'. This property is used by assistive software to help
14575     visually challenged users navigate rich web applications.
14576
14577     The full list of valid WAI-ARIA roles is available at:
14578     http://www.w3.org/TR/wai-aria/roles#roles_categorization
14579
14580     @property ariaRole
14581     @type String
14582     @default null
14583   */
14584   ariaRole: null,
14585
14586   /**
14587     Standard CSS class names to apply to the view's outer element. This
14588     property automatically inherits any class names defined by the view's
14589     superclasses as well.
14590
14591     @property classNames
14592     @type Array
14593     @default ['ember-view']
14594   */
14595   classNames: ['ember-view'],
14596
14597   /**
14598     A list of properties of the view to apply as class names. If the property
14599     is a string value, the value of that string will be applied as a class
14600     name.
14601
14602         // Applies the 'high' class to the view element
14603         Ember.View.create({
14604           classNameBindings: ['priority']
14605           priority: 'high'
14606         });
14607
14608     If the value of the property is a Boolean, the name of that property is
14609     added as a dasherized class name.
14610
14611         // Applies the 'is-urgent' class to the view element
14612         Ember.View.create({
14613           classNameBindings: ['isUrgent']
14614           isUrgent: true
14615         });
14616
14617     If you would prefer to use a custom value instead of the dasherized
14618     property name, you can pass a binding like this:
14619
14620         // Applies the 'urgent' class to the view element
14621         Ember.View.create({
14622           classNameBindings: ['isUrgent:urgent']
14623           isUrgent: true
14624         });
14625
14626     This list of properties is inherited from the view's superclasses as well.
14627
14628     @property classNameBindings
14629     @type Array
14630     @default []
14631   */
14632   classNameBindings: [],
14633
14634   /**
14635     A list of properties of the view to apply as attributes. If the property is
14636     a string value, the value of that string will be applied as the attribute.
14637
14638         // Applies the type attribute to the element
14639         // with the value "button", like <div type="button">
14640         Ember.View.create({
14641           attributeBindings: ['type'],
14642           type: 'button'
14643         });
14644
14645     If the value of the property is a Boolean, the name of that property is
14646     added as an attribute.
14647
14648         // Renders something like <div enabled="enabled">
14649         Ember.View.create({
14650           attributeBindings: ['enabled'],
14651           enabled: true
14652         });
14653
14654     @property attributeBindings
14655   */
14656   attributeBindings: [],
14657
14658   // .......................................................
14659   // CORE DISPLAY METHODS
14660   //
14661
14662   /**
14663     @private
14664
14665     Setup a view, but do not finish waking it up.
14666     - configure childViews
14667     - register the view with the global views hash, which is used for event
14668       dispatch
14669
14670     @method init
14671   */
14672   init: function() {
14673     this._super();
14674
14675     // setup child views. be sure to clone the child views array first
14676     this._childViews = this._childViews.slice();
14677
14678     Ember.assert("Only arrays are allowed for 'classNameBindings'", Ember.typeOf(this.classNameBindings) === 'array');
14679     this.classNameBindings = Ember.A(this.classNameBindings.slice());
14680
14681     Ember.assert("Only arrays are allowed for 'classNames'", Ember.typeOf(this.classNames) === 'array');
14682     this.classNames = Ember.A(this.classNames.slice());
14683
14684     var viewController = get(this, 'viewController');
14685     if (viewController) {
14686       viewController = get(viewController);
14687       if (viewController) {
14688         set(viewController, 'view', this);
14689       }
14690     }
14691   },
14692
14693   appendChild: function(view, options) {
14694     return this.invokeForState('appendChild', view, options);
14695   },
14696
14697   /**
14698     Removes the child view from the parent view.
14699
14700     @method removeChild
14701     @param {Ember.View} view
14702     @return {Ember.View} receiver
14703   */
14704   removeChild: function(view) {
14705     // If we're destroying, the entire subtree will be
14706     // freed, and the DOM will be handled separately,
14707     // so no need to mess with childViews.
14708     if (this.isDestroying) { return; }
14709
14710     // update parent node
14711     set(view, '_parentView', null);
14712
14713     // remove view from childViews array.
14714     var childViews = this._childViews;
14715
14716     Ember.EnumerableUtils.removeObject(childViews, view);
14717
14718     this.propertyDidChange('childViews'); // HUH?! what happened to will change?
14719
14720     return this;
14721   },
14722
14723   /**
14724     Removes all children from the parentView.
14725
14726     @method removeAllChildren
14727     @return {Ember.View} receiver
14728   */
14729   removeAllChildren: function() {
14730     return this.mutateChildViews(function(view) {
14731       this.removeChild(view);
14732     });
14733   },
14734
14735   destroyAllChildren: function() {
14736     return this.mutateChildViews(function(view) {
14737       view.destroy();
14738     });
14739   },
14740
14741   /**
14742     Removes the view from its parentView, if one is found. Otherwise
14743     does nothing.
14744
14745     @method removeFromParent
14746     @return {Ember.View} receiver
14747   */
14748   removeFromParent: function() {
14749     var parent = get(this, '_parentView');
14750
14751     // Remove DOM element from parent
14752     this.remove();
14753
14754     if (parent) { parent.removeChild(this); }
14755     return this;
14756   },
14757
14758   /**
14759     You must call `destroy` on a view to destroy the view (and all of its
14760     child views). This will remove the view from any parent node, then make
14761     sure that the DOM element managed by the view can be released by the
14762     memory manager.
14763
14764     @method willDestroy
14765   */
14766   willDestroy: function() {
14767     // calling this._super() will nuke computed properties and observers,
14768     // so collect any information we need before calling super.
14769     var childViews = this._childViews,
14770         parent     = get(this, '_parentView'),
14771         childLen;
14772
14773     // destroy the element -- this will avoid each child view destroying
14774     // the element over and over again...
14775     if (!this.removedFromDOM) { this.destroyElement(); }
14776
14777     // remove from non-virtual parent view if viewName was specified
14778     if (this.viewName) {
14779       var nonVirtualParentView = get(this, 'parentView');
14780       if (nonVirtualParentView) {
14781         set(nonVirtualParentView, this.viewName, null);
14782       }
14783     }
14784
14785     // remove from parent if found. Don't call removeFromParent,
14786     // as removeFromParent will try to remove the element from
14787     // the DOM again.
14788     if (parent) { parent.removeChild(this); }
14789
14790     this.state = 'destroyed';
14791
14792     childLen = childViews.length;
14793     for (var i=childLen-1; i>=0; i--) {
14794       childViews[i].removedFromDOM = true;
14795       childViews[i].destroy();
14796     }
14797
14798     // next remove view from global hash
14799     if (!this.isVirtual) delete Ember.View.views[get(this, 'elementId')];
14800   },
14801
14802   /**
14803     Instantiates a view to be added to the childViews array during view
14804     initialization. You generally will not call this method directly unless
14805     you are overriding createChildViews(). Note that this method will
14806     automatically configure the correct settings on the new view instance to
14807     act as a child of the parent.
14808
14809     @method createChildView
14810     @param {Class} viewClass
14811     @param {Hash} [attrs] Attributes to add
14812     @return {Ember.View} new instance
14813   */
14814   createChildView: function(view, attrs) {
14815     if (Ember.CoreView.detect(view)) {
14816       attrs = attrs || {};
14817       attrs._parentView = this;
14818       attrs.templateData = attrs.templateData || get(this, 'templateData');
14819
14820       view = view.create(attrs);
14821
14822       // don't set the property on a virtual view, as they are invisible to
14823       // consumers of the view API
14824       if (view.viewName) { set(get(this, 'concreteView'), view.viewName, view); }
14825     } else {
14826       Ember.assert('You must pass instance or subclass of View', view instanceof Ember.CoreView);
14827       Ember.assert("You can only pass attributes when a class is provided", !attrs);
14828
14829       if (!get(view, 'templateData')) {
14830         set(view, 'templateData', get(this, 'templateData'));
14831       }
14832
14833       set(view, '_parentView', this);
14834     }
14835
14836     return view;
14837   },
14838
14839   becameVisible: Ember.K,
14840   becameHidden: Ember.K,
14841
14842   /**
14843     @private
14844
14845     When the view's `isVisible` property changes, toggle the visibility
14846     element of the actual DOM element.
14847
14848     @method _isVisibleDidChange
14849   */
14850   _isVisibleDidChange: Ember.observer(function() {
14851     var $el = this.$();
14852     if (!$el) { return; }
14853
14854     var isVisible = get(this, 'isVisible');
14855
14856     $el.toggle(isVisible);
14857
14858     if (this._isAncestorHidden()) { return; }
14859
14860     if (isVisible) {
14861       this._notifyBecameVisible();
14862     } else {
14863       this._notifyBecameHidden();
14864     }
14865   }, 'isVisible'),
14866
14867   _notifyBecameVisible: function() {
14868     this.trigger('becameVisible');
14869
14870     this.forEachChildView(function(view) {
14871       var isVisible = get(view, 'isVisible');
14872
14873       if (isVisible || isVisible === null) {
14874         view._notifyBecameVisible();
14875       }
14876     });
14877   },
14878
14879   _notifyBecameHidden: function() {
14880     this.trigger('becameHidden');
14881     this.forEachChildView(function(view) {
14882       var isVisible = get(view, 'isVisible');
14883
14884       if (isVisible || isVisible === null) {
14885         view._notifyBecameHidden();
14886       }
14887     });
14888   },
14889
14890   _isAncestorHidden: function() {
14891     var parent = get(this, 'parentView');
14892
14893     while (parent) {
14894       if (get(parent, 'isVisible') === false) { return true; }
14895
14896       parent = get(parent, 'parentView');
14897     }
14898
14899     return false;
14900   },
14901
14902   clearBuffer: function() {
14903     this.invokeRecursively(function(view) {
14904       this.buffer = null;
14905     });
14906   },
14907
14908   transitionTo: function(state, children) {
14909     this.state = state;
14910
14911     if (children !== false) {
14912       this.forEachChildView(function(view) {
14913         view.transitionTo(state);
14914       });
14915     }
14916   },
14917
14918   // .......................................................
14919   // EVENT HANDLING
14920   //
14921
14922   /**
14923     @private
14924
14925     Handle events from `Ember.EventDispatcher`
14926
14927     @method handleEvent
14928     @param eventName {String}
14929     @param evt {Event}
14930   */
14931   handleEvent: function(eventName, evt) {
14932     return this.invokeForState('handleEvent', eventName, evt);
14933   }
14934
14935 });
14936
14937 /*
14938   Describe how the specified actions should behave in the various
14939   states that a view can exist in. Possible states:
14940
14941   * preRender: when a view is first instantiated, and after its
14942     element was destroyed, it is in the preRender state
14943   * inBuffer: once a view has been rendered, but before it has
14944     been inserted into the DOM, it is in the inBuffer state
14945   * inDOM: once a view has been inserted into the DOM it is in
14946     the inDOM state. A view spends the vast majority of its
14947     existence in this state.
14948   * destroyed: once a view has been destroyed (using the destroy
14949     method), it is in this state. No further actions can be invoked
14950     on a destroyed view.
14951 */
14952
14953   // in the destroyed state, everything is illegal
14954
14955   // before rendering has begun, all legal manipulations are noops.
14956
14957   // inside the buffer, legal manipulations are done on the buffer
14958
14959   // once the view has been inserted into the DOM, legal manipulations
14960   // are done on the DOM element.
14961
14962 var DOMManager = {
14963   prepend: function(view, html) {
14964     view.$().prepend(html);
14965   },
14966
14967   after: function(view, html) {
14968     view.$().after(html);
14969   },
14970
14971   html: function(view, html) {
14972     view.$().html(html);
14973   },
14974
14975   replace: function(view) {
14976     var element = get(view, 'element');
14977
14978     set(view, 'element', null);
14979
14980     view._insertElementLater(function() {
14981       Ember.$(element).replaceWith(get(view, 'element'));
14982     });
14983   },
14984
14985   remove: function(view) {
14986     view.$().remove();
14987   },
14988
14989   empty: function(view) {
14990     view.$().empty();
14991   }
14992 };
14993
14994 Ember.View.reopen({
14995   states: Ember.View.states,
14996   domManager: DOMManager
14997 });
14998
14999 Ember.View.reopenClass({
15000
15001   /**
15002     @private
15003
15004     Parse a path and return an object which holds the parsed properties.
15005
15006     For example a path like "content.isEnabled:enabled:disabled" wil return the
15007     following object:
15008
15009         {
15010           path: "content.isEnabled",
15011           className: "enabled",
15012           falsyClassName: "disabled",
15013           classNames: ":enabled:disabled"
15014         }
15015
15016     @method _parsePropertyPath
15017     @static
15018   */
15019   _parsePropertyPath: function(path) {
15020     var split = path.split(':'),
15021         propertyPath = split[0],
15022         classNames = "",
15023         className,
15024         falsyClassName;
15025
15026     // check if the property is defined as prop:class or prop:trueClass:falseClass
15027     if (split.length > 1) {
15028       className = split[1];
15029       if (split.length === 3) { falsyClassName = split[2]; }
15030
15031       classNames = ':' + className;
15032       if (falsyClassName) { classNames += ":" + falsyClassName; }
15033     }
15034
15035     return {
15036       path: propertyPath,
15037       classNames: classNames,
15038       className: (className === '') ? undefined : className,
15039       falsyClassName: falsyClassName
15040     };
15041   },
15042
15043   /**
15044     @private
15045
15046     Get the class name for a given value, based on the path, optional className
15047     and optional falsyClassName.
15048
15049     - if a className or falsyClassName has been specified:
15050       - if the value is truthy and className has been specified, className is returned
15051       - if the value is falsy and falsyClassName has been specified, falsyClassName is returned
15052       - otherwise null is returned
15053     - if the value is true, the dasherized last part of the supplied path is returned
15054     - if the value is not false, undefined or null, the value is returned
15055     - if none of the above rules apply, null is returned
15056
15057     @method _classStringForValue
15058     @param path
15059     @param val
15060     @param className
15061     @param falsyClassName
15062     @static
15063   */
15064   _classStringForValue: function(path, val, className, falsyClassName) {
15065     // When using the colon syntax, evaluate the truthiness or falsiness
15066     // of the value to determine which className to return
15067     if (className || falsyClassName) {
15068       if (className && !!val) {
15069         return className;
15070
15071       } else if (falsyClassName && !val) {
15072         return falsyClassName;
15073
15074       } else {
15075         return null;
15076       }
15077
15078     // If value is a Boolean and true, return the dasherized property
15079     // name.
15080     } else if (val === true) {
15081       // Normalize property path to be suitable for use
15082       // as a class name. For exaple, content.foo.barBaz
15083       // becomes bar-baz.
15084       var parts = path.split('.');
15085       return Ember.String.dasherize(parts[parts.length-1]);
15086
15087     // If the value is not false, undefined, or null, return the current
15088     // value of the property.
15089     } else if (val !== false && val !== undefined && val !== null) {
15090       return val;
15091
15092     // Nothing to display. Return null so that the old class is removed
15093     // but no new class is added.
15094     } else {
15095       return null;
15096     }
15097   }
15098 });
15099
15100 /**
15101   Global views hash
15102
15103   @property views
15104   @static
15105   @type Hash
15106 */
15107 Ember.View.views = {};
15108
15109 // If someone overrides the child views computed property when
15110 // defining their class, we want to be able to process the user's
15111 // supplied childViews and then restore the original computed property
15112 // at view initialization time. This happens in Ember.ContainerView's init
15113 // method.
15114 Ember.View.childViewsProperty = childViewsProperty;
15115
15116 Ember.View.applyAttributeBindings = function(elem, name, value) {
15117   var type = Ember.typeOf(value);
15118   var currentValue = elem.attr(name);
15119
15120   // if this changes, also change the logic in ember-handlebars/lib/helpers/binding.js
15121   if ((type === 'string' || (type === 'number' && !isNaN(value))) && value !== currentValue) {
15122     elem.attr(name, value);
15123   } else if (value && type === 'boolean') {
15124     elem.attr(name, name);
15125   } else if (!value) {
15126     elem.removeAttr(name);
15127   }
15128 };
15129
15130 })();
15131
15132
15133
15134 (function() {
15135 /**
15136 @module ember
15137 @submodule ember-views
15138 */
15139
15140 var get = Ember.get, set = Ember.set;
15141
15142 Ember.View.states = {
15143   _default: {
15144     // appendChild is only legal while rendering the buffer.
15145     appendChild: function() {
15146       throw "You can't use appendChild outside of the rendering process";
15147     },
15148
15149     $: function() {
15150       return undefined;
15151     },
15152
15153     getElement: function() {
15154       return null;
15155     },
15156
15157     // Handle events from `Ember.EventDispatcher`
15158     handleEvent: function() {
15159       return true; // continue event propagation
15160     },
15161
15162     destroyElement: function(view) {
15163       set(view, 'element', null);
15164       if (view._scheduledInsert) {
15165         Ember.run.cancel(view._scheduledInsert);
15166         view._scheduledInsert = null;
15167       }
15168       return view;
15169     },
15170
15171     renderToBufferIfNeeded: function () {
15172       return false;
15173     }
15174   }
15175 };
15176
15177 Ember.View.reopen({
15178   states: Ember.View.states
15179 });
15180
15181 })();
15182
15183
15184
15185 (function() {
15186 /**
15187 @module ember
15188 @submodule ember-views
15189 */
15190
15191 Ember.View.states.preRender = {
15192   parentState: Ember.View.states._default,
15193
15194   // a view leaves the preRender state once its element has been
15195   // created (createElement).
15196   insertElement: function(view, fn) {
15197     view.createElement();
15198     view._notifyWillInsertElement();
15199     // after createElement, the view will be in the hasElement state.
15200     fn.call(view);
15201     view.transitionTo('inDOM');
15202     view._notifyDidInsertElement();
15203   },
15204
15205   renderToBufferIfNeeded: function(view) {
15206     return view.renderToBuffer();
15207   },
15208
15209   empty: Ember.K,
15210
15211   setElement: function(view, value) {
15212     if (value !== null) {
15213       view.transitionTo('hasElement');
15214     }
15215     return value;
15216   }
15217 };
15218
15219 })();
15220
15221
15222
15223 (function() {
15224 /**
15225 @module ember
15226 @submodule ember-views
15227 */
15228
15229 var get = Ember.get, set = Ember.set, meta = Ember.meta;
15230
15231 Ember.View.states.inBuffer = {
15232   parentState: Ember.View.states._default,
15233
15234   $: function(view, sel) {
15235     // if we don't have an element yet, someone calling this.$() is
15236     // trying to update an element that isn't in the DOM. Instead,
15237     // rerender the view to allow the render method to reflect the
15238     // changes.
15239     view.rerender();
15240     return Ember.$();
15241   },
15242
15243   // when a view is rendered in a buffer, rerendering it simply
15244   // replaces the existing buffer with a new one
15245   rerender: function(view) {
15246     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.");
15247
15248     view._notifyWillClearRender();
15249
15250     view.clearRenderedChildren();
15251     view.renderToBuffer(view.buffer, 'replaceWith');
15252   },
15253
15254   // when a view is rendered in a buffer, appending a child
15255   // view will render that view and append the resulting
15256   // buffer into its buffer.
15257   appendChild: function(view, childView, options) {
15258     var buffer = view.buffer;
15259
15260     childView = this.createChildView(childView, options);
15261     view._childViews.push(childView);
15262
15263     childView.renderToBuffer(buffer);
15264
15265     view.propertyDidChange('childViews');
15266
15267     return childView;
15268   },
15269
15270   // when a view is rendered in a buffer, destroying the
15271   // element will simply destroy the buffer and put the
15272   // state back into the preRender state.
15273   destroyElement: function(view) {
15274     view.clearBuffer();
15275     view._notifyWillDestroyElement();
15276     view.transitionTo('preRender');
15277
15278     return view;
15279   },
15280
15281   empty: function() {
15282     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.");
15283   },
15284
15285   renderToBufferIfNeeded: function (view) {
15286     return view.buffer;
15287   },
15288
15289   // It should be impossible for a rendered view to be scheduled for
15290   // insertion.
15291   insertElement: function() {
15292     throw "You can't insert an element that has already been rendered";
15293   },
15294
15295   setElement: function(view, value) {
15296     if (value === null) {
15297       view.transitionTo('preRender');
15298     } else {
15299       view.clearBuffer();
15300       view.transitionTo('hasElement');
15301     }
15302
15303     return value;
15304   }
15305 };
15306
15307
15308 })();
15309
15310
15311
15312 (function() {
15313 /**
15314 @module ember
15315 @submodule ember-views
15316 */
15317
15318 var get = Ember.get, set = Ember.set, meta = Ember.meta;
15319
15320 Ember.View.states.hasElement = {
15321   parentState: Ember.View.states._default,
15322
15323   $: function(view, sel) {
15324     var elem = get(view, 'element');
15325     return sel ? Ember.$(sel, elem) : Ember.$(elem);
15326   },
15327
15328   getElement: function(view) {
15329     var parent = get(view, 'parentView');
15330     if (parent) { parent = get(parent, 'element'); }
15331     if (parent) { return view.findElementInParentElement(parent); }
15332     return Ember.$("#" + get(view, 'elementId'))[0];
15333   },
15334
15335   setElement: function(view, value) {
15336     if (value === null) {
15337       view.transitionTo('preRender');
15338     } else {
15339       throw "You cannot set an element to a non-null value when the element is already in the DOM.";
15340     }
15341
15342     return value;
15343   },
15344
15345   // once the view has been inserted into the DOM, rerendering is
15346   // deferred to allow bindings to synchronize.
15347   rerender: function(view) {
15348     view._notifyWillClearRender();
15349
15350     view.clearRenderedChildren();
15351
15352     view.domManager.replace(view);
15353     return view;
15354   },
15355
15356   // once the view is already in the DOM, destroying it removes it
15357   // from the DOM, nukes its element, and puts it back into the
15358   // preRender state if inDOM.
15359
15360   destroyElement: function(view) {
15361     view._notifyWillDestroyElement();
15362     view.domManager.remove(view);
15363     set(view, 'element', null);
15364     if (view._scheduledInsert) {
15365       Ember.run.cancel(view._scheduledInsert);
15366       view._scheduledInsert = null;
15367     }
15368     return view;
15369   },
15370
15371   empty: function(view) {
15372     var _childViews = view._childViews, len, idx;
15373     if (_childViews) {
15374       len = _childViews.length;
15375       for (idx = 0; idx < len; idx++) {
15376         _childViews[idx]._notifyWillDestroyElement();
15377       }
15378     }
15379     view.domManager.empty(view);
15380   },
15381
15382   // Handle events from `Ember.EventDispatcher`
15383   handleEvent: function(view, eventName, evt) {
15384     if (view.has(eventName)) {
15385       // Handler should be able to re-dispatch events, so we don't
15386       // preventDefault or stopPropagation.
15387       return view.trigger(eventName, evt);
15388     } else {
15389       return true; // continue event propagation
15390     }
15391   }
15392 };
15393
15394 Ember.View.states.inDOM = {
15395   parentState: Ember.View.states.hasElement,
15396
15397   insertElement: function(view, fn) {
15398     throw "You can't insert an element into the DOM that has already been inserted";
15399   }
15400 };
15401
15402 })();
15403
15404
15405
15406 (function() {
15407 /**
15408 @module ember
15409 @submodule ember-views
15410 */
15411
15412 var destroyedError = "You can't call %@ on a destroyed view", fmt = Ember.String.fmt;
15413
15414 Ember.View.states.destroyed = {
15415   parentState: Ember.View.states._default,
15416
15417   appendChild: function() {
15418     throw fmt(destroyedError, ['appendChild']);
15419   },
15420   rerender: function() {
15421     throw fmt(destroyedError, ['rerender']);
15422   },
15423   destroyElement: function() {
15424     throw fmt(destroyedError, ['destroyElement']);
15425   },
15426   empty: function() {
15427     throw fmt(destroyedError, ['empty']);
15428   },
15429
15430   setElement: function() {
15431     throw fmt(destroyedError, ["set('element', ...)"]);
15432   },
15433
15434   renderToBufferIfNeeded: function() {
15435     throw fmt(destroyedError, ["renderToBufferIfNeeded"]);
15436   },
15437
15438   // Since element insertion is scheduled, don't do anything if
15439   // the view has been destroyed between scheduling and execution
15440   insertElement: Ember.K
15441 };
15442
15443
15444 })();
15445
15446
15447
15448 (function() {
15449
15450 })();
15451
15452
15453
15454 (function() {
15455 /**
15456 @module ember
15457 @submodule ember-views
15458 */
15459
15460 var get = Ember.get, set = Ember.set, meta = Ember.meta;
15461 var forEach = Ember.EnumerableUtils.forEach;
15462
15463 var childViewsProperty = Ember.computed(function() {
15464   return get(this, '_childViews');
15465 }).property('_childViews');
15466
15467 /**
15468   A `ContainerView` is an `Ember.View` subclass that allows for manual or programatic
15469   management of a view's `childViews` array that will correctly update the `ContainerView`
15470   instance's rendered DOM representation.
15471
15472   ## Setting Initial Child Views
15473   The initial array of child views can be set in one of two ways. You can provide
15474   a `childViews` property at creation time that contains instance of `Ember.View`:
15475
15476   ``` javascript
15477   aContainer = Ember.ContainerView.create({
15478     childViews: [Ember.View.create(), Ember.View.create()]
15479   });
15480   ```
15481
15482   You can also provide a list of property names whose values are instances of `Ember.View`:
15483
15484   ``` javascript
15485   aContainer = Ember.ContainerView.create({
15486     childViews: ['aView', 'bView', 'cView'],
15487     aView: Ember.View.create(),
15488     bView: Ember.View.create()
15489     cView: Ember.View.create()
15490   });
15491   ```
15492
15493   The two strategies can be combined:
15494
15495   ``` javascript
15496   aContainer = Ember.ContainerView.create({
15497     childViews: ['aView', Ember.View.create()],
15498     aView: Ember.View.create()
15499   });
15500   ```
15501
15502   Each child view's rendering will be inserted into the container's rendered HTML in the same
15503   order as its position in the `childViews` property.
15504
15505   ## Adding and Removing Child Views
15506   The views in a container's `childViews` array should be added and removed by manipulating
15507   the `childViews` property directly.
15508
15509   To remove a view pass that view into a `removeObject` call on the container's `childViews` property.
15510
15511   Given an empty `<body>` the following code
15512
15513   ``` javascript
15514   aContainer = Ember.ContainerView.create({
15515     classNames: ['the-container'],
15516     childViews: ['aView', 'bView'],
15517     aView: Ember.View.create({
15518       template: Ember.Handlebars.compile("A")
15519     }),
15520     bView: Ember.View.create({
15521       template: Ember.Handlebars.compile("B")
15522     })
15523   });
15524
15525   aContainer.appendTo('body');
15526   ``` 
15527
15528   Results in the HTML
15529
15530   ``` html
15531   <div class="ember-view the-container">
15532     <div class="ember-view">A</div>
15533     <div class="ember-view">B</div>
15534   </div>
15535   ```
15536
15537   Removing a view
15538
15539   ``` javascript
15540   aContainer.get('childViews'); // [aContainer.aView, aContainer.bView]
15541   aContainer.get('childViews').removeObject(aContainer.get('bView'));
15542   aContainer.get('childViews'); // [aContainer.aView]
15543   ```
15544
15545   Will result in the following HTML
15546
15547   ``` html
15548   <div class="ember-view the-container">
15549     <div class="ember-view">A</div>
15550   </div>
15551   ```
15552
15553
15554   Similarly, adding a child view is accomplished by adding `Ember.View` instances to the
15555   container's `childViews` property.
15556
15557   Given an empty `<body>` the following code
15558
15559   ``` javascript
15560   aContainer = Ember.ContainerView.create({
15561     classNames: ['the-container'],
15562     childViews: ['aView', 'bView'],
15563     aView: Ember.View.create({
15564       template: Ember.Handlebars.compile("A")
15565     }),
15566     bView: Ember.View.create({
15567       template: Ember.Handlebars.compile("B")
15568     })
15569   });
15570
15571   aContainer.appendTo('body');
15572   ```
15573
15574   Results in the HTML
15575
15576   ``` html
15577   <div class="ember-view the-container">
15578     <div class="ember-view">A</div>
15579     <div class="ember-view">B</div>
15580   </div>
15581   ```
15582
15583   Adding a view
15584
15585   ``` javascript
15586   AnotherViewClass = Ember.View.extend({
15587     template: Ember.Handlebars.compile("Another view")
15588   });
15589
15590   aContainer.get('childViews'); // [aContainer.aView, aContainer.bView]
15591   aContainer.get('childViews').pushObject(AnotherViewClass.create());
15592   aContainer.get('childViews'); // [aContainer.aView, aContainer.bView, <AnotherViewClass instance>]
15593   ```
15594
15595   Will result in the following HTML
15596
15597   ``` html
15598   <div class="ember-view the-container">
15599     <div class="ember-view">A</div>
15600     <div class="ember-view">B</div>
15601     <div class="ember-view">Another view</div>
15602   </div>
15603   ```
15604
15605
15606   Direct manipulation of childViews presence or absence in the DOM via calls to
15607   `remove` or `removeFromParent` or calls to a container's `removeChild` may not behave
15608   correctly.
15609
15610   Calling `remove()` on a child view will remove the view's HTML, but it will remain as part of its
15611   container's `childView`s property.
15612
15613   Calling `removeChild()` on the container will remove the passed view instance from the container's
15614   `childView`s but keep its HTML within the container's rendered view.
15615
15616   Calling `removeFromParent()` behaves as expected but should be avoided in favor of direct
15617   manipulation of a container's `childViews` property.
15618
15619   ``` javascript
15620   aContainer = Ember.ContainerView.create({
15621     classNames: ['the-container'],
15622     childViews: ['aView', 'bView'],
15623     aView: Ember.View.create({
15624       template: Ember.Handlebars.compile("A")
15625     }),
15626     bView: Ember.View.create({
15627       template: Ember.Handlebars.compile("B")
15628     })
15629   });
15630
15631   aContainer.appendTo('body');
15632   ```
15633
15634   Results in the HTML
15635
15636   ``` html
15637   <div class="ember-view the-container">
15638     <div class="ember-view">A</div>
15639     <div class="ember-view">B</div>
15640   </div>
15641   ```
15642
15643   Calling `aContainer.get('aView').removeFromParent()` will result in the following HTML
15644
15645   ``` html
15646   <div class="ember-view the-container">
15647     <div class="ember-view">B</div>
15648   </div>
15649   ```
15650
15651   And the `Ember.View` instance stored in `aContainer.aView` will be removed from `aContainer`'s
15652   `childViews` array.
15653
15654   ## Templates and Layout
15655
15656   A `template`, `templateName`, `defaultTemplate`, `layout`, `layoutName` or `defaultLayout`
15657   property on a container view will not result in the template or layout being rendered.
15658   The HTML contents of a `Ember.ContainerView`'s DOM representation will only be the rendered HTML
15659   of its child views.
15660
15661   ## Binding a View to Display
15662
15663   If you would like to display a single view in your ContainerView, you can set its `currentView`
15664   property. When the `currentView` property is set to a view instance, it will be added to the
15665   ContainerView's `childViews` array. If the `currentView` property is later changed to a
15666   different view, the new view will replace the old view. If `currentView` is set to `null`, the
15667   last `currentView` will be removed.
15668
15669   This functionality is useful for cases where you want to bind the display of a ContainerView to
15670   a controller or state manager. For example, you can bind the `currentView` of a container to
15671   a controller like this:
15672
15673   ``` javascript
15674   App.appController = Ember.Object.create({
15675     view: Ember.View.create({
15676       templateName: 'person_template'
15677     })
15678   });
15679   ```
15680
15681   ``` handlebars
15682   {{view Ember.ContainerView currentViewBinding="App.appController.view"}}
15683   ```
15684
15685   @class ContainerView
15686   @namespace Ember
15687   @extends Ember.View
15688 */
15689
15690 Ember.ContainerView = Ember.View.extend({
15691
15692   init: function() {
15693     this._super();
15694
15695     var childViews = get(this, 'childViews');
15696     Ember.defineProperty(this, 'childViews', childViewsProperty);
15697
15698     var _childViews = this._childViews;
15699
15700     forEach(childViews, function(viewName, idx) {
15701       var view;
15702
15703       if ('string' === typeof viewName) {
15704         view = get(this, viewName);
15705         view = this.createChildView(view);
15706         set(this, viewName, view);
15707       } else {
15708         view = this.createChildView(viewName);
15709       }
15710
15711       _childViews[idx] = view;
15712     }, this);
15713
15714     var currentView = get(this, 'currentView');
15715     if (currentView) _childViews.push(this.createChildView(currentView));
15716
15717     // Make the _childViews array observable
15718     Ember.A(_childViews);
15719
15720     // Sets up an array observer on the child views array. This
15721     // observer will detect when child views are added or removed
15722     // and update the DOM to reflect the mutation.
15723     get(this, 'childViews').addArrayObserver(this, {
15724       willChange: 'childViewsWillChange',
15725       didChange: 'childViewsDidChange'
15726     });
15727   },
15728
15729   /**
15730     @private
15731
15732     Instructs each child view to render to the passed render buffer.
15733
15734     @method render
15735     @param {Ember.RenderBuffer} buffer the buffer to render to
15736   */
15737   render: function(buffer) {
15738     this.forEachChildView(function(view) {
15739       view.renderToBuffer(buffer);
15740     });
15741   },
15742
15743   instrumentName: 'render.container',
15744
15745   /**
15746     @private
15747
15748     When the container view is destroyed, tear down the child views
15749     array observer.
15750
15751     @method willDestroy
15752   */
15753   willDestroy: function() {
15754     get(this, 'childViews').removeArrayObserver(this, {
15755       willChange: 'childViewsWillChange',
15756       didChange: 'childViewsDidChange'
15757     });
15758
15759     this._super();
15760   },
15761
15762   /**
15763     @private
15764
15765     When a child view is removed, destroy its element so that
15766     it is removed from the DOM.
15767
15768     The array observer that triggers this action is set up in the
15769     `renderToBuffer` method.
15770
15771     @method childViewsWillChange
15772     @param {Ember.Array} views the child views array before mutation
15773     @param {Number} start the start position of the mutation
15774     @param {Number} removed the number of child views removed
15775   **/
15776   childViewsWillChange: function(views, start, removed) {
15777     if (removed === 0) { return; }
15778
15779     var changedViews = views.slice(start, start+removed);
15780     this.initializeViews(changedViews, null, null);
15781
15782     this.invokeForState('childViewsWillChange', views, start, removed);
15783   },
15784
15785   /**
15786     @private
15787
15788     When a child view is added, make sure the DOM gets updated appropriately.
15789
15790     If the view has already rendered an element, we tell the child view to
15791     create an element and insert it into the DOM. If the enclosing container view
15792     has already written to a buffer, but not yet converted that buffer into an
15793     element, we insert the string representation of the child into the appropriate
15794     place in the buffer.
15795
15796     @method childViewsDidChange
15797     @param {Ember.Array} views the array of child views afte the mutation has occurred
15798     @param {Number} start the start position of the mutation
15799     @param {Number} removed the number of child views removed
15800     @param {Number} the number of child views added
15801   */
15802   childViewsDidChange: function(views, start, removed, added) {
15803     var len = get(views, 'length');
15804
15805     // No new child views were added; bail out.
15806     if (added === 0) return;
15807
15808     var changedViews = views.slice(start, start+added);
15809     this.initializeViews(changedViews, this, get(this, 'templateData'));
15810
15811     // Let the current state handle the changes
15812     this.invokeForState('childViewsDidChange', views, start, added);
15813   },
15814
15815   initializeViews: function(views, parentView, templateData) {
15816     forEach(views, function(view) {
15817       set(view, '_parentView', parentView);
15818
15819       if (!get(view, 'templateData')) {
15820         set(view, 'templateData', templateData);
15821       }
15822     });
15823   },
15824
15825   currentView: null,
15826
15827   _currentViewWillChange: Ember.beforeObserver(function() {
15828     var childViews = get(this, 'childViews'),
15829         currentView = get(this, 'currentView');
15830
15831     if (currentView) {
15832       childViews.removeObject(currentView);
15833       currentView.destroy();
15834     }
15835   }, 'currentView'),
15836
15837   _currentViewDidChange: Ember.observer(function() {
15838     var childViews = get(this, 'childViews'),
15839         currentView = get(this, 'currentView');
15840
15841     if (currentView) {
15842       childViews.pushObject(currentView);
15843     }
15844   }, 'currentView'),
15845
15846   _ensureChildrenAreInDOM: function () {
15847     this.invokeForState('ensureChildrenAreInDOM', this);
15848   }
15849 });
15850
15851 // Ember.ContainerView extends the default view states to provide different
15852 // behavior for childViewsWillChange and childViewsDidChange.
15853 Ember.ContainerView.states = {
15854   parent: Ember.View.states,
15855
15856   inBuffer: {
15857     childViewsDidChange: function(parentView, views, start, added) {
15858       var buffer = parentView.buffer,
15859           startWith, prev, prevBuffer, view;
15860
15861       // Determine where to begin inserting the child view(s) in the
15862       // render buffer.
15863       if (start === 0) {
15864         // If views were inserted at the beginning, prepend the first
15865         // view to the render buffer, then begin inserting any
15866         // additional views at the beginning.
15867         view = views[start];
15868         startWith = start + 1;
15869         view.renderToBuffer(buffer, 'prepend');
15870       } else {
15871         // Otherwise, just insert them at the same place as the child
15872         // views mutation.
15873         view = views[start - 1];
15874         startWith = start;
15875       }
15876
15877       for (var i=startWith; i<start+added; i++) {
15878         prev = view;
15879         view = views[i];
15880         prevBuffer = prev.buffer;
15881         view.renderToBuffer(prevBuffer, 'insertAfter');
15882       }
15883     }
15884   },
15885
15886   hasElement: {
15887     childViewsWillChange: function(view, views, start, removed) {
15888       for (var i=start; i<start+removed; i++) {
15889         views[i].remove();
15890       }
15891     },
15892
15893     childViewsDidChange: function(view, views, start, added) {
15894       Ember.run.scheduleOnce('render', this, '_ensureChildrenAreInDOM');
15895     },
15896
15897     ensureChildrenAreInDOM: function(view) {
15898       var childViews = view.get('childViews'), i, len, childView, previous, buffer;
15899       for (i = 0, len = childViews.length; i < len; i++) {
15900         childView = childViews[i];
15901         buffer = childView.renderToBufferIfNeeded();
15902         if (buffer) {
15903           childView._notifyWillInsertElement();
15904           if (previous) {
15905             previous.domManager.after(previous, buffer.string());
15906           } else {
15907             view.domManager.prepend(view, buffer.string());
15908           }
15909           childView.transitionTo('inDOM');
15910           childView.propertyDidChange('element');
15911           childView._notifyDidInsertElement();
15912         }
15913         previous = childView;
15914       }
15915     }
15916   }
15917 };
15918
15919 Ember.ContainerView.states.inDOM = {
15920   parentState: Ember.ContainerView.states.hasElement
15921 };
15922
15923 Ember.ContainerView.reopen({
15924   states: Ember.ContainerView.states
15925 });
15926
15927 })();
15928
15929
15930
15931 (function() {
15932 /**
15933 @module ember
15934 @submodule ember-views
15935 */
15936
15937 var get = Ember.get, set = Ember.set, fmt = Ember.String.fmt;
15938
15939 /**
15940   `Ember.CollectionView` is an `Ember.View` descendent responsible for managing a
15941   collection (an array or array-like object) by maintaing a child view object and 
15942   associated DOM representation for each item in the array and ensuring that child
15943   views and their associated rendered HTML are updated when items in the array
15944   are added, removed, or replaced.
15945
15946   ## Setting content
15947   The managed collection of objects is referenced as the `Ember.CollectionView` instance's
15948   `content` property.
15949
15950   ``` javascript
15951   someItemsView = Ember.CollectionView.create({
15952     content: ['A', 'B','C']
15953   })
15954   ```
15955
15956   The view for each item in the collection will have its `content` property set
15957   to the item.
15958
15959   ## Specifying itemViewClass
15960   By default the view class for each item in the managed collection will be an instance
15961   of `Ember.View`. You can supply a different class by setting the `CollectionView`'s
15962   `itemViewClass` property.
15963
15964   Given an empty `<body>` and the following code:
15965
15966   ``` javascript 
15967   someItemsView = Ember.CollectionView.create({
15968     classNames: ['a-collection'],
15969     content: ['A','B','C'],
15970     itemViewClass: Ember.View.extend({
15971       template: Ember.Handlebars.compile("the letter: {{view.content}}")
15972     })
15973   });
15974
15975   someItemsView.appendTo('body');
15976   ```
15977
15978   Will result in the following HTML structure
15979
15980   ``` html
15981   <div class="ember-view a-collection">
15982     <div class="ember-view">the letter: A</div>
15983     <div class="ember-view">the letter: B</div>
15984     <div class="ember-view">the letter: C</div>
15985   </div>
15986   ```
15987
15988   ## Automatic matching of parent/child tagNames
15989
15990   Setting the `tagName` property of a `CollectionView` to any of 
15991   "ul", "ol", "table", "thead", "tbody", "tfoot", "tr", or "select" will result
15992   in the item views receiving an appropriately matched `tagName` property.
15993
15994
15995   Given an empty `<body>` and the following code:
15996
15997   ``` javascript
15998   anUndorderedListView = Ember.CollectionView.create({
15999     tagName: 'ul',
16000     content: ['A','B','C'],
16001     itemViewClass: Ember.View.extend({
16002       template: Ember.Handlebars.compile("the letter: {{view.content}}")
16003     })
16004   });
16005
16006   anUndorderedListView.appendTo('body');
16007   ```
16008
16009   Will result in the following HTML structure
16010
16011   ``` html
16012   <ul class="ember-view a-collection">
16013     <li class="ember-view">the letter: A</li>
16014     <li class="ember-view">the letter: B</li>
16015     <li class="ember-view">the letter: C</li>
16016   </ul>
16017   ```
16018
16019   Additional tagName pairs can be provided by adding to `Ember.CollectionView.CONTAINER_MAP `
16020
16021   ``` javascript
16022   Ember.CollectionView.CONTAINER_MAP['article'] = 'section'
16023   ```
16024
16025
16026   ## Empty View
16027   You can provide an `Ember.View` subclass to the `Ember.CollectionView` instance as its
16028   `emptyView` property. If the `content` property of a `CollectionView` is set to `null`
16029   or an empty array, an instance of this view will be the `CollectionView`s only child.
16030
16031   ``` javascript
16032   aListWithNothing = Ember.CollectionView.create({
16033     classNames: ['nothing']
16034     content: null,
16035     emptyView: Ember.View.extend({
16036       template: Ember.Handlebars.compile("The collection is empty")
16037     })
16038   });
16039
16040   aListWithNothing.appendTo('body');
16041   ```
16042
16043   Will result in the following HTML structure
16044
16045   ``` html
16046   <div class="ember-view nothing">
16047     <div class="ember-view">
16048       The collection is empty
16049     </div>
16050   </div>
16051   ```
16052
16053   ## Adding and Removing items
16054   The `childViews` property of a `CollectionView` should not be directly manipulated. Instead,
16055   add, remove, replace items from its `content` property. This will trigger
16056   appropriate changes to its rendered HTML.
16057
16058   ## Use in templates via the `{{collection}}` Ember.Handlebars helper
16059   Ember.Handlebars provides a helper specifically for adding `CollectionView`s to templates.
16060   See `Ember.Handlebars.collection` for more details
16061
16062   @class CollectionView
16063   @namespace Ember
16064   @extends Ember.ContainerView
16065   @since Ember 0.9
16066 */
16067 Ember.CollectionView = Ember.ContainerView.extend(
16068 /** @scope Ember.CollectionView.prototype */ {
16069
16070   /**
16071     A list of items to be displayed by the Ember.CollectionView.
16072
16073     @property content
16074     @type Ember.Array
16075     @default null
16076   */
16077   content: null,
16078
16079   /**
16080     @private
16081
16082     This provides metadata about what kind of empty view class this
16083     collection would like if it is being instantiated from another
16084     system (like Handlebars)
16085
16086     @property emptyViewClass
16087   */
16088   emptyViewClass: Ember.View,
16089
16090   /**
16091     An optional view to display if content is set to an empty array.
16092
16093     @property emptyView
16094     @type Ember.View
16095     @default null
16096   */
16097   emptyView: null,
16098
16099   /**
16100     @property itemViewClass
16101     @type Ember.View
16102     @default Ember.View
16103   */
16104   itemViewClass: Ember.View,
16105
16106   init: function() {
16107     var ret = this._super();
16108     this._contentDidChange();
16109     return ret;
16110   },
16111
16112   _contentWillChange: Ember.beforeObserver(function() {
16113     var content = this.get('content');
16114
16115     if (content) { content.removeArrayObserver(this); }
16116     var len = content ? get(content, 'length') : 0;
16117     this.arrayWillChange(content, 0, len);
16118   }, 'content'),
16119
16120   /**
16121     @private
16122
16123     Check to make sure that the content has changed, and if so,
16124     update the children directly. This is always scheduled
16125     asynchronously, to allow the element to be created before
16126     bindings have synchronized and vice versa.
16127
16128     @method _contentDidChange
16129   */
16130   _contentDidChange: Ember.observer(function() {
16131     var content = get(this, 'content');
16132
16133     if (content) {
16134       Ember.assert(fmt("an Ember.CollectionView's content must implement Ember.Array. You passed %@", [content]), Ember.Array.detect(content));
16135       content.addArrayObserver(this);
16136     }
16137
16138     var len = content ? get(content, 'length') : 0;
16139     this.arrayDidChange(content, 0, null, len);
16140   }, 'content'),
16141
16142   willDestroy: function() {
16143     var content = get(this, 'content');
16144     if (content) { content.removeArrayObserver(this); }
16145
16146     this._super();
16147   },
16148
16149   arrayWillChange: function(content, start, removedCount) {
16150     // If the contents were empty before and this template collection has an
16151     // empty view remove it now.
16152     var emptyView = get(this, 'emptyView');
16153     if (emptyView && emptyView instanceof Ember.View) {
16154       emptyView.removeFromParent();
16155     }
16156
16157     // Loop through child views that correspond with the removed items.
16158     // Note that we loop from the end of the array to the beginning because
16159     // we are mutating it as we go.
16160     var childViews = get(this, 'childViews'), childView, idx, len;
16161
16162     len = get(childViews, 'length');
16163
16164     var removingAll = removedCount === len;
16165
16166     if (removingAll) {
16167       this.invokeForState('empty');
16168     }
16169
16170     for (idx = start + removedCount - 1; idx >= start; idx--) {
16171       childView = childViews[idx];
16172       if (removingAll) { childView.removedFromDOM = true; }
16173       childView.destroy();
16174     }
16175   },
16176
16177   /**
16178     Called when a mutation to the underlying content array occurs.
16179
16180     This method will replay that mutation against the views that compose the
16181     Ember.CollectionView, ensuring that the view reflects the model.
16182
16183     This array observer is added in contentDidChange.
16184
16185     @method arrayDidChange
16186     @param {Array} addedObjects the objects that were added to the content
16187     @param {Array} removedObjects the objects that were removed from the content
16188     @param {Number} changeIndex the index at which the changes occurred
16189   */
16190   arrayDidChange: function(content, start, removed, added) {
16191     var itemViewClass = get(this, 'itemViewClass'),
16192         childViews = get(this, 'childViews'),
16193         addedViews = [], view, item, idx, len, itemTagName;
16194
16195     if ('string' === typeof itemViewClass) {
16196       itemViewClass = get(itemViewClass);
16197     }
16198
16199     Ember.assert(fmt("itemViewClass must be a subclass of Ember.View, not %@", [itemViewClass]), Ember.View.detect(itemViewClass));
16200
16201     len = content ? get(content, 'length') : 0;
16202     if (len) {
16203       for (idx = start; idx < start+added; idx++) {
16204         item = content.objectAt(idx);
16205
16206         view = this.createChildView(itemViewClass, {
16207           content: item,
16208           contentIndex: idx
16209         });
16210
16211         addedViews.push(view);
16212       }
16213     } else {
16214       var emptyView = get(this, 'emptyView');
16215       if (!emptyView) { return; }
16216
16217       emptyView = this.createChildView(emptyView);
16218       addedViews.push(emptyView);
16219       set(this, 'emptyView', emptyView);
16220     }
16221     childViews.replace(start, 0, addedViews);
16222   },
16223
16224   createChildView: function(view, attrs) {
16225     view = this._super(view, attrs);
16226
16227     var itemTagName = get(view, 'tagName');
16228     var tagName = (itemTagName === null || itemTagName === undefined) ? Ember.CollectionView.CONTAINER_MAP[get(this, 'tagName')] : itemTagName;
16229
16230     set(view, 'tagName', tagName);
16231
16232     return view;
16233   }
16234 });
16235
16236 /**
16237   A map of parent tags to their default child tags. You can add
16238   additional parent tags if you want collection views that use
16239   a particular parent tag to default to a child tag.
16240
16241   @property CONTAINER_MAP
16242   @type Hash
16243   @static
16244   @final
16245 */
16246 Ember.CollectionView.CONTAINER_MAP = {
16247   ul: 'li',
16248   ol: 'li',
16249   table: 'tr',
16250   thead: 'tr',
16251   tbody: 'tr',
16252   tfoot: 'tr',
16253   tr: 'td',
16254   select: 'option'
16255 };
16256
16257 })();
16258
16259
16260
16261 (function() {
16262
16263 })();
16264
16265
16266
16267 (function() {
16268 /*globals jQuery*/
16269 /**
16270 Ember Views
16271
16272 @module ember
16273 @submodule ember-views
16274 @require ember-runtime
16275 @main ember-views
16276 */
16277
16278 })();
16279
16280 (function() {
16281 var get = Ember.get, set = Ember.set;
16282
16283 /**
16284 @module ember
16285 @submodule ember-states
16286 */
16287
16288 /**
16289   @class State
16290   @namespace Ember
16291   @extends Ember.Object
16292   @uses Ember.Evented
16293 */
16294 Ember.State = Ember.Object.extend(Ember.Evented,
16295 /** @scope Ember.State.prototype */{
16296   isState: true,
16297
16298   /**
16299     A reference to the parent state.
16300
16301     @property parentState
16302     @type Ember.State
16303   */
16304   parentState: null,
16305   start: null,
16306
16307   /**
16308     The name of this state.
16309
16310     @property name
16311     @type String
16312   */
16313   name: null,
16314
16315   /**
16316     The full path to this state.
16317
16318     @property path
16319     @type String
16320   */
16321   path: Ember.computed(function() {
16322     var parentPath = get(this, 'parentState.path'),
16323         path = get(this, 'name');
16324
16325     if (parentPath) {
16326       path = parentPath + '.' + path;
16327     }
16328
16329     return path;
16330   }).property(),
16331
16332   /**
16333     @private
16334
16335     Override the default event firing from Ember.Evented to
16336     also call methods with the given name.
16337
16338     @method trigger
16339     @param name
16340   */
16341   trigger: function(name) {
16342     if (this[name]) {
16343       this[name].apply(this, [].slice.call(arguments, 1));
16344     }
16345     this._super.apply(this, arguments);
16346   },
16347
16348   init: function() {
16349     var states = get(this, 'states'), foundStates;
16350     set(this, 'childStates', Ember.A());
16351     set(this, 'eventTransitions', get(this, 'eventTransitions') || {});
16352
16353     var name, value, transitionTarget;
16354
16355     // As a convenience, loop over the properties
16356     // of this state and look for any that are other
16357     // Ember.State instances or classes, and move them
16358     // to the `states` hash. This avoids having to
16359     // create an explicit separate hash.
16360
16361     if (!states) {
16362       states = {};
16363
16364       for (name in this) {
16365         if (name === "constructor") { continue; }
16366
16367         if (value = this[name]) {
16368           if (transitionTarget = value.transitionTarget) {
16369             this.eventTransitions[name] = transitionTarget;
16370           }
16371
16372           this.setupChild(states, name, value);
16373         }
16374       }
16375
16376       set(this, 'states', states);
16377     } else {
16378       for (name in states) {
16379         this.setupChild(states, name, states[name]);
16380       }
16381     }
16382
16383     set(this, 'pathsCache', {});
16384     set(this, 'pathsCacheNoContext', {});
16385   },
16386
16387   setupChild: function(states, name, value) {
16388     if (!value) { return false; }
16389
16390     if (value.isState) {
16391       set(value, 'name', name);
16392     } else if (Ember.State.detect(value)) {
16393       value = value.create({
16394         name: name
16395       });
16396     }
16397
16398     if (value.isState) {
16399       set(value, 'parentState', this);
16400       get(this, 'childStates').pushObject(value);
16401       states[name] = value;
16402       return value;
16403     }
16404   },
16405
16406   lookupEventTransition: function(name) {
16407     var path, state = this;
16408
16409     while(state && !path) {
16410       path = state.eventTransitions[name];
16411       state = state.get('parentState');
16412     }
16413
16414     return path;
16415   },
16416
16417   /**
16418     A Boolean value indicating whether the state is a leaf state
16419     in the state hierarchy. This is false if the state has child
16420     states; otherwise it is true.
16421
16422     @property isLeaf
16423     @type Boolean
16424   */
16425   isLeaf: Ember.computed(function() {
16426     return !get(this, 'childStates').length;
16427   }),
16428
16429   /**
16430     A boolean value indicating whether the state takes a context.
16431     By default we assume all states take contexts.
16432
16433     @property hasContext
16434     @default true
16435   */
16436   hasContext: true,
16437
16438   /**
16439     This is the default transition event.
16440
16441     @event setup
16442     @param {Ember.StateManager} manager
16443     @param context
16444     @see Ember.StateManager#transitionEvent
16445   */
16446   setup: Ember.K,
16447
16448   /**
16449     This event fires when the state is entered.
16450
16451     @event enter
16452     @param {Ember.StateManager} manager
16453   */
16454   enter: Ember.K,
16455
16456   /**
16457     This event fires when the state is exited.
16458
16459     @event exit
16460     @param {Ember.StateManager} manager
16461   */
16462   exit: Ember.K
16463 });
16464
16465 Ember.State.reopenClass({
16466
16467   /**
16468     Creates an action function for transitioning to the named state while preserving context.
16469
16470     The following example StateManagers are equivalent:
16471
16472         aManager = Ember.StateManager.create({
16473           stateOne: Ember.State.create({
16474             changeToStateTwo: Ember.State.transitionTo('stateTwo')
16475           }),
16476           stateTwo: Ember.State.create({})
16477         })
16478
16479         bManager = Ember.StateManager.create({
16480           stateOne: Ember.State.create({
16481             changeToStateTwo: function(manager, context){
16482               manager.transitionTo('stateTwo', context)
16483             }
16484           }),
16485           stateTwo: Ember.State.create({})
16486         })
16487
16488     @method transitionTo
16489     @static
16490     @param {String} target
16491   */
16492
16493   transitionTo: function(target) {
16494
16495     var transitionFunction = function(stateManager, contextOrEvent) {
16496       var contexts = [], transitionArgs,
16497           Event = Ember.$ && Ember.$.Event;
16498
16499       if (contextOrEvent && (Event && contextOrEvent instanceof Event)) {
16500         if (contextOrEvent.hasOwnProperty('contexts')) {
16501           contexts = contextOrEvent.contexts.slice();
16502         }
16503       }
16504       else {
16505         contexts = [].slice.call(arguments, 1);
16506       }
16507
16508       contexts.unshift(target);
16509       stateManager.transitionTo.apply(stateManager, contexts);
16510     };
16511
16512     transitionFunction.transitionTarget = target;
16513
16514     return transitionFunction;
16515   }
16516
16517 });
16518
16519 })();
16520
16521
16522
16523 (function() {
16524 /**
16525 @module ember
16526 @submodule ember-states
16527 */
16528
16529 var get = Ember.get, set = Ember.set, fmt = Ember.String.fmt;
16530 var arrayForEach = Ember.ArrayPolyfills.forEach;
16531 /**
16532   A Transition takes the enter, exit and resolve states and normalizes
16533   them:
16534
16535   * takes any passed in contexts into consideration
16536   * adds in `initialState`s
16537
16538   @class Transition
16539   @private
16540 */
16541 var Transition = function(raw) {
16542   this.enterStates = raw.enterStates.slice();
16543   this.exitStates = raw.exitStates.slice();
16544   this.resolveState = raw.resolveState;
16545
16546   this.finalState = raw.enterStates[raw.enterStates.length - 1] || raw.resolveState;
16547 };
16548
16549 Transition.prototype = {
16550   /**
16551     Normalize the passed in enter, exit and resolve states.
16552
16553     This process also adds `finalState` and `contexts` to the Transition object.
16554
16555     @method normalize
16556     @param {Ember.StateManager} manager the state manager running the transition
16557     @param {Array} contexts a list of contexts passed into `transitionTo`
16558   */
16559   normalize: function(manager, contexts) {
16560     this.matchContextsToStates(contexts);
16561     this.addInitialStates();
16562     this.removeUnchangedContexts(manager);
16563     return this;
16564   },
16565
16566   /**
16567     Match each of the contexts passed to `transitionTo` to a state.
16568     This process may also require adding additional enter and exit
16569     states if there are more contexts than enter states.
16570
16571     @method matchContextsToStates
16572     @param {Array} contexts a list of contexts passed into `transitionTo`
16573   */
16574   matchContextsToStates: function(contexts) {
16575     var stateIdx = this.enterStates.length - 1,
16576         matchedContexts = [],
16577         state,
16578         context;
16579
16580     // Next, we will match the passed in contexts to the states they
16581     // represent.
16582     //
16583     // First, assign a context to each enter state in reverse order. If
16584     // any contexts are left, add a parent state to the list of states
16585     // to enter and exit, and assign a context to the parent state.
16586     //
16587     // If there are still contexts left when the state manager is
16588     // reached, raise an exception.
16589     //
16590     // This allows the following:
16591     //
16592     // |- root
16593     // | |- post
16594     // | | |- comments
16595     // | |- about (* current state)
16596     //
16597     // For `transitionTo('post.comments', post, post.get('comments')`,
16598     // the first context (`post`) will be assigned to `root.post`, and
16599     // the second context (`post.get('comments')`) will be assigned
16600     // to `root.post.comments`.
16601     //
16602     // For the following:
16603     //
16604     // |- root
16605     // | |- post
16606     // | | |- index (* current state)
16607     // | | |- comments
16608     //
16609     // For `transitionTo('post.comments', otherPost, otherPost.get('comments')`,
16610     // the `<root.post>` state will be added to the list of enter and exit
16611     // states because its context has changed.
16612
16613     while (contexts.length > 0) {
16614       if (stateIdx >= 0) {
16615         state = this.enterStates[stateIdx--];
16616       } else {
16617         if (this.enterStates.length) {
16618           state = get(this.enterStates[0], 'parentState');
16619           if (!state) { throw "Cannot match all contexts to states"; }
16620         } else {
16621           // If re-entering the current state with a context, the resolve
16622           // state will be the current state.
16623           state = this.resolveState;
16624         }
16625
16626         this.enterStates.unshift(state);
16627         this.exitStates.unshift(state);
16628       }
16629
16630       // in routers, only states with dynamic segments have a context
16631       if (get(state, 'hasContext')) {
16632         context = contexts.pop();
16633       } else {
16634         context = null;
16635       }
16636
16637       matchedContexts.unshift(context);
16638     }
16639
16640     this.contexts = matchedContexts;
16641   },
16642
16643   /**
16644     Add any `initialState`s to the list of enter states.
16645
16646     @method addInitialStates
16647   */
16648   addInitialStates: function() {
16649     var finalState = this.finalState, initialState;
16650
16651     while(true) {
16652       initialState = get(finalState, 'initialState') || 'start';
16653       finalState = get(finalState, 'states.' + initialState);
16654
16655       if (!finalState) { break; }
16656
16657       this.finalState = finalState;
16658       this.enterStates.push(finalState);
16659       this.contexts.push(undefined);
16660     }
16661   },
16662
16663   /**
16664     Remove any states that were added because the number of contexts
16665     exceeded the number of explicit enter states, but the context has
16666     not changed since the last time the state was entered.
16667
16668     @method removeUnchangedContexts
16669     @param {Ember.StateManager} manager passed in to look up the last
16670       context for a states
16671   */
16672   removeUnchangedContexts: function(manager) {
16673     // Start from the beginning of the enter states. If the state was added
16674     // to the list during the context matching phase, make sure the context
16675     // has actually changed since the last time the state was entered.
16676     while (this.enterStates.length > 0) {
16677       if (this.enterStates[0] !== this.exitStates[0]) { break; }
16678
16679       if (this.enterStates.length === this.contexts.length) {
16680         if (manager.getStateMeta(this.enterStates[0], 'context') !== this.contexts[0]) { break; }
16681         this.contexts.shift();
16682       }
16683
16684       this.resolveState = this.enterStates.shift();
16685       this.exitStates.shift();
16686     }
16687   }
16688 };
16689
16690 /**
16691   StateManager is part of Ember's implementation of a finite state machine. A StateManager
16692   instance manages a number of properties that are instances of `Ember.State`,
16693   tracks the current active state, and triggers callbacks when states have changed.
16694
16695   ## Defining States
16696
16697   The states of StateManager can be declared in one of two ways. First, you can define
16698   a `states` property that contains all the states:
16699
16700       managerA = Ember.StateManager.create({
16701         states: {
16702           stateOne: Ember.State.create(),
16703           stateTwo: Ember.State.create()
16704         }
16705       })
16706
16707       managerA.get('states')
16708       // {
16709       //   stateOne: Ember.State.create(),
16710       //   stateTwo: Ember.State.create()
16711       // }
16712
16713   You can also add instances of `Ember.State` (or an `Ember.State` subclass) directly as properties
16714   of a StateManager. These states will be collected into the `states` property for you.
16715
16716       managerA = Ember.StateManager.create({
16717         stateOne: Ember.State.create(),
16718         stateTwo: Ember.State.create()
16719       })
16720
16721       managerA.get('states')
16722       // {
16723       //   stateOne: Ember.State.create(),
16724       //   stateTwo: Ember.State.create()
16725       // }
16726
16727   ## The Initial State
16728   When created a StateManager instance will immediately enter into the state
16729   defined as its `start` property or the state referenced by name in its
16730   `initialState` property:
16731
16732       managerA = Ember.StateManager.create({
16733         start: Ember.State.create({})
16734       })
16735
16736       managerA.get('currentState.name') // 'start'
16737
16738       managerB = Ember.StateManager.create({
16739         initialState: 'beginHere',
16740         beginHere: Ember.State.create({})
16741       })
16742
16743       managerB.get('currentState.name') // 'beginHere'
16744
16745   Because it is a property you may also provide a computed function if you wish to derive
16746   an `initialState` programmatically:
16747
16748       managerC = Ember.StateManager.create({
16749         initialState: function(){
16750           if (someLogic) {
16751             return 'active';
16752           } else {
16753             return 'passive';
16754           }
16755         }.property(),
16756         active: Ember.State.create({}),
16757         passive: Ember.State.create({})
16758       })
16759
16760   ## Moving Between States
16761   A StateManager can have any number of Ember.State objects as properties
16762   and can have a single one of these states as its current state.
16763
16764   Calling `transitionTo` transitions between states:
16765
16766       robotManager = Ember.StateManager.create({
16767         initialState: 'poweredDown',
16768         poweredDown: Ember.State.create({}),
16769         poweredUp: Ember.State.create({})
16770       })
16771
16772       robotManager.get('currentState.name') // 'poweredDown'
16773       robotManager.transitionTo('poweredUp')
16774       robotManager.get('currentState.name') // 'poweredUp'
16775
16776   Before transitioning into a new state the existing `currentState` will have its
16777   `exit` method called with the StateManager instance as its first argument and
16778   an object representing the transition as its second argument.
16779
16780   After transitioning into a new state the new `currentState` will have its
16781   `enter` method called with the StateManager instance as its first argument and
16782   an object representing the transition as its second argument.
16783
16784       robotManager = Ember.StateManager.create({
16785         initialState: 'poweredDown',
16786         poweredDown: Ember.State.create({
16787           exit: function(stateManager){
16788             console.log("exiting the poweredDown state")
16789           }
16790         }),
16791         poweredUp: Ember.State.create({
16792           enter: function(stateManager){
16793             console.log("entering the poweredUp state. Destroy all humans.")
16794           }
16795         })
16796       })
16797
16798       robotManager.get('currentState.name') // 'poweredDown'
16799       robotManager.transitionTo('poweredUp')
16800       // will log
16801       // 'exiting the poweredDown state'
16802       // 'entering the poweredUp state. Destroy all humans.'
16803
16804
16805   Once a StateManager is already in a state, subsequent attempts to enter that state will
16806   not trigger enter or exit method calls. Attempts to transition into a state that the
16807   manager does not have will result in no changes in the StateManager's current state:
16808
16809       robotManager = Ember.StateManager.create({
16810         initialState: 'poweredDown',
16811         poweredDown: Ember.State.create({
16812           exit: function(stateManager){
16813             console.log("exiting the poweredDown state")
16814           }
16815         }),
16816         poweredUp: Ember.State.create({
16817           enter: function(stateManager){
16818             console.log("entering the poweredUp state. Destroy all humans.")
16819           }
16820         })
16821       })
16822
16823       robotManager.get('currentState.name') // 'poweredDown'
16824       robotManager.transitionTo('poweredUp')
16825       // will log
16826       // 'exiting the poweredDown state'
16827       // 'entering the poweredUp state. Destroy all humans.'
16828       robotManager.transitionTo('poweredUp') // no logging, no state change
16829
16830       robotManager.transitionTo('someUnknownState') // silently fails
16831       robotManager.get('currentState.name') // 'poweredUp'
16832
16833
16834   Each state property may itself contain properties that are instances of Ember.State.
16835   The StateManager can transition to specific sub-states in a series of transitionTo method calls or
16836   via a single transitionTo with the full path to the specific state. The StateManager will also
16837   keep track of the full path to its currentState
16838
16839       robotManager = Ember.StateManager.create({
16840         initialState: 'poweredDown',
16841         poweredDown: Ember.State.create({
16842           charging: Ember.State.create(),
16843           charged: Ember.State.create()
16844         }),
16845         poweredUp: Ember.State.create({
16846           mobile: Ember.State.create(),
16847           stationary: Ember.State.create()
16848         })
16849       })
16850
16851       robotManager.get('currentState.name') // 'poweredDown'
16852
16853       robotManager.transitionTo('poweredUp')
16854       robotManager.get('currentState.name') // 'poweredUp'
16855
16856       robotManager.transitionTo('mobile')
16857       robotManager.get('currentState.name') // 'mobile'
16858
16859       // transition via a state path
16860       robotManager.transitionTo('poweredDown.charging')
16861       robotManager.get('currentState.name') // 'charging'
16862
16863       robotManager.get('currentState.path') // 'poweredDown.charging'
16864
16865   Enter transition methods will be called for each state and nested child state in their
16866   hierarchical order.  Exit methods will be called for each state and its nested states in
16867   reverse hierarchical order.
16868
16869   Exit transitions for a parent state are not called when entering into one of its child states,
16870   only when transitioning to a new section of possible states in the hierarchy.
16871
16872       robotManager = Ember.StateManager.create({
16873         initialState: 'poweredDown',
16874         poweredDown: Ember.State.create({
16875           enter: function(){},
16876           exit: function(){
16877             console.log("exited poweredDown state")
16878           },
16879           charging: Ember.State.create({
16880             enter: function(){},
16881             exit: function(){}
16882           }),
16883           charged: Ember.State.create({
16884             enter: function(){
16885               console.log("entered charged state")
16886             },
16887             exit: function(){
16888               console.log("exited charged state")
16889             }
16890           })
16891         }),
16892         poweredUp: Ember.State.create({
16893           enter: function(){
16894             console.log("entered poweredUp state")
16895           },
16896           exit: function(){},
16897           mobile: Ember.State.create({
16898             enter: function(){
16899               console.log("entered mobile state")
16900             },
16901             exit: function(){}
16902           }),
16903           stationary: Ember.State.create({
16904             enter: function(){},
16905             exit: function(){}
16906           })
16907         })
16908       })
16909
16910
16911       robotManager.get('currentState.path') // 'poweredDown'
16912       robotManager.transitionTo('charged')
16913       // logs 'entered charged state'
16914       // but does *not* log  'exited poweredDown state'
16915       robotManager.get('currentState.name') // 'charged
16916
16917       robotManager.transitionTo('poweredUp.mobile')
16918       // logs
16919       // 'exited charged state'
16920       // 'exited poweredDown state'
16921       // 'entered poweredUp state'
16922       // 'entered mobile state'
16923
16924   During development you can set a StateManager's `enableLogging` property to `true` to
16925   receive console messages of state transitions.
16926
16927       robotManager = Ember.StateManager.create({
16928         enableLogging: true
16929       })
16930
16931   ## Managing currentState with Actions
16932   To control which transitions between states are possible for a given state, StateManager
16933   can receive and route action messages to its states via the `send` method.  Calling to `send` with
16934   an action name will begin searching for a method with the same name starting at the current state
16935   and moving up through the parent states in a state hierarchy until an appropriate method is found
16936   or the StateManager instance itself is reached.
16937
16938   If an appropriately named method is found it will be called with the state manager as the first
16939   argument and an optional `context` object as the second argument.
16940
16941       managerA = Ember.StateManager.create({
16942         initialState: 'stateOne.substateOne.subsubstateOne',
16943         stateOne: Ember.State.create({
16944           substateOne: Ember.State.create({
16945             anAction: function(manager, context){
16946               console.log("an action was called")
16947             },
16948             subsubstateOne: Ember.State.create({})
16949           })
16950         })
16951       })
16952
16953       managerA.get('currentState.name') // 'subsubstateOne'
16954       managerA.send('anAction')
16955       // 'stateOne.substateOne.subsubstateOne' has no anAction method
16956       // so the 'anAction' method of 'stateOne.substateOne' is called
16957       // and logs "an action was called"
16958       // with managerA as the first argument
16959       // and no second argument
16960
16961       someObject = {}
16962       managerA.send('anAction', someObject)
16963       // the 'anAction' method of 'stateOne.substateOne' is called again
16964       // with managerA as the first argument and
16965       // someObject as the second argument.
16966
16967
16968   If the StateManager attempts to send an action but does not find an appropriately named
16969   method in the current state or while moving upwards through the state hierarchy
16970   it will throw a new Ember.Error. Action detection only moves upwards through the state hierarchy
16971   from the current state. It does not search in other portions of the hierarchy.
16972
16973       managerB = Ember.StateManager.create({
16974         initialState: 'stateOne.substateOne.subsubstateOne',
16975         stateOne: Ember.State.create({
16976           substateOne: Ember.State.create({
16977             subsubstateOne: Ember.State.create({})
16978           })
16979         }),
16980         stateTwo: Ember.State.create({
16981          anAction: function(manager, context){
16982            // will not be called below because it is
16983            // not a parent of the current state
16984          }
16985         })
16986       })
16987
16988       managerB.get('currentState.name') // 'subsubstateOne'
16989       managerB.send('anAction')
16990       // Error: <Ember.StateManager:ember132> could not
16991       // respond to event anAction in state stateOne.substateOne.subsubstateOne.
16992
16993   Inside of an action method the given state should delegate `transitionTo` calls on its
16994   StateManager.
16995
16996       robotManager = Ember.StateManager.create({
16997         initialState: 'poweredDown.charging',
16998         poweredDown: Ember.State.create({
16999           charging: Ember.State.create({
17000             chargeComplete: function(manager, context){
17001               manager.transitionTo('charged')
17002             }
17003           }),
17004           charged: Ember.State.create({
17005             boot: function(manager, context){
17006               manager.transitionTo('poweredUp')
17007             }
17008           })
17009         }),
17010         poweredUp: Ember.State.create({
17011           beginExtermination: function(manager, context){
17012             manager.transitionTo('rampaging')
17013           },
17014           rampaging: Ember.State.create()
17015         })
17016       })
17017
17018       robotManager.get('currentState.name') // 'charging'
17019       robotManager.send('boot') // throws error, no boot action
17020                                 // in current hierarchy
17021       robotManager.get('currentState.name') // remains 'charging'
17022
17023       robotManager.send('beginExtermination') // throws error, no beginExtermination
17024                                               // action in current hierarchy
17025       robotManager.get('currentState.name') // remains 'charging'
17026
17027       robotManager.send('chargeComplete')
17028       robotManager.get('currentState.name') // 'charged'
17029
17030       robotManager.send('boot')
17031       robotManager.get('currentState.name') // 'poweredUp'
17032
17033       robotManager.send('beginExtermination', allHumans)
17034       robotManager.get('currentState.name') // 'rampaging'
17035
17036   Transition actions can also be created using the `transitionTo` method of the Ember.State class. The
17037   following example StateManagers are equivalent:
17038
17039       aManager = Ember.StateManager.create({
17040         stateOne: Ember.State.create({
17041           changeToStateTwo: Ember.State.transitionTo('stateTwo')
17042         }),
17043         stateTwo: Ember.State.create({})
17044       })
17045
17046       bManager = Ember.StateManager.create({
17047         stateOne: Ember.State.create({
17048           changeToStateTwo: function(manager, context){
17049             manager.transitionTo('stateTwo', context)
17050           }
17051         }),
17052         stateTwo: Ember.State.create({})
17053       })
17054
17055   @class StateManager
17056   @namespace Ember
17057   @extends Ember.State
17058 **/
17059 Ember.StateManager = Ember.State.extend({
17060   /**
17061     @private
17062
17063     When creating a new statemanager, look for a default state to transition
17064     into. This state can either be named `start`, or can be specified using the
17065     `initialState` property.
17066
17067     @method init
17068   */
17069   init: function() {
17070     this._super();
17071
17072     set(this, 'stateMeta', Ember.Map.create());
17073
17074     var initialState = get(this, 'initialState');
17075
17076     if (!initialState && get(this, 'states.start')) {
17077       initialState = 'start';
17078     }
17079
17080     if (initialState) {
17081       this.transitionTo(initialState);
17082       Ember.assert('Failed to transition to initial state "' + initialState + '"', !!get(this, 'currentState'));
17083     }
17084   },
17085
17086   stateMetaFor: function(state) {
17087     var meta = get(this, 'stateMeta'),
17088         stateMeta = meta.get(state);
17089
17090     if (!stateMeta) {
17091       stateMeta = {};
17092       meta.set(state, stateMeta);
17093     }
17094
17095     return stateMeta;
17096   },
17097
17098   setStateMeta: function(state, key, value) {
17099     return set(this.stateMetaFor(state), key, value);
17100   },
17101
17102   getStateMeta: function(state, key) {
17103     return get(this.stateMetaFor(state), key);
17104   },
17105
17106   /**
17107     The current state from among the manager's possible states. This property should
17108     not be set directly.  Use `transitionTo` to move between states by name.
17109
17110     @property currentState
17111     @type Ember.State
17112   */
17113   currentState: null,
17114
17115   /**
17116    The path of the current state. Returns a string representation of the current
17117    state.
17118
17119    @property currentPath
17120    @type String
17121   */
17122   currentPath: Ember.computed('currentState', function() {
17123     return get(this, 'currentState.path');
17124   }),
17125
17126   /**
17127     The name of transitionEvent that this stateManager will dispatch
17128
17129     @property transitionEvent
17130     @type String
17131     @default 'setup'
17132   */
17133   transitionEvent: 'setup',
17134
17135   /**
17136     If set to true, `errorOnUnhandledEvents` will cause an exception to be
17137     raised if you attempt to send an event to a state manager that is not
17138     handled by the current state or any of its parent states.
17139
17140     @property errorOnUnhandledEvents
17141     @type Boolean
17142     @default true
17143   */
17144   errorOnUnhandledEvent: true,
17145
17146   send: function(event) {
17147     var contexts, sendRecursiveArguments;
17148
17149     Ember.assert('Cannot send event "' + event + '" while currentState is ' + get(this, 'currentState'), get(this, 'currentState'));
17150
17151     contexts = [].slice.call(arguments, 1);
17152     sendRecursiveArguments = contexts;
17153     sendRecursiveArguments.unshift(event, get(this, 'currentState'));
17154
17155     return this.sendRecursively.apply(this, sendRecursiveArguments);
17156   },
17157
17158   sendRecursively: function(event, currentState) {
17159     var log = this.enableLogging,
17160         action = currentState[event],
17161         contexts, sendRecursiveArguments, actionArguments;
17162
17163     contexts = [].slice.call(arguments, 2);
17164
17165     // Test to see if the action is a method that
17166     // can be invoked. Don't blindly check just for
17167     // existence, because it is possible the state
17168     // manager has a child state of the given name,
17169     // and we should still raise an exception in that
17170     // case.
17171     if (typeof action === 'function') {
17172       if (log) { Ember.Logger.log(fmt("STATEMANAGER: Sending event '%@' to state %@.", [event, get(currentState, 'path')])); }
17173
17174       actionArguments = contexts;
17175       actionArguments.unshift(this);
17176
17177       return action.apply(currentState, actionArguments);
17178     } else {
17179       var parentState = get(currentState, 'parentState');
17180       if (parentState) {
17181
17182         sendRecursiveArguments = contexts;
17183         sendRecursiveArguments.unshift(event, parentState);
17184
17185         return this.sendRecursively.apply(this, sendRecursiveArguments);
17186       } else if (get(this, 'errorOnUnhandledEvent')) {
17187         throw new Ember.Error(this.toString() + " could not respond to event " + event + " in state " + get(this, 'currentState.path') + ".");
17188       }
17189     }
17190   },
17191
17192   /**
17193     Finds a state by its state path.
17194
17195     Example:
17196
17197         manager = Ember.StateManager.create({
17198           root: Ember.State.create({
17199             dashboard: Ember.State.create()
17200           })
17201         });
17202
17203         manager.getStateByPath(manager, "root.dashboard")
17204
17205         // returns the dashboard state
17206
17207     @method getStateByPath
17208     @param {Ember.State} root the state to start searching from
17209     @param {String} path the state path to follow
17210     @return {Ember.State} the state at the end of the path
17211   */
17212   getStateByPath: function(root, path) {
17213     var parts = path.split('.'),
17214         state = root;
17215
17216     for (var i=0, len=parts.length; i<len; i++) {
17217       state = get(get(state, 'states'), parts[i]);
17218       if (!state) { break; }
17219     }
17220
17221     return state;
17222   },
17223
17224   findStateByPath: function(state, path) {
17225     var possible;
17226
17227     while (!possible && state) {
17228       possible = this.getStateByPath(state, path);
17229       state = get(state, 'parentState');
17230     }
17231
17232     return possible;
17233   },
17234
17235   /**
17236     A state stores its child states in its `states` hash.
17237     This code takes a path like `posts.show` and looks
17238     up `root.states.posts.states.show`.
17239
17240     It returns a list of all of the states from the
17241     root, which is the list of states to call `enter`
17242     on.
17243
17244     @method getStatesInPath
17245     @param root
17246     @param path
17247   */
17248   getStatesInPath: function(root, path) {
17249     if (!path || path === "") { return undefined; }
17250     var parts = path.split('.'),
17251         result = [],
17252         states,
17253         state;
17254
17255     for (var i=0, len=parts.length; i<len; i++) {
17256       states = get(root, 'states');
17257       if (!states) { return undefined; }
17258       state = get(states, parts[i]);
17259       if (state) { root = state; result.push(state); }
17260       else { return undefined; }
17261     }
17262
17263     return result;
17264   },
17265
17266   goToState: function() {
17267     // not deprecating this yet so people don't constantly need to
17268     // make trivial changes for little reason.
17269     return this.transitionTo.apply(this, arguments);
17270   },
17271
17272   transitionTo: function(path, context) {
17273     // XXX When is transitionTo called with no path
17274     if (Ember.empty(path)) { return; }
17275
17276     // The ES6 signature of this function is `path, ...contexts`
17277     var contexts = context ? Array.prototype.slice.call(arguments, 1) : [],
17278         currentState = get(this, 'currentState') || this;
17279
17280     // First, get the enter, exit and resolve states for the current state
17281     // and specified path. If possible, use an existing cache.
17282     var hash = this.contextFreeTransition(currentState, path);
17283
17284     // Next, process the raw state information for the contexts passed in.
17285     var transition = new Transition(hash).normalize(this, contexts);
17286
17287     this.enterState(transition);
17288     this.triggerSetupContext(transition);
17289   },
17290
17291   contextFreeTransition: function(currentState, path) {
17292     var cache = currentState.pathsCache[path];
17293     if (cache) { return cache; }
17294
17295     var enterStates = this.getStatesInPath(currentState, path),
17296         exitStates = [],
17297         resolveState = currentState;
17298
17299     // Walk up the states. For each state, check whether a state matching
17300     // the `path` is nested underneath. This will find the closest
17301     // parent state containing `path`.
17302     //
17303     // This allows the user to pass in a relative path. For example, for
17304     // the following state hierarchy:
17305     //
17306     //    | |root
17307     //    | |- posts
17308     //    | | |- show (* current)
17309     //    | |- comments
17310     //    | | |- show
17311     //
17312     // If the current state is `<root.posts.show>`, an attempt to
17313     // transition to `comments.show` will match `<root.comments.show>`.
17314     //
17315     // First, this code will look for root.posts.show.comments.show.
17316     // Next, it will look for root.posts.comments.show. Finally,
17317     // it will look for `root.comments.show`, and find the state.
17318     //
17319     // After this process, the following variables will exist:
17320     //
17321     // * resolveState: a common parent state between the current
17322     //   and target state. In the above example, `<root>` is the
17323     //   `resolveState`.
17324     // * enterStates: a list of all of the states represented
17325     //   by the path from the `resolveState`. For example, for
17326     //   the path `root.comments.show`, `enterStates` would have
17327     //   `[<root.comments>, <root.comments.show>]`
17328     // * exitStates: a list of all of the states from the
17329     //   `resolveState` to the `currentState`. In the above
17330     //   example, `exitStates` would have
17331     //   `[<root.posts>`, `<root.posts.show>]`.
17332     while (resolveState && !enterStates) {
17333       exitStates.unshift(resolveState);
17334
17335       resolveState = get(resolveState, 'parentState');
17336       if (!resolveState) {
17337         enterStates = this.getStatesInPath(this, path);
17338         if (!enterStates) {
17339           Ember.assert('Could not find state for path: "'+path+'"');
17340           return;
17341         }
17342       }
17343       enterStates = this.getStatesInPath(resolveState, path);
17344     }
17345
17346     // If the path contains some states that are parents of both the
17347     // current state and the target state, remove them.
17348     //
17349     // For example, in the following hierarchy:
17350     //
17351     // |- root
17352     // | |- post
17353     // | | |- index (* current)
17354     // | | |- show
17355     //
17356     // If the `path` is `root.post.show`, the three variables will
17357     // be:
17358     //
17359     // * resolveState: `<state manager>`
17360     // * enterStates: `[<root>, <root.post>, <root.post.show>]`
17361     // * exitStates: `[<root>, <root.post>, <root.post.index>]`
17362     //
17363     // The goal of this code is to remove the common states, so we
17364     // have:
17365     //
17366     // * resolveState: `<root.post>`
17367     // * enterStates: `[<root.post.show>]`
17368     // * exitStates: `[<root.post.index>]`
17369     //
17370     // This avoid unnecessary calls to the enter and exit transitions.
17371     while (enterStates.length > 0 && enterStates[0] === exitStates[0]) {
17372       resolveState = enterStates.shift();
17373       exitStates.shift();
17374     }
17375
17376     // Cache the enterStates, exitStates, and resolveState for the
17377     // current state and the `path`.
17378     var transitions = currentState.pathsCache[path] = {
17379       exitStates: exitStates,
17380       enterStates: enterStates,
17381       resolveState: resolveState
17382     };
17383
17384     return transitions;
17385   },
17386
17387   triggerSetupContext: function(transitions) {
17388     var contexts = transitions.contexts,
17389         offset = transitions.enterStates.length - contexts.length,
17390         enterStates = transitions.enterStates,
17391         transitionEvent = get(this, 'transitionEvent');
17392
17393     Ember.assert("More contexts provided than states", offset >= 0);
17394
17395     arrayForEach.call(enterStates, function(state, idx) {
17396       state.trigger(transitionEvent, this, contexts[idx-offset]);
17397     }, this);
17398   },
17399
17400   getState: function(name) {
17401     var state = get(this, name),
17402         parentState = get(this, 'parentState');
17403
17404     if (state) {
17405       return state;
17406     } else if (parentState) {
17407       return parentState.getState(name);
17408     }
17409   },
17410
17411   enterState: function(transition) {
17412     var log = this.enableLogging;
17413
17414     var exitStates = transition.exitStates.slice(0).reverse();
17415     arrayForEach.call(exitStates, function(state) {
17416       state.trigger('exit', this);
17417     }, this);
17418
17419     arrayForEach.call(transition.enterStates, function(state) {
17420       if (log) { Ember.Logger.log("STATEMANAGER: Entering " + get(state, 'path')); }
17421       state.trigger('enter', this);
17422     }, this);
17423
17424     set(this, 'currentState', transition.finalState);
17425   }
17426 });
17427
17428 })();
17429
17430
17431
17432 (function() {
17433 /**
17434 Ember States
17435
17436 @module ember
17437 @submodule ember-states
17438 @requires ember-runtime
17439 */
17440
17441 })();
17442
17443 (function() {
17444 var get = Ember.get;
17445
17446 Ember._ResolvedState = Ember.Object.extend({
17447   manager: null,
17448   state: null,
17449   match: null,
17450
17451   object: Ember.computed(function(key, value) {
17452     if (arguments.length === 2) {
17453       this._object = value;
17454       return value;
17455     } else {
17456       if (this._object) {
17457         return this._object;
17458       } else {
17459         var state = get(this, 'state'),
17460             match = get(this, 'match'),
17461             manager = get(this, 'manager');
17462         return state.deserialize(manager, match.hash);
17463       }
17464     }
17465   }).property(),
17466
17467   hasPromise: Ember.computed(function() {
17468     return Ember.canInvoke(get(this, 'object'), 'then');
17469   }).property('object'),
17470
17471   promise: Ember.computed(function() {
17472     var object = get(this, 'object');
17473     if (Ember.canInvoke(object, 'then')) {
17474       return object;
17475     } else {
17476       return {
17477         then: function(success) { success(object); }
17478       };
17479     }
17480   }).property('object'),
17481
17482   transition: function() {
17483     var manager = get(this, 'manager'),
17484         path = get(this, 'state.path'),
17485         object = get(this, 'object');
17486     manager.transitionTo(path, object);
17487   }
17488 });
17489
17490 })();
17491
17492
17493
17494 (function() {
17495 /**
17496 @module ember
17497 @submodule ember-routing
17498 */
17499
17500 var get = Ember.get;
17501
17502 // The Ember Routable mixin assumes the existance of a simple
17503 // routing shim that supports the following three behaviors:
17504 //
17505 // * .getURL() - this is called when the page loads
17506 // * .setURL(newURL) - this is called from within the state
17507 //   manager when the state changes to a routable state
17508 // * .onURLChange(callback) - this happens when the user presses
17509 //   the back or forward button
17510
17511 var paramForClass = function(classObject) {
17512   var className = classObject.toString(),
17513       parts = className.split("."),
17514       last = parts[parts.length - 1];
17515
17516   return Ember.String.underscore(last) + "_id";
17517 };
17518
17519 var merge = function(original, hash) {
17520   for (var prop in hash) {
17521     if (!hash.hasOwnProperty(prop)) { continue; }
17522     if (original.hasOwnProperty(prop)) { continue; }
17523
17524     original[prop] = hash[prop];
17525   }
17526 };
17527
17528 /**
17529   @class Routable
17530   @namespace Ember
17531   @extends Ember.Mixin
17532 */
17533 Ember.Routable = Ember.Mixin.create({
17534   init: function() {
17535     var redirection;
17536     this.on('setup', this, this.stashContext);
17537
17538     if (redirection = get(this, 'redirectsTo')) {
17539       Ember.assert("You cannot use `redirectsTo` if you already have a `connectOutlets` method", this.connectOutlets === Ember.K);
17540
17541       this.connectOutlets = function(router) {
17542         router.transitionTo(redirection);
17543       };
17544     }
17545
17546     // normalize empty route to '/'
17547     var route = get(this, 'route');
17548     if (route === '') {
17549       route = '/';
17550     }
17551
17552     this._super();
17553
17554     Ember.assert("You cannot use `redirectsTo` on a state that has child states", !redirection || (!!redirection && !!get(this, 'isLeaf')));
17555   },
17556
17557   setup: function() {
17558     return this.connectOutlets.apply(this, arguments);
17559   },
17560
17561   /**
17562     @private
17563
17564     Whenever a routable state is entered, the context it was entered with
17565     is stashed so that we can regenerate the state's `absoluteURL` on
17566     demand.
17567
17568     @method stashContext
17569     @param manager {Ember.StateManager}
17570     @param context
17571   */
17572   stashContext: function(manager, context) {
17573     this.router = manager;
17574
17575     var serialized = this.serialize(manager, context);
17576     Ember.assert('serialize must return a hash', !serialized || typeof serialized === 'object');
17577
17578     manager.setStateMeta(this, 'context', context);
17579     manager.setStateMeta(this, 'serialized', serialized);
17580
17581     if (get(this, 'isRoutable') && !get(manager, 'isRouting')) {
17582       this.updateRoute(manager, get(manager, 'location'));
17583     }
17584   },
17585
17586   /**
17587     @private
17588
17589     Whenever a routable state is entered, the router's location object
17590     is notified to set the URL to the current absolute path.
17591
17592     In general, this will update the browser's URL.
17593
17594     @method updateRoute
17595     @param manager {Ember.StateManager}
17596     @param location {Ember.Location}
17597   */
17598   updateRoute: function(manager, location) {
17599     if (get(this, 'isLeafRoute')) {
17600       var path = this.absoluteRoute(manager);
17601       location.setURL(path);
17602     }
17603   },
17604
17605   /**
17606     @private
17607
17608     Get the absolute route for the current state and a given
17609     hash.
17610
17611     This method is private, as it expects a serialized hash,
17612     not the original context object.
17613
17614     @method absoluteRoute
17615     @param manager {Ember.StateManager}
17616     @param hash {Hash}
17617   */
17618   absoluteRoute: function(manager, hash) {
17619     var parentState = get(this, 'parentState');
17620     var path = '', generated;
17621
17622     // If the parent state is routable, use its current path
17623     // as this route's prefix.
17624     if (get(parentState, 'isRoutable')) {
17625       path = parentState.absoluteRoute(manager, hash);
17626     }
17627
17628     var matcher = get(this, 'routeMatcher'),
17629         serialized = manager.getStateMeta(this, 'serialized');
17630
17631     // merge the existing serialized object in with the passed
17632     // in hash.
17633     hash = hash || {};
17634     merge(hash, serialized);
17635
17636     generated = matcher && matcher.generate(hash);
17637
17638     if (generated) {
17639       path = path + '/' + generated;
17640     }
17641
17642     return path;
17643   },
17644
17645   /**
17646     @private
17647
17648     At the moment, a state is routable if it has a string `route`
17649     property. This heuristic may change.
17650
17651     @property isRoutable
17652     @type Boolean
17653   */
17654   isRoutable: Ember.computed(function() {
17655     return typeof get(this, 'route') === 'string';
17656   }),
17657
17658   /**
17659     @private
17660
17661     Determine if this is the last routeable state
17662
17663     @property isLeafRoute
17664     @type Boolean
17665   */
17666   isLeafRoute: Ember.computed(function() {
17667     if (get(this, 'isLeaf')) { return true; }
17668     return !get(this, 'childStates').findProperty('isRoutable');
17669   }),
17670
17671   /**
17672     @private
17673
17674     A _RouteMatcher object generated from the current route's `route`
17675     string property.
17676
17677     @property routeMatcher
17678     @type Ember._RouteMatcher
17679   */
17680   routeMatcher: Ember.computed(function() {
17681     var route = get(this, 'route');
17682     if (route) {
17683       return Ember._RouteMatcher.create({ route: route });
17684     }
17685   }),
17686
17687   /**
17688     @private
17689
17690     Check whether the route has dynamic segments and therefore takes
17691     a context.
17692
17693     @property hasContext
17694     @type Boolean
17695   */
17696   hasContext: Ember.computed(function() {
17697     var routeMatcher = get(this, 'routeMatcher');
17698     if (routeMatcher) {
17699       return routeMatcher.identifiers.length > 0;
17700     }
17701   }),
17702
17703   /**
17704     @private
17705
17706     The model class associated with the current state. This property
17707     uses the `modelType` property, in order to allow it to be
17708     specified as a String.
17709
17710     @property modelClass
17711     @type Ember.Object
17712   */
17713   modelClass: Ember.computed(function() {
17714     var modelType = get(this, 'modelType');
17715
17716     if (typeof modelType === 'string') {
17717       return Ember.get(Ember.lookup, modelType);
17718     } else {
17719       return modelType;
17720     }
17721   }),
17722
17723   /**
17724     @private
17725
17726     Get the model class for the state. The heuristic is:
17727
17728     * The state must have a single dynamic segment
17729     * The dynamic segment must end in `_id`
17730     * A dynamic segment like `blog_post_id` is converted into `BlogPost`
17731     * The name is then looked up on the passed in namespace
17732
17733     The process of initializing an application with a router will
17734     pass the application's namespace into the router, which will be
17735     used here.
17736
17737     @method modelClassFor
17738     @param namespace {Ember.Namespace}
17739   */
17740   modelClassFor: function(namespace) {
17741     var modelClass, routeMatcher, identifiers, match, className;
17742
17743     // if an explicit modelType was specified, use that
17744     if (modelClass = get(this, 'modelClass')) { return modelClass; }
17745
17746     // if the router has no lookup namespace, we won't be able to guess
17747     // the modelType
17748     if (!namespace) { return; }
17749
17750     // make sure this state is actually a routable state
17751     routeMatcher = get(this, 'routeMatcher');
17752     if (!routeMatcher) { return; }
17753
17754     // only guess modelType for states with a single dynamic segment
17755     // (no more, no fewer)
17756     identifiers = routeMatcher.identifiers;
17757     if (identifiers.length !== 2) { return; }
17758
17759     // extract the `_id` from the end of the dynamic segment; if the
17760     // dynamic segment does not end in `_id`, we can't guess the
17761     // modelType
17762     match = identifiers[1].match(/^(.*)_id$/);
17763     if (!match) { return; }
17764
17765     // convert the underscored type into a class form and look it up
17766     // on the router's namespace
17767     className = Ember.String.classify(match[1]);
17768     return get(namespace, className);
17769   },
17770
17771   /**
17772     The default method that takes a `params` object and converts
17773     it into an object.
17774
17775     By default, a params hash that looks like `{ post_id: 1 }`
17776     will be looked up as `namespace.Post.find(1)`. This is
17777     designed to work seamlessly with Ember Data, but will work
17778     fine with any class that has a `find` method.
17779
17780     @method deserialize
17781     @param manager {Ember.StateManager}
17782     @param params {Hash}
17783   */
17784   deserialize: function(manager, params) {
17785     var modelClass, routeMatcher, param;
17786
17787     if (modelClass = this.modelClassFor(get(manager, 'namespace'))) {
17788       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);
17789       return modelClass.find(params[paramForClass(modelClass)]);
17790     }
17791
17792     return params;
17793   },
17794
17795   /**
17796     The default method that takes an object and converts it into
17797     a params hash.
17798
17799     By default, if there is a single dynamic segment named
17800     `blog_post_id` and the object is a `BlogPost` with an
17801     `id` of `12`, the serialize method will produce:
17802
17803         { blog_post_id: 12 }
17804
17805     @method serialize
17806     @param manager {Ember.StateManager}
17807     @param context
17808   */
17809   serialize: function(manager, context) {
17810     var modelClass, routeMatcher, namespace, param, id;
17811
17812     if (Ember.empty(context)) { return ''; }
17813
17814     if (modelClass = this.modelClassFor(get(manager, 'namespace'))) {
17815       param = paramForClass(modelClass);
17816       id = get(context, 'id');
17817       context = {};
17818       context[param] = id;
17819     }
17820
17821     return context;
17822   },
17823
17824   /**
17825     @private
17826     @method resolvePath
17827     @param manager {Ember.StateManager}
17828     @param path {String}
17829   */
17830   resolvePath: function(manager, path) {
17831     if (get(this, 'isLeafRoute')) { return Ember.A(); }
17832
17833     var childStates = get(this, 'childStates'), match;
17834
17835     childStates = Ember.A(childStates.filterProperty('isRoutable'));
17836
17837     childStates = childStates.sort(function(a, b) {
17838       var aDynamicSegments = get(a, 'routeMatcher.identifiers.length'),
17839           bDynamicSegments = get(b, 'routeMatcher.identifiers.length'),
17840           aRoute = get(a, 'route'),
17841           bRoute = get(b, 'route');
17842
17843       if (aRoute.indexOf(bRoute) === 0) {
17844         return -1;
17845       } else if (bRoute.indexOf(aRoute) === 0) {
17846         return 1;
17847       }
17848
17849       if (aDynamicSegments !== bDynamicSegments) {
17850         return aDynamicSegments - bDynamicSegments;
17851       }
17852
17853       return get(b, 'route.length') - get(a, 'route.length');
17854     });
17855
17856     var state = childStates.find(function(state) {
17857       var matcher = get(state, 'routeMatcher');
17858       if (match = matcher.match(path)) { return true; }
17859     });
17860
17861     Ember.assert("Could not find state for path " + path, !!state);
17862
17863     var resolvedState = Ember._ResolvedState.create({
17864       manager: manager,
17865       state: state,
17866       match: match
17867     });
17868
17869     var states = state.resolvePath(manager, match.remaining);
17870
17871     return Ember.A([resolvedState]).pushObjects(states);
17872   },
17873
17874   /**
17875     @private
17876
17877     Once `unroute` has finished unwinding, `routePath` will be called
17878     with the remainder of the route.
17879
17880     For example, if you were in the /posts/1/comments state, and you
17881     moved into the /posts/2/comments state, `routePath` will be called
17882     on the state whose path is `/posts` with the path `/2/comments`.
17883
17884     @method routePath
17885     @param manager {Ember.StateManager}
17886     @param path {String}
17887   */
17888   routePath: function(manager, path) {
17889     if (get(this, 'isLeafRoute')) { return; }
17890
17891     var resolvedStates = this.resolvePath(manager, path),
17892         hasPromises = resolvedStates.some(function(s) { return get(s, 'hasPromise'); });
17893
17894     function runTransition() {
17895       resolvedStates.forEach(function(rs) { rs.transition(); });
17896     }
17897
17898     if (hasPromises) {
17899       manager.transitionTo('loading');
17900
17901       Ember.assert('Loading state should be the child of a route', Ember.Routable.detect(get(manager, 'currentState.parentState')));
17902       Ember.assert('Loading state should not be a route', !Ember.Routable.detect(get(manager, 'currentState')));
17903
17904       manager.handleStatePromises(resolvedStates, runTransition);
17905     } else {
17906       runTransition();
17907     }
17908   },
17909
17910   /**
17911     @private
17912
17913     When you move to a new route by pressing the back
17914     or forward button, this method is called first.
17915
17916     Its job is to move the state manager into a parent
17917     state of the state it will eventually move into.
17918
17919     @method unroutePath
17920     @param router {Ember.Router}
17921     @param path {String}
17922   */
17923   unroutePath: function(router, path) {
17924     var parentState = get(this, 'parentState');
17925
17926     // If we're at the root state, we're done
17927     if (parentState === router) {
17928       return;
17929     }
17930
17931     path = path.replace(/^(?=[^\/])/, "/");
17932     var absolutePath = this.absoluteRoute(router);
17933
17934     var route = get(this, 'route');
17935
17936     // If the current path is empty, move up one state,
17937     // because the index ('/') state must be a leaf node.
17938     if (route !== '/') {
17939       // If the current path is a prefix of the path we're trying
17940       // to go to, we're done.
17941       var index = path.indexOf(absolutePath),
17942           next = path.charAt(absolutePath.length);
17943
17944       if (index === 0 && (next === "/" || next === "")) {
17945         return;
17946       }
17947     }
17948
17949     // Transition to the parent and call unroute again.
17950     router.enterState({
17951       exitStates: [this],
17952       enterStates: [],
17953       finalState: parentState
17954     });
17955
17956     router.send('unroutePath', path);
17957   },
17958
17959   parentTemplate: Ember.computed(function() {
17960     var state = this, parentState, template;
17961
17962     while (state = get(state, 'parentState')) {
17963       if (template = get(state, 'template')) {
17964         return template;
17965       }
17966     }
17967
17968     return 'application';
17969   }),
17970
17971   _template: Ember.computed(function(key, value) {
17972     if (arguments.length > 1) { return value; }
17973
17974     if (value = get(this, 'template')) {
17975       return value;
17976     }
17977
17978     // If no template was explicitly supplied convert
17979     // the class name into a template name. For example,
17980     // App.PostRoute will return `post`.
17981     var className = this.constructor.toString(), baseName;
17982     if (/^[^\[].*Route$/.test(className)) {
17983       baseName = className.match(/([^\.]+\.)*([^\.]+)/)[2];
17984       baseName = baseName.replace(/Route$/, '');
17985       return baseName.charAt(0).toLowerCase() + baseName.substr(1);
17986     }
17987   }),
17988
17989   render: function(options) {
17990     options = options || {};
17991
17992     var template = options.template || get(this, '_template'),
17993         parentTemplate = options.into || get(this, 'parentTemplate'),
17994         controller = get(this.router, parentTemplate + "Controller");
17995
17996     var viewName = Ember.String.classify(template) + "View",
17997         viewClass = get(get(this.router, 'namespace'), viewName);
17998
17999     viewClass = (viewClass || Ember.View).extend({
18000       templateName: template
18001     });
18002
18003     controller.set('view', viewClass.create());
18004   },
18005
18006   /**
18007     The `connectOutlets` event will be triggered once a
18008     state has been entered. It will be called with the
18009     route's context.
18010
18011     @event connectOutlets
18012     @param router {Ember.Router}
18013     @param [context*]
18014   */
18015   connectOutlets: Ember.K,
18016
18017   /**
18018    The `navigateAway` event will be triggered when the
18019    URL changes due to the back/forward button
18020
18021    @event navigateAway
18022   */
18023   navigateAway: Ember.K
18024 });
18025
18026 })();
18027
18028
18029
18030 (function() {
18031 /**
18032 @module ember
18033 @submodule ember-routing
18034 */
18035
18036 /**
18037   @class Route
18038   @namespace Ember
18039   @extends Ember.State
18040   @uses Ember.Routable
18041 */
18042 Ember.Route = Ember.State.extend(Ember.Routable);
18043
18044 })();
18045
18046
18047
18048 (function() {
18049 var escapeForRegex = function(text) {
18050   return text.replace(/[\-\[\]{}()*+?.,\\\^\$|#\s]/g, "\\$&");
18051 };
18052
18053 /**
18054   @class _RouteMatcher
18055   @namespace Ember
18056   @private
18057   @extends Ember.Object
18058 */
18059 Ember._RouteMatcher = Ember.Object.extend({
18060   state: null,
18061
18062   init: function() {
18063     var route = this.route,
18064         identifiers = [],
18065         count = 1,
18066         escaped;
18067
18068     // Strip off leading slash if present
18069     if (route.charAt(0) === '/') {
18070       route = this.route = route.substr(1);
18071     }
18072
18073     escaped = escapeForRegex(route);
18074
18075     var regex = escaped.replace(/(:|(?:\\\*))([a-z_]+)(?=$|\/)/gi, function(match, type, id) {
18076       identifiers[count++] = id;
18077       switch (type) {
18078         case ":":
18079           return "([^/]+)";
18080         case "\\*":
18081           return "(.+)";
18082       }
18083     });
18084
18085     this.identifiers = identifiers;
18086     this.regex = new RegExp("^/?" + regex);
18087   },
18088
18089   match: function(path) {
18090     var match = path.match(this.regex);
18091
18092     if (match) {
18093       var identifiers = this.identifiers,
18094           hash = {};
18095
18096       for (var i=1, l=identifiers.length; i<l; i++) {
18097         hash[identifiers[i]] = match[i];
18098       }
18099
18100       return {
18101         remaining: path.substr(match[0].length),
18102         hash: identifiers.length > 0 ? hash : null
18103       };
18104     }
18105   },
18106
18107   generate: function(hash) {
18108     var identifiers = this.identifiers, route = this.route, id;
18109     for (var i=1, l=identifiers.length; i<l; i++) {
18110       id = identifiers[i];
18111       route = route.replace(new RegExp("(:|(\\*))" + id), hash[id]);
18112     }
18113     return route;
18114   }
18115 });
18116
18117 })();
18118
18119
18120
18121 (function() {
18122 /**
18123 @module ember
18124 @submodule ember-routing
18125 */
18126
18127 var get = Ember.get, set = Ember.set;
18128
18129 /*
18130   This file implements the `location` API used by Ember's router.
18131
18132   That API is:
18133
18134   getURL: returns the current URL
18135   setURL(path): sets the current URL
18136   onUpdateURL(callback): triggers the callback when the URL changes
18137   formatURL(url): formats `url` to be placed into `href` attribute
18138
18139   Calling setURL will not trigger onUpdateURL callbacks.
18140
18141   TODO: This should perhaps be moved so that it's visible in the doc output.
18142 */
18143
18144 /**
18145   Ember.Location returns an instance of the correct implementation of
18146   the `location` API.
18147
18148   You can pass it a `implementation` ('hash', 'history', 'none') to force a
18149   particular implementation.
18150
18151   @class Location
18152   @namespace Ember
18153   @static
18154 */
18155 Ember.Location = {
18156   create: function(options) {
18157     var implementation = options && options.implementation;
18158     Ember.assert("Ember.Location.create: you must specify a 'implementation' option", !!implementation);
18159
18160     var implementationClass = this.implementations[implementation];
18161     Ember.assert("Ember.Location.create: " + implementation + " is not a valid implementation", !!implementationClass);
18162
18163     return implementationClass.create.apply(implementationClass, arguments);
18164   },
18165
18166   registerImplementation: function(name, implementation) {
18167     this.implementations[name] = implementation;
18168   },
18169
18170   implementations: {}
18171 };
18172
18173 })();
18174
18175
18176
18177 (function() {
18178 /**
18179 @module ember
18180 @submodule ember-routing
18181 */
18182
18183 var get = Ember.get, set = Ember.set;
18184
18185 /**
18186   Ember.NoneLocation does not interact with the browser. It is useful for
18187   testing, or when you need to manage state with your Router, but temporarily
18188   don't want it to muck with the URL (for example when you embed your
18189   application in a larger page).
18190
18191   @class NoneLocation
18192   @namespace Ember
18193   @extends Ember.Object
18194 */
18195 Ember.NoneLocation = Ember.Object.extend({
18196   path: '',
18197
18198   getURL: function() {
18199     return get(this, 'path');
18200   },
18201
18202   setURL: function(path) {
18203     set(this, 'path', path);
18204   },
18205
18206   onUpdateURL: function(callback) {
18207     // We are not wired up to the browser, so we'll never trigger the callback.
18208   },
18209
18210   formatURL: function(url) {
18211     // The return value is not overly meaningful, but we do not want to throw
18212     // errors when test code renders templates containing {{action href=true}}
18213     // helpers.
18214     return url;
18215   }
18216 });
18217
18218 Ember.Location.registerImplementation('none', Ember.NoneLocation);
18219
18220 })();
18221
18222
18223
18224 (function() {
18225 /**
18226 @module ember
18227 @submodule ember-routing
18228 */
18229
18230 var get = Ember.get, set = Ember.set;
18231
18232 /**
18233   Ember.HashLocation implements the location API using the browser's
18234   hash. At present, it relies on a hashchange event existing in the
18235   browser.
18236
18237   @class HashLocation
18238   @namespace Ember
18239   @extends Ember.Object
18240 */
18241 Ember.HashLocation = Ember.Object.extend({
18242
18243   init: function() {
18244     set(this, 'location', get(this, 'location') || window.location);
18245   },
18246
18247   /**
18248     @private
18249
18250     Returns the current `location.hash`, minus the '#' at the front.
18251
18252     @method getURL
18253   */
18254   getURL: function() {
18255     return get(this, 'location').hash.substr(1);
18256   },
18257
18258   /**
18259     @private
18260
18261     Set the `location.hash` and remembers what was set. This prevents
18262     `onUpdateURL` callbacks from triggering when the hash was set by
18263     `HashLocation`.
18264
18265     @method setURL
18266     @param path {String}
18267   */
18268   setURL: function(path) {
18269     get(this, 'location').hash = path;
18270     set(this, 'lastSetURL', path);
18271   },
18272
18273   /**
18274     @private
18275
18276     Register a callback to be invoked when the hash changes. These
18277     callbacks will execute when the user presses the back or forward
18278     button, but not after `setURL` is invoked.
18279
18280     @method onUpdateURL
18281     @param callback {Function}
18282   */
18283   onUpdateURL: function(callback) {
18284     var self = this;
18285     var guid = Ember.guidFor(this);
18286
18287     Ember.$(window).bind('hashchange.ember-location-'+guid, function() {
18288       var path = location.hash.substr(1);
18289       if (get(self, 'lastSetURL') === path) { return; }
18290
18291       set(self, 'lastSetURL', null);
18292
18293       callback(location.hash.substr(1));
18294     });
18295   },
18296
18297   /**
18298     @private
18299
18300     Given a URL, formats it to be placed into the page as part
18301     of an element's `href` attribute.
18302
18303     This is used, for example, when using the {{action}} helper
18304     to generate a URL based on an event.
18305
18306     @method formatURL
18307     @param url {String}
18308   */
18309   formatURL: function(url) {
18310     return '#'+url;
18311   },
18312
18313   willDestroy: function() {
18314     var guid = Ember.guidFor(this);
18315
18316     Ember.$(window).unbind('hashchange.ember-location-'+guid);
18317   }
18318 });
18319
18320 Ember.Location.registerImplementation('hash', Ember.HashLocation);
18321
18322 })();
18323
18324
18325
18326 (function() {
18327 /**
18328 @module ember
18329 @submodule ember-routing
18330 */
18331
18332 var get = Ember.get, set = Ember.set;
18333 var popstateReady = false;
18334
18335 /**
18336   Ember.HistoryLocation implements the location API using the browser's
18337   history.pushState API.
18338
18339   @class HistoryLocation
18340   @namespace Ember
18341   @extends Ember.Object
18342 */
18343 Ember.HistoryLocation = Ember.Object.extend({
18344
18345   init: function() {
18346     set(this, 'location', get(this, 'location') || window.location);
18347     this.initState();
18348   },
18349
18350   /**
18351     @private
18352
18353     Used to set state on first call to setURL
18354
18355     @method initState
18356   */
18357   initState: function() {
18358     this.replaceState(get(this, 'location').pathname);
18359     set(this, 'history', window.history);
18360   },
18361
18362   /**
18363     Will be pre-pended to path upon state change
18364
18365     @property rootURL
18366     @default '/'
18367   */
18368   rootURL: '/',
18369
18370   /**
18371     @private
18372
18373     Returns the current `location.pathname`.
18374
18375     @method getURL
18376   */
18377   getURL: function() {
18378     return get(this, 'location').pathname;
18379   },
18380
18381   /**
18382     @private
18383
18384     Uses `history.pushState` to update the url without a page reload.
18385
18386     @method setURL
18387     @param path {String}
18388   */
18389   setURL: function(path) {
18390     path = this.formatURL(path);
18391
18392     if (this.getState().path !== path) {
18393       popstateReady = true;
18394       this.pushState(path);
18395     }
18396   },
18397
18398   /**
18399    @private
18400
18401    Get the current `history.state`
18402
18403    @method getState
18404   */
18405   getState: function() {
18406     return get(this, 'history').state;
18407   },
18408
18409   /**
18410    @private
18411
18412    Pushes a new state
18413
18414    @method pushState
18415    @param path {String}
18416   */
18417   pushState: function(path) {
18418     window.history.pushState({ path: path }, null, path);
18419   },
18420
18421   /**
18422    @private
18423
18424    Replaces the current state
18425
18426    @method replaceState
18427    @param path {String}
18428   */
18429   replaceState: function(path) {
18430     window.history.replaceState({ path: path }, null, path);
18431   },
18432
18433   /**
18434     @private
18435
18436     Register a callback to be invoked whenever the browser
18437     history changes, including using forward and back buttons.
18438
18439     @method onUpdateURL
18440     @param callback {Function}
18441   */
18442   onUpdateURL: function(callback) {
18443     var guid = Ember.guidFor(this);
18444
18445     Ember.$(window).bind('popstate.ember-location-'+guid, function(e) {
18446       if(!popstateReady) {
18447         return;
18448       }
18449       callback(location.pathname);
18450     });
18451   },
18452
18453   /**
18454     @private
18455
18456     Used when using `{{action}}` helper.  The url is always appended to the rootURL.
18457
18458     @method formatURL
18459     @param url {String}
18460   */
18461   formatURL: function(url) {
18462     var rootURL = get(this, 'rootURL');
18463
18464     if (url !== '') {
18465       rootURL = rootURL.replace(/\/$/, '');
18466     }
18467
18468     return rootURL + url;
18469   },
18470
18471   willDestroy: function() {
18472     var guid = Ember.guidFor(this);
18473
18474     Ember.$(window).unbind('popstate.ember-location-'+guid);
18475   }
18476 });
18477
18478 Ember.Location.registerImplementation('history', Ember.HistoryLocation);
18479
18480 })();
18481
18482
18483
18484 (function() {
18485
18486 })();
18487
18488
18489
18490 (function() {
18491 /**
18492 @module ember
18493 @submodule ember-routing
18494 */
18495
18496 var get = Ember.get, set = Ember.set;
18497
18498 var merge = function(original, hash) {
18499   for (var prop in hash) {
18500     if (!hash.hasOwnProperty(prop)) { continue; }
18501     if (original.hasOwnProperty(prop)) { continue; }
18502
18503     original[prop] = hash[prop];
18504   }
18505 };
18506
18507 /**
18508   `Ember.Router` is the subclass of `Ember.StateManager` responsible for providing URL-based
18509   application state detection. The `Ember.Router` instance of an application detects the browser URL
18510   at application load time and attempts to match it to a specific application state. Additionally
18511   the router will update the URL to reflect an application's state changes over time.
18512
18513   ## Adding a Router Instance to Your Application
18514   An instance of Ember.Router can be associated with an instance of Ember.Application in one of two ways:
18515
18516   You can provide a subclass of Ember.Router as the `Router` property of your application. An instance
18517   of this Router class will be instantiated and route detection will be enabled when the application's
18518   `initialize` method is called. The Router instance will be available as the `router` property
18519   of the application:
18520
18521       App = Ember.Application.create({
18522         Router: Ember.Router.extend({ ... })
18523       });
18524
18525       App.initialize();
18526       App.get('router') // an instance of App.Router
18527
18528   If you want to define a Router instance elsewhere, you can pass the instance to the application's
18529   `initialize` method:
18530
18531       App = Ember.Application.create();
18532       aRouter = Ember.Router.create({ ... });
18533
18534       App.initialize(aRouter);
18535       App.get('router') // aRouter
18536
18537   ## Adding Routes to a Router
18538   The `initialState` property of Ember.Router instances is named `root`. The state stored in this
18539   property must be a subclass of Ember.Route. The `root` route acts as the container for the
18540   set of routable states but is not routable itself. It should have states that are also subclasses
18541   of Ember.Route which each have a `route` property describing the URL pattern you would like to detect.
18542
18543       App = Ember.Application.create({
18544         Router: Ember.Router.extend({
18545           root: Ember.Route.extend({
18546             index: Ember.Route.extend({
18547               route: '/'
18548             }),
18549             ... additional Ember.Routes ...
18550           })
18551         })
18552       });
18553       App.initialize();
18554
18555
18556   When an application loads, Ember will parse the URL and attempt to find an Ember.Route within
18557   the application's states that matches. (The example URL-matching below will use the default
18558   'hash syntax' provided by `Ember.HashLocation`.)
18559
18560   In the following route structure:
18561
18562       App = Ember.Application.create({
18563         Router: Ember.Router.extend({
18564           root: Ember.Route.extend({
18565             aRoute: Ember.Route.extend({
18566               route: '/'
18567             }),
18568             bRoute: Ember.Route.extend({
18569               route: '/alphabeta'
18570             })
18571           })
18572         })
18573       });
18574       App.initialize();
18575
18576   Loading the page at the URL '#/' will detect the route property of 'root.aRoute' ('/') and
18577   transition the router first to the state named 'root' and then to the substate 'aRoute'.
18578
18579   Respectively, loading the page at the URL '#/alphabeta' would detect the route property of
18580   'root.bRoute' ('/alphabeta') and transition the router first to the state named 'root' and
18581   then to the substate 'bRoute'.
18582
18583   ## Adding Nested Routes to a Router
18584   Routes can contain nested subroutes each with their own `route` property describing the nested
18585   portion of the URL they would like to detect and handle. Router, like all instances of StateManager,
18586   cannot call `transitonTo` with an intermediary state. To avoid transitioning the Router into an
18587   intermediary state when detecting URLs, a Route with nested routes must define both a base `route`
18588   property for itself and a child Route with a `route` property of `'/'` which will be transitioned
18589   to when the base route is detected in the URL:
18590
18591   Given the following application code:
18592
18593       App = Ember.Application.create({
18594         Router: Ember.Router.extend({
18595           root: Ember.Route.extend({
18596             aRoute: Ember.Route.extend({
18597               route: '/theBaseRouteForThisSet',
18598
18599               indexSubRoute: Ember.Route.extend({
18600                 route: '/'
18601               }),
18602
18603               subRouteOne: Ember.Route.extend({
18604                 route: '/subroute1'
18605               }),
18606
18607               subRouteTwo: Ember.Route.extend({
18608                 route: '/subRoute2'
18609               })
18610
18611             })
18612           })
18613         })
18614       });
18615       App.initialize();
18616
18617   When the application is loaded at '/theBaseRouteForThisSet' the Router will transition to the route
18618   at path 'root.aRoute' and then transition to state 'indexSubRoute'.
18619
18620   When the application is loaded at '/theBaseRouteForThisSet/subRoute1' the Router will transition to
18621   the route at path 'root.aRoute' and then transition to state 'subRouteOne'.
18622
18623   ## Route Transition Events
18624   Transitioning between Ember.Route instances (including the transition into the detected
18625   route when loading the application)  triggers the same transition events as state transitions for
18626   base `Ember.State`s. However, the default `setup` transition event is named `connectOutlets` on
18627   Ember.Router instances (see 'Changing View Hierarchy in Response To State Change').
18628
18629   The following route structure when loaded with the URL "#/"
18630
18631       App = Ember.Application.create({
18632         Router: Ember.Router.extend({
18633           root: Ember.Route.extend({
18634             aRoute: Ember.Route.extend({
18635               route: '/',
18636               enter: function(router) {
18637                 console.log("entering root.aRoute from", router.get('currentState.name'));
18638               },
18639               connectOutlets: function(router) {
18640                 console.log("entered root.aRoute, fully transitioned to", router.get('currentState.path'));
18641               }
18642             })
18643           })
18644         })
18645       });
18646       App.initialize();
18647
18648   Will result in console output of:
18649
18650       'entering root.aRoute from root'
18651       'entered root.aRoute, fully transitioned to root.aRoute '
18652
18653   Ember.Route has two additional callbacks for handling URL serialization and deserialization. See
18654   'Serializing/Deserializing URLs'
18655
18656   ## Routes With Dynamic Segments
18657   An Ember.Route's `route` property can reference dynamic sections of the URL by prefacing a URL segment
18658   with the ':' character.  The values of these dynamic segments will be passed as a hash to the
18659   `deserialize` method of the matching Route (see 'Serializing/Deserializing URLs').
18660
18661   ## Serializing/Deserializing URLs
18662   Ember.Route has two callbacks for associating a particular object context with a URL: `serialize`
18663   for converting an object into a parameters hash to fill dynamic segments of a URL and `deserialize`
18664   for converting a hash of dynamic segments from the URL into the appropriate object.
18665
18666   ### Deserializing A URL's Dynamic Segments
18667   When an application is first loaded or the URL is changed manually (e.g. through the browser's
18668   back button) the `deserialize` method of the URL's matching Ember.Route will be called with
18669   the application's router as its first argument and a hash of the URL's dynamic segments and values
18670   as its second argument.
18671
18672   The following route structure when loaded with the URL "#/fixed/thefirstvalue/anotherFixed/thesecondvalue":
18673
18674       App = Ember.Application.create({
18675         Router: Ember.Router.extend({
18676           root: Ember.Route.extend({
18677             aRoute: Ember.Route.extend({
18678               route: '/fixed/:dynamicSectionA/anotherFixed/:dynamicSectionB',
18679               deserialize: function(router, params) {}
18680             })
18681           })
18682         })
18683       });
18684       App.initialize();
18685
18686   Will call the 'deserialize' method of the Route instance at the path 'root.aRoute' with the
18687   following hash as its second argument:
18688
18689       {
18690         dynamicSectionA: 'thefirstvalue',
18691         dynamicSectionB: 'thesecondvalue'
18692       }
18693
18694   Within `deserialize` you should use this information to retrieve or create an appropriate context
18695   object for the given URL (e.g. by loading from a remote API or accessing the browser's
18696   `localStorage`). This object must be the `return` value of `deserialize` and will be
18697   passed to the Route's `connectOutlets` and `serialize` methods.
18698
18699   When an application's state is changed from within the application itself, the context provided for
18700   the transition will be passed and `deserialize` is not called (see 'Transitions Between States').
18701
18702   ### Serializing An Object For URLs with Dynamic Segments
18703   When transitioning into a Route whose `route` property contains dynamic segments the Route's
18704   `serialize` method is called with the Route's router as the first argument and the Route's
18705   context as the second argument.  The return value of `serialize` will be used to populate the
18706   dynamic segments and should be an object with keys that match the names of the dynamic sections.
18707
18708   Given the following route structure:
18709
18710       App = Ember.Application.create({
18711         Router: Ember.Router.extend({
18712           root: Ember.Route.extend({
18713             aRoute: Ember.Route.extend({
18714               route: '/'
18715             }),
18716             bRoute: Ember.Route.extend({
18717               route: '/staticSection/:someDynamicSegment',
18718               serialize: function(router, context) {
18719                 return {
18720                   someDynamicSegment: context.get('name')
18721                 }
18722               }
18723             })
18724           })
18725         })
18726       });
18727       App.initialize();
18728
18729
18730   Transitioning to "root.bRoute" with a context of `Object.create({name: 'Yehuda'})` will call
18731   the Route's `serialize` method with the context as its second argument and update the URL to
18732   '#/staticSection/Yehuda'.
18733
18734   ## Transitions Between States
18735   Once a routed application has initialized its state based on the entry URL, subsequent transitions to other
18736   states will update the URL if the entered Route has a `route` property. Given the following route structure
18737   loaded at the URL '#/':
18738
18739       App = Ember.Application.create({
18740         Router: Ember.Router.extend({
18741           root: Ember.Route.extend({
18742             aRoute: Ember.Route.extend({
18743               route: '/',
18744               moveElsewhere: Ember.Route.transitionTo('bRoute')
18745             }),
18746             bRoute: Ember.Route.extend({
18747               route: '/someOtherLocation'
18748             })
18749           })
18750         })
18751       });
18752       App.initialize();
18753
18754   And application code:
18755
18756       App.get('router').send('moveElsewhere');
18757
18758   Will transition the application's state to 'root.bRoute' and trigger an update of the URL to
18759   '#/someOtherLocation'.
18760
18761   For URL patterns with dynamic segments a context can be supplied as the second argument to `send`.
18762   The router will match dynamic segments names to keys on this object and fill in the URL with the
18763   supplied values. Given the following state structure loaded at the URL '#/':
18764
18765       App = Ember.Application.create({
18766         Router: Ember.Router.extend({
18767           root: Ember.Route.extend({
18768             aRoute: Ember.Route.extend({
18769               route: '/',
18770               moveElsewhere: Ember.Route.transitionTo('bRoute')
18771             }),
18772             bRoute: Ember.Route.extend({
18773               route: '/a/route/:dynamicSection/:anotherDynamicSection',
18774               connectOutlets: function(router, context) {},
18775             })
18776           })
18777         })
18778       });
18779       App.initialize();
18780
18781   And application code:
18782
18783       App.get('router').send('moveElsewhere', {
18784         dynamicSection: '42',
18785         anotherDynamicSection: 'Life'
18786       });
18787
18788   Will transition the application's state to 'root.bRoute' and trigger an update of the URL to
18789   '#/a/route/42/Life'.
18790
18791   The context argument will also be passed as the second argument to the `serialize` method call.
18792
18793   ## Injection of Controller Singletons
18794   During application initialization Ember will detect properties of the application ending in 'Controller',
18795   create singleton instances of each class, and assign them as properties on the router.  The property name
18796   will be the UpperCamel name converted to lowerCamel format. These controller classes should be subclasses
18797   of Ember.ObjectController, Ember.ArrayController, Ember.Controller, or a custom Ember.Object that includes the
18798   Ember.ControllerMixin mixin.
18799
18800   ``` javascript
18801   App = Ember.Application.create({
18802     FooController: Ember.Object.create(Ember.ControllerMixin),
18803     Router: Ember.Router.extend({ ... })
18804   });
18805
18806   App.get('router.fooController'); // instance of App.FooController
18807   ```
18808
18809   The controller singletons will have their `namespace` property set to the application and their `target`
18810   property set to the application's router singleton for easy integration with Ember's user event system.
18811   See 'Changing View Hierarchy in Response To State Change' and 'Responding to User-initiated Events.'
18812
18813   ## Responding to User-initiated Events
18814   Controller instances injected into the router at application initialization have their `target` property
18815   set to the application's router instance. These controllers will also be the default `context` for their
18816   associated views.  Uses of the `{{action}}` helper will automatically target the application's router.
18817
18818   Given the following application entered at the URL '#/':
18819
18820   ``` javascript
18821   App = Ember.Application.create({
18822     Router: Ember.Router.extend({
18823       root: Ember.Route.extend({
18824         aRoute: Ember.Route.extend({
18825           route: '/',
18826           anActionOnTheRouter: function(router, context) {
18827             router.transitionTo('anotherState', context);
18828           }
18829         })
18830         anotherState: Ember.Route.extend({
18831           route: '/differentUrl',
18832           connectOutlets: function(router, context) {
18833
18834           }
18835         })
18836       })
18837     })
18838   });
18839   App.initialize();
18840   ```
18841
18842   The following template:
18843
18844   ``` handlebars
18845   <script type="text/x-handlebars" data-template-name="aView">
18846       <h1><a {{action anActionOnTheRouter}}>{{title}}</a></h1>
18847   </script>
18848   ```
18849
18850   Will delegate `click` events on the rendered `h1` to the application's router instance. In this case the
18851   `anActionOnTheRouter` method of the state at 'root.aRoute' will be called with the view's controller
18852   as the context argument. This context will be passed to the `connectOutlets` as its second argument.
18853
18854   Different `context` can be supplied from within the `{{action}}` helper, allowing specific context passing
18855   between application states:
18856
18857   ``` handlebars
18858   <script type="text/x-handlebars" data-template-name="photos">
18859     {{#each photo in controller}}
18860       <h1><a {{action showPhoto photo}}>{{title}}</a></h1>
18861     {{/each}}
18862   </script>
18863   ```
18864
18865   See `Handlebars.helpers.action` for additional usage examples.
18866
18867
18868   ## Changing View Hierarchy in Response To State Change
18869
18870   Changes in application state that change the URL should be accompanied by associated changes in view
18871   hierarchy.  This can be accomplished by calling 'connectOutlet' on the injected controller singletons from
18872   within the 'connectOutlets' event of an Ember.Route:
18873
18874   ``` javascript
18875   App = Ember.Application.create({
18876     OneController: Ember.ObjectController.extend(),
18877     OneView: Ember.View.extend(),
18878
18879     AnotherController: Ember.ObjectController.extend(),
18880     AnotherView: Ember.View.extend(),
18881
18882     Router: Ember.Router.extend({
18883       root: Ember.Route.extend({
18884         aRoute: Ember.Route.extend({
18885           route: '/',
18886           connectOutlets: function(router, context) {
18887             router.get('oneController').connectOutlet('another');
18888           },
18889         })
18890       })
18891     })
18892   });
18893   App.initialize();
18894   ```
18895
18896
18897   This will detect the '{{outlet}}' portion of `oneController`'s view (an instance of `App.OneView`) and
18898   fill it with a rendered instance of `App.AnotherView` whose `context` will be the single instance of
18899   `App.AnotherController` stored on the router in the `anotherController` property.
18900
18901   For more information about Outlets, see `Ember.Handlebars.helpers.outlet`. For additional information on
18902   the `connectOutlet` method, see `Ember.Controller.connectOutlet`. For more information on
18903   controller injections, see `Ember.Application#initialize()`. For additional information about view context,
18904   see `Ember.View`.
18905
18906   @class Router
18907   @namespace Ember
18908   @extends Ember.StateManager
18909 */
18910 Ember.Router = Ember.StateManager.extend(
18911 /** @scope Ember.Router.prototype */ {
18912
18913   /**
18914     @property initialState
18915     @type String
18916     @default 'root'
18917   */
18918   initialState: 'root',
18919
18920   /**
18921     The `Ember.Location` implementation to be used to manage the application
18922     URL state. The following values are supported:
18923
18924     * 'hash': Uses URL fragment identifiers (like #/blog/1) for routing.
18925     * 'history': Uses the browser's history.pushstate API for routing. Only works in
18926        modern browsers with pushstate support.
18927     * 'none': Does not read or set the browser URL, but still allows for
18928       routing to happen. Useful for testing.
18929
18930     @property location
18931     @type String
18932     @default 'hash'
18933   */
18934   location: 'hash',
18935
18936   /**
18937     This is only used when a history location is used so that applications that
18938     don't live at the root of the domain can append paths to their root.
18939
18940     @property rootURL
18941     @type String
18942     @default '/'
18943   */
18944
18945   rootURL: '/',
18946
18947   transitionTo: function() {
18948     this.abortRoutingPromises();
18949     this._super.apply(this, arguments);
18950   },
18951
18952   route: function(path) {
18953     this.abortRoutingPromises();
18954
18955     set(this, 'isRouting', true);
18956
18957     var routableState;
18958
18959     try {
18960       path = path.replace(get(this, 'rootURL'), '');
18961       path = path.replace(/^(?=[^\/])/, "/");
18962
18963       this.send('navigateAway');
18964       this.send('unroutePath', path);
18965
18966       routableState = get(this, 'currentState');
18967       while (routableState && !routableState.get('isRoutable')) {
18968         routableState = get(routableState, 'parentState');
18969       }
18970       var currentURL = routableState ? routableState.absoluteRoute(this) : '';
18971       var rest = path.substr(currentURL.length);
18972
18973       this.send('routePath', rest);
18974     } finally {
18975       set(this, 'isRouting', false);
18976     }
18977
18978     routableState = get(this, 'currentState');
18979     while (routableState && !routableState.get('isRoutable')) {
18980       routableState = get(routableState, 'parentState');
18981     }
18982
18983     if (routableState) {
18984       routableState.updateRoute(this, get(this, 'location'));
18985     }
18986   },
18987
18988   urlFor: function(path, hash) {
18989     var currentState = get(this, 'currentState') || this,
18990         state = this.findStateByPath(currentState, path);
18991
18992     Ember.assert(Ember.String.fmt("Could not find route with path '%@'", [path]), state);
18993     Ember.assert(Ember.String.fmt("To get a URL for the state '%@', it must have a `route` property.", [path]), get(state, 'routeMatcher'));
18994
18995     var location = get(this, 'location'),
18996         absoluteRoute = state.absoluteRoute(this, hash);
18997
18998     return location.formatURL(absoluteRoute);
18999   },
19000
19001   urlForEvent: function(eventName) {
19002     var contexts = Array.prototype.slice.call(arguments, 1);
19003     var currentState = get(this, 'currentState');
19004     var targetStateName = currentState.lookupEventTransition(eventName);
19005
19006     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);
19007
19008     var targetState = this.findStateByPath(currentState, targetStateName);
19009
19010     Ember.assert("Your target state name " + targetStateName + " for event " + eventName + " did not resolve to a state", targetState);
19011
19012     var hash = this.serializeRecursively(targetState, contexts, {});
19013
19014     return this.urlFor(targetStateName, hash);
19015   },
19016
19017   serializeRecursively: function(state, contexts, hash) {
19018     var parentState,
19019         context = get(state, 'hasContext') ? contexts.pop() : null;
19020     merge(hash, state.serialize(this, context));
19021     parentState = state.get("parentState");
19022     if (parentState && parentState instanceof Ember.Route) {
19023       return this.serializeRecursively(parentState, contexts, hash);
19024     } else {
19025       return hash;
19026     }
19027   },
19028
19029   abortRoutingPromises: function() {
19030     if (this._routingPromises) {
19031       this._routingPromises.abort();
19032       this._routingPromises = null;
19033     }
19034   },
19035
19036   handleStatePromises: function(states, complete) {
19037     this.abortRoutingPromises();
19038
19039     this.set('isLocked', true);
19040
19041     var manager = this;
19042
19043     this._routingPromises = Ember._PromiseChain.create({
19044       promises: states.slice(),
19045
19046       successCallback: function() {
19047         manager.set('isLocked', false);
19048         complete();
19049       },
19050
19051       failureCallback: function() {
19052         throw "Unable to load object";
19053       },
19054
19055       promiseSuccessCallback: function(item, args) {
19056         set(item, 'object', args[0]);
19057       },
19058
19059       abortCallback: function() {
19060         manager.set('isLocked', false);
19061       }
19062     }).start();
19063   },
19064
19065   moveStatesIntoRoot: function() {
19066     this.root = Ember.Route.extend();
19067
19068     for (var name in this) {
19069       if (name === "constructor") { continue; }
19070
19071       var state = this[name];
19072
19073       if (state instanceof Ember.Route || Ember.Route.detect(state)) {
19074         this.root[name] = state;
19075         delete this[name];
19076       }
19077     }
19078   },
19079
19080   init: function() {
19081     if (!this.root) {
19082       this.moveStatesIntoRoot();
19083     }
19084
19085     this._super();
19086
19087     var location = get(this, 'location'),
19088         rootURL = get(this, 'rootURL');
19089
19090     if ('string' === typeof location) {
19091       set(this, 'location', Ember.Location.create({
19092         implementation: location,
19093         rootURL: rootURL
19094       }));
19095     }
19096
19097     this.assignRouter(this, this);
19098   },
19099
19100   assignRouter: function(state, router) {
19101     state.router = router;
19102
19103     var childStates = state.states;
19104
19105     if (childStates) {
19106       for (var stateName in childStates) {
19107         if (!childStates.hasOwnProperty(stateName)) { continue; }
19108         this.assignRouter(childStates[stateName], router);
19109       }
19110     }
19111   },
19112
19113   willDestroy: function() {
19114     get(this, 'location').destroy();
19115   }
19116 });
19117
19118 })();
19119
19120
19121
19122 (function() {
19123 /**
19124 Ember Routing
19125
19126 @module ember
19127 @submodule ember-routing
19128 @requires ember-states
19129 */
19130
19131 })();
19132
19133 (function() {
19134 // ==========================================================================
19135 // Project:   metamorph
19136 // Copyright: Â©2011 My Company Inc. All rights reserved.
19137 // ==========================================================================
19138
19139 (function(window) {
19140
19141   var K = function(){},
19142       guid = 0,
19143       document = window.document,
19144
19145       // Feature-detect the W3C range API, the extended check is for IE9 which only partially supports ranges
19146       supportsRange = ('createRange' in document) && (typeof Range !== 'undefined') && Range.prototype.createContextualFragment,
19147
19148       // Internet Explorer prior to 9 does not allow setting innerHTML if the first element
19149       // is a "zero-scope" element. This problem can be worked around by making
19150       // the first node an invisible text node. We, like Modernizr, use &shy;
19151       needsShy = (function(){
19152         var testEl = document.createElement('div');
19153         testEl.innerHTML = "<div></div>";
19154         testEl.firstChild.innerHTML = "<script></script>";
19155         return testEl.firstChild.innerHTML === '';
19156       })();
19157
19158   // Constructor that supports either Metamorph('foo') or new
19159   // Metamorph('foo');
19160   //
19161   // Takes a string of HTML as the argument.
19162
19163   var Metamorph = function(html) {
19164     var self;
19165
19166     if (this instanceof Metamorph) {
19167       self = this;
19168     } else {
19169       self = new K();
19170     }
19171
19172     self.innerHTML = html;
19173     var myGuid = 'metamorph-'+(guid++);
19174     self.start = myGuid + '-start';
19175     self.end = myGuid + '-end';
19176
19177     return self;
19178   };
19179
19180   K.prototype = Metamorph.prototype;
19181
19182   var rangeFor, htmlFunc, removeFunc, outerHTMLFunc, appendToFunc, afterFunc, prependFunc, startTagFunc, endTagFunc;
19183
19184   outerHTMLFunc = function() {
19185     return this.startTag() + this.innerHTML + this.endTag();
19186   };
19187
19188   startTagFunc = function() {
19189     return "<script id='" + this.start + "' type='text/x-placeholder'></script>";
19190   };
19191
19192   endTagFunc = function() {
19193     return "<script id='" + this.end + "' type='text/x-placeholder'></script>";
19194   };
19195
19196   // If we have the W3C range API, this process is relatively straight forward.
19197   if (supportsRange) {
19198
19199     // Get a range for the current morph. Optionally include the starting and
19200     // ending placeholders.
19201     rangeFor = function(morph, outerToo) {
19202       var range = document.createRange();
19203       var before = document.getElementById(morph.start);
19204       var after = document.getElementById(morph.end);
19205
19206       if (outerToo) {
19207         range.setStartBefore(before);
19208         range.setEndAfter(after);
19209       } else {
19210         range.setStartAfter(before);
19211         range.setEndBefore(after);
19212       }
19213
19214       return range;
19215     };
19216
19217     htmlFunc = function(html, outerToo) {
19218       // get a range for the current metamorph object
19219       var range = rangeFor(this, outerToo);
19220
19221       // delete the contents of the range, which will be the
19222       // nodes between the starting and ending placeholder.
19223       range.deleteContents();
19224
19225       // create a new document fragment for the HTML
19226       var fragment = range.createContextualFragment(html);
19227
19228       // insert the fragment into the range
19229       range.insertNode(fragment);
19230     };
19231
19232     removeFunc = function() {
19233       // get a range for the current metamorph object including
19234       // the starting and ending placeholders.
19235       var range = rangeFor(this, true);
19236
19237       // delete the entire range.
19238       range.deleteContents();
19239     };
19240
19241     appendToFunc = function(node) {
19242       var range = document.createRange();
19243       range.setStart(node);
19244       range.collapse(false);
19245       var frag = range.createContextualFragment(this.outerHTML());
19246       node.appendChild(frag);
19247     };
19248
19249     afterFunc = function(html) {
19250       var range = document.createRange();
19251       var after = document.getElementById(this.end);
19252
19253       range.setStartAfter(after);
19254       range.setEndAfter(after);
19255
19256       var fragment = range.createContextualFragment(html);
19257       range.insertNode(fragment);
19258     };
19259
19260     prependFunc = function(html) {
19261       var range = document.createRange();
19262       var start = document.getElementById(this.start);
19263
19264       range.setStartAfter(start);
19265       range.setEndAfter(start);
19266
19267       var fragment = range.createContextualFragment(html);
19268       range.insertNode(fragment);
19269     };
19270
19271   } else {
19272     /**
19273      * This code is mostly taken from jQuery, with one exception. In jQuery's case, we
19274      * have some HTML and we need to figure out how to convert it into some nodes.
19275      *
19276      * In this case, jQuery needs to scan the HTML looking for an opening tag and use
19277      * that as the key for the wrap map. In our case, we know the parent node, and
19278      * can use its type as the key for the wrap map.
19279      **/
19280     var wrapMap = {
19281       select: [ 1, "<select multiple='multiple'>", "</select>" ],
19282       fieldset: [ 1, "<fieldset>", "</fieldset>" ],
19283       table: [ 1, "<table>", "</table>" ],
19284       tbody: [ 2, "<table><tbody>", "</tbody></table>" ],
19285       tr: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
19286       colgroup: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
19287       map: [ 1, "<map>", "</map>" ],
19288       _default: [ 0, "", "" ]
19289     };
19290
19291     /**
19292      * Given a parent node and some HTML, generate a set of nodes. Return the first
19293      * node, which will allow us to traverse the rest using nextSibling.
19294      *
19295      * We need to do this because innerHTML in IE does not really parse the nodes.
19296      **/
19297     var firstNodeFor = function(parentNode, html) {
19298       var arr = wrapMap[parentNode.tagName.toLowerCase()] || wrapMap._default;
19299       var depth = arr[0], start = arr[1], end = arr[2];
19300
19301       if (needsShy) { html = '&shy;'+html; }
19302
19303       var element = document.createElement('div');
19304       element.innerHTML = start + html + end;
19305
19306       for (var i=0; i<=depth; i++) {
19307         element = element.firstChild;
19308       }
19309
19310       // Look for &shy; to remove it.
19311       if (needsShy) {
19312         var shyElement = element;
19313
19314         // Sometimes we get nameless elements with the shy inside
19315         while (shyElement.nodeType === 1 && !shyElement.nodeName) {
19316           shyElement = shyElement.firstChild;
19317         }
19318
19319         // At this point it's the actual unicode character.
19320         if (shyElement.nodeType === 3 && shyElement.nodeValue.charAt(0) === "\u00AD") {
19321           shyElement.nodeValue = shyElement.nodeValue.slice(1);
19322         }
19323       }
19324
19325       return element;
19326     };
19327
19328     /**
19329      * In some cases, Internet Explorer can create an anonymous node in
19330      * the hierarchy with no tagName. You can create this scenario via:
19331      *
19332      *     div = document.createElement("div");
19333      *     div.innerHTML = "<table>&shy<script></script><tr><td>hi</td></tr></table>";
19334      *     div.firstChild.firstChild.tagName //=> ""
19335      *
19336      * If our script markers are inside such a node, we need to find that
19337      * node and use *it* as the marker.
19338      **/
19339     var realNode = function(start) {
19340       while (start.parentNode.tagName === "") {
19341         start = start.parentNode;
19342       }
19343
19344       return start;
19345     };
19346
19347     /**
19348      * When automatically adding a tbody, Internet Explorer inserts the
19349      * tbody immediately before the first <tr>. Other browsers create it
19350      * before the first node, no matter what.
19351      *
19352      * This means the the following code:
19353      *
19354      *     div = document.createElement("div");
19355      *     div.innerHTML = "<table><script id='first'></script><tr><td>hi</td></tr><script id='last'></script></table>
19356      *
19357      * Generates the following DOM in IE:
19358      *
19359      *     + div
19360      *       + table
19361      *         - script id='first'
19362      *         + tbody
19363      *           + tr
19364      *             + td
19365      *               - "hi"
19366      *           - script id='last'
19367      *
19368      * Which means that the two script tags, even though they were
19369      * inserted at the same point in the hierarchy in the original
19370      * HTML, now have different parents.
19371      *
19372      * This code reparents the first script tag by making it the tbody's
19373      * first child.
19374      **/
19375     var fixParentage = function(start, end) {
19376       if (start.parentNode !== end.parentNode) {
19377         end.parentNode.insertBefore(start, end.parentNode.firstChild);
19378       }
19379     };
19380
19381     htmlFunc = function(html, outerToo) {
19382       // get the real starting node. see realNode for details.
19383       var start = realNode(document.getElementById(this.start));
19384       var end = document.getElementById(this.end);
19385       var parentNode = end.parentNode;
19386       var node, nextSibling, last;
19387
19388       // make sure that the start and end nodes share the same
19389       // parent. If not, fix it.
19390       fixParentage(start, end);
19391
19392       // remove all of the nodes after the starting placeholder and
19393       // before the ending placeholder.
19394       node = start.nextSibling;
19395       while (node) {
19396         nextSibling = node.nextSibling;
19397         last = node === end;
19398
19399         // if this is the last node, and we want to remove it as well,
19400         // set the `end` node to the next sibling. This is because
19401         // for the rest of the function, we insert the new nodes
19402         // before the end (note that insertBefore(node, null) is
19403         // the same as appendChild(node)).
19404         //
19405         // if we do not want to remove it, just break.
19406         if (last) {
19407           if (outerToo) { end = node.nextSibling; } else { break; }
19408         }
19409
19410         node.parentNode.removeChild(node);
19411
19412         // if this is the last node and we didn't break before
19413         // (because we wanted to remove the outer nodes), break
19414         // now.
19415         if (last) { break; }
19416
19417         node = nextSibling;
19418       }
19419
19420       // get the first node for the HTML string, even in cases like
19421       // tables and lists where a simple innerHTML on a div would
19422       // swallow some of the content.
19423       node = firstNodeFor(start.parentNode, html);
19424
19425       // copy the nodes for the HTML between the starting and ending
19426       // placeholder.
19427       while (node) {
19428         nextSibling = node.nextSibling;
19429         parentNode.insertBefore(node, end);
19430         node = nextSibling;
19431       }
19432     };
19433
19434     // remove the nodes in the DOM representing this metamorph.
19435     //
19436     // this includes the starting and ending placeholders.
19437     removeFunc = function() {
19438       var start = realNode(document.getElementById(this.start));
19439       var end = document.getElementById(this.end);
19440
19441       this.html('');
19442       start.parentNode.removeChild(start);
19443       end.parentNode.removeChild(end);
19444     };
19445
19446     appendToFunc = function(parentNode) {
19447       var node = firstNodeFor(parentNode, this.outerHTML());
19448
19449       while (node) {
19450         nextSibling = node.nextSibling;
19451         parentNode.appendChild(node);
19452         node = nextSibling;
19453       }
19454     };
19455
19456     afterFunc = function(html) {
19457       // get the real starting node. see realNode for details.
19458       var end = document.getElementById(this.end);
19459       var insertBefore = end.nextSibling;
19460       var parentNode = end.parentNode;
19461       var nextSibling;
19462       var node;
19463
19464       // get the first node for the HTML string, even in cases like
19465       // tables and lists where a simple innerHTML on a div would
19466       // swallow some of the content.
19467       node = firstNodeFor(parentNode, html);
19468
19469       // copy the nodes for the HTML between the starting and ending
19470       // placeholder.
19471       while (node) {
19472         nextSibling = node.nextSibling;
19473         parentNode.insertBefore(node, insertBefore);
19474         node = nextSibling;
19475       }
19476     };
19477
19478     prependFunc = function(html) {
19479       var start = document.getElementById(this.start);
19480       var parentNode = start.parentNode;
19481       var nextSibling;
19482       var node;
19483
19484       node = firstNodeFor(parentNode, html);
19485       var insertBefore = start.nextSibling;
19486
19487       while (node) {
19488         nextSibling = node.nextSibling;
19489         parentNode.insertBefore(node, insertBefore);
19490         node = nextSibling;
19491       }
19492     }
19493   }
19494
19495   Metamorph.prototype.html = function(html) {
19496     this.checkRemoved();
19497     if (html === undefined) { return this.innerHTML; }
19498
19499     htmlFunc.call(this, html);
19500
19501     this.innerHTML = html;
19502   };
19503
19504   Metamorph.prototype.replaceWith = function(html) {
19505     this.checkRemoved();
19506     htmlFunc.call(this, html, true);
19507   };
19508
19509   Metamorph.prototype.remove = removeFunc;
19510   Metamorph.prototype.outerHTML = outerHTMLFunc;
19511   Metamorph.prototype.appendTo = appendToFunc;
19512   Metamorph.prototype.after = afterFunc;
19513   Metamorph.prototype.prepend = prependFunc;
19514   Metamorph.prototype.startTag = startTagFunc;
19515   Metamorph.prototype.endTag = endTagFunc;
19516
19517   Metamorph.prototype.isRemoved = function() {
19518     var before = document.getElementById(this.start);
19519     var after = document.getElementById(this.end);
19520
19521     return !before || !after;
19522   };
19523
19524   Metamorph.prototype.checkRemoved = function() {
19525     if (this.isRemoved()) {
19526       throw new Error("Cannot perform operations on a Metamorph that is not in the DOM.");
19527     }
19528   };
19529
19530   window.Metamorph = Metamorph;
19531 })(this);
19532
19533
19534 })();
19535
19536 (function() {
19537 /**
19538 @module ember
19539 @submodule ember-handlebars
19540 */
19541
19542 var objectCreate = Ember.create;
19543
19544 var Handlebars = Ember.imports.Handlebars;
19545 Ember.assert("Ember Handlebars requires Handlebars 1.0.beta.5 or greater", Handlebars && Handlebars.VERSION.match(/^1\.0\.beta\.[56789]$|^1\.0\.rc\.[123456789]+/));
19546
19547 /**
19548   Prepares the Handlebars templating library for use inside Ember's view
19549   system.
19550
19551   The Ember.Handlebars object is the standard Handlebars library, extended to use
19552   Ember's get() method instead of direct property access, which allows
19553   computed properties to be used inside templates.
19554
19555   To create an Ember.Handlebars template, call Ember.Handlebars.compile().  This will
19556   return a function that can be used by Ember.View for rendering.
19557
19558   @class Handlebars
19559   @namespace Ember
19560 */
19561 Ember.Handlebars = objectCreate(Handlebars);
19562
19563 /**
19564 @class helpers
19565 @namespace Ember.Handlebars
19566 */
19567 Ember.Handlebars.helpers = objectCreate(Handlebars.helpers);
19568
19569 /**
19570   Override the the opcode compiler and JavaScript compiler for Handlebars.
19571
19572   @class Compiler
19573   @namespace Ember.Handlebars
19574   @private
19575   @constructor
19576 */
19577 Ember.Handlebars.Compiler = function() {};
19578
19579 // Handlebars.Compiler doesn't exist in runtime-only
19580 if (Handlebars.Compiler) {
19581   Ember.Handlebars.Compiler.prototype = objectCreate(Handlebars.Compiler.prototype);
19582 }
19583
19584 Ember.Handlebars.Compiler.prototype.compiler = Ember.Handlebars.Compiler;
19585
19586 /**
19587   @class JavaScriptCompiler
19588   @namespace Ember.Handlebars
19589   @private
19590   @constructor
19591 */
19592 Ember.Handlebars.JavaScriptCompiler = function() {};
19593
19594 // Handlebars.JavaScriptCompiler doesn't exist in runtime-only
19595 if (Handlebars.JavaScriptCompiler) {
19596   Ember.Handlebars.JavaScriptCompiler.prototype = objectCreate(Handlebars.JavaScriptCompiler.prototype);
19597   Ember.Handlebars.JavaScriptCompiler.prototype.compiler = Ember.Handlebars.JavaScriptCompiler;
19598 }
19599
19600
19601 Ember.Handlebars.JavaScriptCompiler.prototype.namespace = "Ember.Handlebars";
19602
19603
19604 Ember.Handlebars.JavaScriptCompiler.prototype.initializeBuffer = function() {
19605   return "''";
19606 };
19607
19608 /**
19609   @private
19610
19611   Override the default buffer for Ember Handlebars. By default, Handlebars creates
19612   an empty String at the beginning of each invocation and appends to it. Ember's
19613   Handlebars overrides this to append to a single shared buffer.
19614
19615   @method appendToBuffer
19616   @param string {String}
19617 */
19618 Ember.Handlebars.JavaScriptCompiler.prototype.appendToBuffer = function(string) {
19619   return "data.buffer.push("+string+");";
19620 };
19621
19622 /**
19623   @private
19624
19625   Rewrite simple mustaches from `{{foo}}` to `{{bind "foo"}}`. This means that all simple
19626   mustaches in Ember's Handlebars will also set up an observer to keep the DOM
19627   up to date when the underlying property changes.
19628
19629   @method mustache
19630   @for Ember.Handlebars.Compiler
19631   @param mustache
19632 */
19633 Ember.Handlebars.Compiler.prototype.mustache = function(mustache) {
19634   if (mustache.params.length || mustache.hash) {
19635     return Handlebars.Compiler.prototype.mustache.call(this, mustache);
19636   } else {
19637     var id = new Handlebars.AST.IdNode(['_triageMustache']);
19638
19639     // Update the mustache node to include a hash value indicating whether the original node
19640     // was escaped. This will allow us to properly escape values when the underlying value
19641     // changes and we need to re-render the value.
19642     if(!mustache.escaped) {
19643       mustache.hash = mustache.hash || new Handlebars.AST.HashNode([]);
19644       mustache.hash.pairs.push(["unescaped", new Handlebars.AST.StringNode("true")]);
19645     }
19646     mustache = new Handlebars.AST.MustacheNode([id].concat([mustache.id]), mustache.hash, !mustache.escaped);
19647     return Handlebars.Compiler.prototype.mustache.call(this, mustache);
19648   }
19649 };
19650
19651 /**
19652   Used for precompilation of Ember Handlebars templates. This will not be used during normal
19653   app execution.
19654
19655   @method precompile
19656   @for Ember.Handlebars
19657   @static
19658   @param {String} string The template to precompile
19659 */
19660 Ember.Handlebars.precompile = function(string) {
19661   var ast = Handlebars.parse(string);
19662
19663   var options = {
19664     knownHelpers: {
19665       action: true,
19666       unbound: true,
19667       bindAttr: true,
19668       template: true,
19669       view: true,
19670       _triageMustache: true
19671     },
19672     data: true,
19673     stringParams: true
19674   };
19675
19676   var environment = new Ember.Handlebars.Compiler().compile(ast, options);
19677   return new Ember.Handlebars.JavaScriptCompiler().compile(environment, options, undefined, true);
19678 };
19679
19680 // We don't support this for Handlebars runtime-only
19681 if (Handlebars.compile) {
19682   /**
19683     The entry point for Ember Handlebars. This replaces the default Handlebars.compile and turns on
19684     template-local data and String parameters.
19685
19686     @method compile
19687     @for Ember.Handlebars
19688     @static
19689     @param {String} string The template to compile
19690     @return {Function}
19691   */
19692   Ember.Handlebars.compile = function(string) {
19693     var ast = Handlebars.parse(string);
19694     var options = { data: true, stringParams: true };
19695     var environment = new Ember.Handlebars.Compiler().compile(ast, options);
19696     var templateSpec = new Ember.Handlebars.JavaScriptCompiler().compile(environment, options, undefined, true);
19697
19698     return Handlebars.template(templateSpec);
19699   };
19700 }
19701
19702 /**
19703   @private
19704
19705   If a path starts with a reserved keyword, returns the root
19706   that should be used.
19707
19708   @method normalizePath
19709   @for Ember
19710   @param root {Object}
19711   @param path {String}
19712   @param data {Hash}
19713 */
19714 var normalizePath = Ember.Handlebars.normalizePath = function(root, path, data) {
19715   var keywords = (data && data.keywords) || {},
19716       keyword, isKeyword;
19717
19718   // Get the first segment of the path. For example, if the
19719   // path is "foo.bar.baz", returns "foo".
19720   keyword = path.split('.', 1)[0];
19721
19722   // Test to see if the first path is a keyword that has been
19723   // passed along in the view's data hash. If so, we will treat
19724   // that object as the new root.
19725   if (keywords.hasOwnProperty(keyword)) {
19726     // Look up the value in the template's data hash.
19727     root = keywords[keyword];
19728     isKeyword = true;
19729
19730     // Handle cases where the entire path is the reserved
19731     // word. In that case, return the object itself.
19732     if (path === keyword) {
19733       path = '';
19734     } else {
19735       // Strip the keyword from the path and look up
19736       // the remainder from the newly found root.
19737       path = path.substr(keyword.length+1);
19738     }
19739   }
19740
19741   return { root: root, path: path, isKeyword: isKeyword };
19742 };
19743
19744
19745 /**
19746   Lookup both on root and on window. If the path starts with
19747   a keyword, the corresponding object will be looked up in the
19748   template's data hash and used to resolve the path.
19749
19750   @method get
19751   @for Ember.Handlebars
19752   @param {Object} root The object to look up the property on
19753   @param {String} path The path to be lookedup
19754   @param {Object} options The template's option hash
19755 */
19756 Ember.Handlebars.get = function(root, path, options) {
19757   var data = options && options.data,
19758       normalizedPath = normalizePath(root, path, data),
19759       value;
19760
19761   // In cases where the path begins with a keyword, change the
19762   // root to the value represented by that keyword, and ensure
19763   // the path is relative to it.
19764   root = normalizedPath.root;
19765   path = normalizedPath.path;
19766
19767   value = Ember.get(root, path);
19768
19769   // If the path starts with a capital letter, look it up on Ember.lookup,
19770   // which defaults to the `window` object in browsers.
19771   if (value === undefined && root !== Ember.lookup && Ember.isGlobalPath(path)) {
19772     value = Ember.get(Ember.lookup, path);
19773   }
19774   return value;
19775 };
19776 Ember.Handlebars.getPath = Ember.deprecateFunc('`Ember.Handlebars.getPath` has been changed to `Ember.Handlebars.get` for consistency.', Ember.Handlebars.get);
19777
19778 /**
19779   @private
19780
19781   Registers a helper in Handlebars that will be called if no property with the
19782   given name can be found on the current context object, and no helper with
19783   that name is registered.
19784
19785   This throws an exception with a more helpful error message so the user can
19786   track down where the problem is happening.
19787
19788   @method helperMissing
19789   @for Ember.Handlebars.helpers
19790   @param {String} path
19791   @param {Hash} options
19792 */
19793 Ember.Handlebars.registerHelper('helperMissing', function(path, options) {
19794   var error, view = "";
19795
19796   error = "%@ Handlebars error: Could not find property '%@' on object %@.";
19797   if (options.data){
19798     view = options.data.view;
19799   }
19800   throw new Ember.Error(Ember.String.fmt(error, [view, path, this]));
19801 });
19802
19803
19804 })();
19805
19806
19807
19808 (function() {
19809 /**
19810   @method htmlSafe
19811   @for Ember.String
19812   @static
19813 */
19814 Ember.String.htmlSafe = function(str) {
19815   return new Handlebars.SafeString(str);
19816 };
19817
19818 var htmlSafe = Ember.String.htmlSafe;
19819
19820 if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {
19821
19822   /**
19823     See {{#crossLink "Ember.String/htmlSafe"}}{{/crossLink}}
19824
19825     @method htmlSafe
19826     @for String
19827   */
19828   String.prototype.htmlSafe = function() {
19829     return htmlSafe(this);
19830   };
19831 }
19832
19833 })();
19834
19835
19836
19837 (function() {
19838 /*jshint newcap:false*/
19839 /**
19840 @module ember
19841 @submodule ember-handlebars
19842 */
19843
19844 var set = Ember.set, get = Ember.get;
19845
19846 // DOMManager should just abstract dom manipulation between jquery and metamorph
19847 var DOMManager = {
19848   remove: function(view) {
19849     view.morph.remove();
19850   },
19851
19852   prepend: function(view, html) {
19853     view.morph.prepend(html);
19854   },
19855
19856   after: function(view, html) {
19857     view.morph.after(html);
19858   },
19859
19860   html: function(view, html) {
19861     view.morph.html(html);
19862   },
19863
19864   // This is messed up.
19865   replace: function(view) {
19866     var morph = view.morph;
19867
19868     view.transitionTo('preRender');
19869     view.clearRenderedChildren();
19870     var buffer = view.renderToBuffer();
19871
19872     Ember.run.schedule('render', this, function() {
19873       if (get(view, 'isDestroyed')) { return; }
19874       view.invalidateRecursively('element');
19875       view._notifyWillInsertElement();
19876       morph.replaceWith(buffer.string());
19877       view.transitionTo('inDOM');
19878       view._notifyDidInsertElement();
19879     });
19880   },
19881
19882   empty: function(view) {
19883     view.morph.html("");
19884   }
19885 };
19886
19887 // The `morph` and `outerHTML` properties are internal only
19888 // and not observable.
19889
19890 /**
19891   @class _Metamorph
19892   @namespace Ember
19893   @extends Ember.Mixin
19894   @private
19895 */
19896 Ember._Metamorph = Ember.Mixin.create({
19897   isVirtual: true,
19898   tagName: '',
19899
19900   instrumentName: 'render.metamorph',
19901
19902   init: function() {
19903     this._super();
19904     this.morph = Metamorph();
19905   },
19906
19907   beforeRender: function(buffer) {
19908     buffer.push(this.morph.startTag());
19909   },
19910
19911   afterRender: function(buffer) {
19912     buffer.push(this.morph.endTag());
19913   },
19914
19915   createElement: function() {
19916     var buffer = this.renderToBuffer();
19917     this.outerHTML = buffer.string();
19918     this.clearBuffer();
19919   },
19920
19921   domManager: DOMManager
19922 });
19923
19924 /**
19925   @class _MetamorphView
19926   @namespace Ember
19927   @extends Ember.View
19928   @uses Ember._Metamorph
19929   @private
19930 */
19931 Ember._MetamorphView = Ember.View.extend(Ember._Metamorph);
19932
19933 /**
19934   @class _SimpleMetamorphView
19935   @namespace Ember
19936   @extends Ember.View
19937   @uses Ember._Metamorph
19938   @private
19939 */
19940 Ember._SimpleMetamorphView = Ember.CoreView.extend(Ember._Metamorph);
19941
19942
19943 })();
19944
19945
19946
19947 (function() {
19948 /*globals Handlebars */
19949
19950 /**
19951 @module ember
19952 @submodule ember-handlebars
19953 */
19954
19955 var get = Ember.get, set = Ember.set, handlebarsGet = Ember.Handlebars.get;
19956 Ember._SimpleHandlebarsView = Ember._SimpleMetamorphView.extend({
19957   instrumentName: 'render.simpleHandlebars',
19958
19959   normalizedValue: Ember.computed(function() {
19960     var path = get(this, 'path'),
19961         pathRoot  = get(this, 'pathRoot'),
19962         result, templateData;
19963
19964     // Use the pathRoot as the result if no path is provided. This
19965     // happens if the path is `this`, which gets normalized into
19966     // a `pathRoot` of the current Handlebars context and a path
19967     // of `''`.
19968     if (path === '') {
19969       result = pathRoot;
19970     } else {
19971       templateData = get(this, 'templateData');
19972       result = handlebarsGet(pathRoot, path, { data: templateData });
19973     }
19974
19975     return result;
19976   }).property('path', 'pathRoot').volatile(),
19977
19978   render: function(buffer) {
19979     // If not invoked via a triple-mustache ({{{foo}}}), escape
19980     // the content of the template.
19981     var escape = get(this, 'isEscaped');
19982     var result = get(this, 'normalizedValue');
19983
19984     if (result === null || result === undefined) {
19985       result = "";
19986     } else if (!(result instanceof Handlebars.SafeString)) {
19987       result = String(result);
19988     }
19989
19990     if (escape) { result = Handlebars.Utils.escapeExpression(result); }
19991     buffer.push(result);
19992     return;
19993   },
19994
19995   rerender: function() {
19996     switch(this.state) {
19997       case 'preRender':
19998       case 'destroyed':
19999         break;
20000       case 'inBuffer':
20001         throw new Error("Something you did tried to replace an {{expression}} before it was inserted into the DOM.");
20002       case 'hasElement':
20003       case 'inDOM':
20004         this.domManager.replace(this);
20005         break;
20006     }
20007
20008     return this;
20009   },
20010
20011   transitionTo: function(state) {
20012     this.state = state;
20013   }
20014 });
20015
20016 /**
20017   Ember._HandlebarsBoundView is a private view created by the Handlebars `{{bind}}`
20018   helpers that is used to keep track of bound properties.
20019
20020   Every time a property is bound using a `{{mustache}}`, an anonymous subclass
20021   of Ember._HandlebarsBoundView is created with the appropriate sub-template and
20022   context set up. When the associated property changes, just the template for
20023   this view will re-render.
20024
20025   @class _HandlebarsBoundView
20026   @namespace Ember
20027   @extends Ember._MetamorphView
20028   @private
20029 */
20030 Ember._HandlebarsBoundView = Ember._MetamorphView.extend({
20031   instrumentName: 'render.boundHandlebars',
20032
20033   /**
20034     The function used to determine if the `displayTemplate` or
20035     `inverseTemplate` should be rendered. This should be a function that takes
20036     a value and returns a Boolean.
20037
20038     @property shouldDisplayFunc
20039     @type Function
20040     @default null
20041   */
20042   shouldDisplayFunc: null,
20043
20044   /**
20045     Whether the template rendered by this view gets passed the context object
20046     of its parent template, or gets passed the value of retrieving `path`
20047     from the `pathRoot`.
20048
20049     For example, this is true when using the `{{#if}}` helper, because the
20050     template inside the helper should look up properties relative to the same
20051     object as outside the block. This would be false when used with `{{#with
20052     foo}}` because the template should receive the object found by evaluating
20053     `foo`.
20054
20055     @property preserveContext
20056     @type Boolean
20057     @default false
20058   */
20059   preserveContext: false,
20060
20061   /**
20062     If `preserveContext` is true, this is the object that will be used
20063     to render the template.
20064
20065     @property previousContext
20066     @type Object
20067   */
20068   previousContext: null,
20069
20070   /**
20071     The template to render when `shouldDisplayFunc` evaluates to true.
20072
20073     @property displayTemplate
20074     @type Function
20075     @default null
20076   */
20077   displayTemplate: null,
20078
20079   /**
20080     The template to render when `shouldDisplayFunc` evaluates to false.
20081
20082     @property inverseTemplate
20083     @type Function
20084     @default null
20085   */
20086   inverseTemplate: null,
20087
20088
20089   /**
20090     The path to look up on `pathRoot` that is passed to
20091     `shouldDisplayFunc` to determine which template to render.
20092
20093     In addition, if `preserveContext` is false, the object at this path will
20094     be passed to the template when rendering.
20095
20096     @property path
20097     @type String
20098     @default null
20099   */
20100   path: null,
20101
20102   /**
20103     The object from which the `path` will be looked up. Sometimes this is the
20104     same as the `previousContext`, but in cases where this view has been generated
20105     for paths that start with a keyword such as `view` or `controller`, the
20106     path root will be that resolved object.
20107
20108     @property pathRoot
20109     @type Object
20110   */
20111   pathRoot: null,
20112
20113   normalizedValue: Ember.computed(function() {
20114     var path = get(this, 'path'),
20115         pathRoot  = get(this, 'pathRoot'),
20116         valueNormalizer = get(this, 'valueNormalizerFunc'),
20117         result, templateData;
20118
20119     // Use the pathRoot as the result if no path is provided. This
20120     // happens if the path is `this`, which gets normalized into
20121     // a `pathRoot` of the current Handlebars context and a path
20122     // of `''`.
20123     if (path === '') {
20124       result = pathRoot;
20125     } else {
20126       templateData = get(this, 'templateData');
20127       result = handlebarsGet(pathRoot, path, { data: templateData });
20128     }
20129
20130     return valueNormalizer ? valueNormalizer(result) : result;
20131   }).property('path', 'pathRoot', 'valueNormalizerFunc').volatile(),
20132
20133   rerenderIfNeeded: function() {
20134     if (!get(this, 'isDestroyed') && get(this, 'normalizedValue') !== this._lastNormalizedValue) {
20135       this.rerender();
20136     }
20137   },
20138
20139   /**
20140     Determines which template to invoke, sets up the correct state based on
20141     that logic, then invokes the default Ember.View `render` implementation.
20142
20143     This method will first look up the `path` key on `pathRoot`,
20144     then pass that value to the `shouldDisplayFunc` function. If that returns
20145     true, the `displayTemplate` function will be rendered to DOM. Otherwise,
20146     `inverseTemplate`, if specified, will be rendered.
20147
20148     For example, if this Ember._HandlebarsBoundView represented the `{{#with foo}}`
20149     helper, it would look up the `foo` property of its context, and
20150     `shouldDisplayFunc` would always return true. The object found by looking
20151     up `foo` would be passed to `displayTemplate`.
20152
20153     @method render
20154     @param {Ember.RenderBuffer} buffer
20155   */
20156   render: function(buffer) {
20157     // If not invoked via a triple-mustache ({{{foo}}}), escape
20158     // the content of the template.
20159     var escape = get(this, 'isEscaped');
20160
20161     var shouldDisplay = get(this, 'shouldDisplayFunc'),
20162         preserveContext = get(this, 'preserveContext'),
20163         context = get(this, 'previousContext');
20164
20165     var inverseTemplate = get(this, 'inverseTemplate'),
20166         displayTemplate = get(this, 'displayTemplate');
20167
20168     var result = get(this, 'normalizedValue');
20169     this._lastNormalizedValue = result;
20170
20171     // First, test the conditional to see if we should
20172     // render the template or not.
20173     if (shouldDisplay(result)) {
20174       set(this, 'template', displayTemplate);
20175
20176       // If we are preserving the context (for example, if this
20177       // is an #if block, call the template with the same object.
20178       if (preserveContext) {
20179         set(this, '_context', context);
20180       } else {
20181       // Otherwise, determine if this is a block bind or not.
20182       // If so, pass the specified object to the template
20183         if (displayTemplate) {
20184           set(this, '_context', result);
20185         } else {
20186         // This is not a bind block, just push the result of the
20187         // expression to the render context and return.
20188           if (result === null || result === undefined) {
20189             result = "";
20190           } else if (!(result instanceof Handlebars.SafeString)) {
20191             result = String(result);
20192           }
20193
20194           if (escape) { result = Handlebars.Utils.escapeExpression(result); }
20195           buffer.push(result);
20196           return;
20197         }
20198       }
20199     } else if (inverseTemplate) {
20200       set(this, 'template', inverseTemplate);
20201
20202       if (preserveContext) {
20203         set(this, '_context', context);
20204       } else {
20205         set(this, '_context', result);
20206       }
20207     } else {
20208       set(this, 'template', function() { return ''; });
20209     }
20210
20211     return this._super(buffer);
20212   }
20213 });
20214
20215 })();
20216
20217
20218
20219 (function() {
20220 /**
20221 @module ember
20222 @submodule ember-handlebars
20223 */
20224
20225 var get = Ember.get, set = Ember.set, fmt = Ember.String.fmt;
20226 var handlebarsGet = Ember.Handlebars.get, normalizePath = Ember.Handlebars.normalizePath;
20227 var forEach = Ember.ArrayPolyfills.forEach;
20228
20229 var EmberHandlebars = Ember.Handlebars, helpers = EmberHandlebars.helpers;
20230
20231 // Binds a property into the DOM. This will create a hook in DOM that the
20232 // KVO system will look for and update if the property changes.
20233 function bind(property, options, preserveContext, shouldDisplay, valueNormalizer) {
20234   var data = options.data,
20235       fn = options.fn,
20236       inverse = options.inverse,
20237       view = data.view,
20238       currentContext = this,
20239       pathRoot, path, normalized;
20240
20241   normalized = normalizePath(currentContext, property, data);
20242
20243   pathRoot = normalized.root;
20244   path = normalized.path;
20245
20246   // Set up observers for observable objects
20247   if ('object' === typeof this) {
20248     // Create the view that will wrap the output of this template/property
20249     // and add it to the nearest view's childViews array.
20250     // See the documentation of Ember._HandlebarsBoundView for more.
20251     var bindView = view.createChildView(Ember._HandlebarsBoundView, {
20252       preserveContext: preserveContext,
20253       shouldDisplayFunc: shouldDisplay,
20254       valueNormalizerFunc: valueNormalizer,
20255       displayTemplate: fn,
20256       inverseTemplate: inverse,
20257       path: path,
20258       pathRoot: pathRoot,
20259       previousContext: currentContext,
20260       isEscaped: !options.hash.unescaped,
20261       templateData: options.data
20262     });
20263
20264     view.appendChild(bindView);
20265
20266     var observer = function() {
20267       Ember.run.scheduleOnce('render', bindView, 'rerenderIfNeeded');
20268     };
20269
20270     // Observes the given property on the context and
20271     // tells the Ember._HandlebarsBoundView to re-render. If property
20272     // is an empty string, we are printing the current context
20273     // object ({{this}}) so updating it is not our responsibility.
20274     if (path !== '') {
20275       Ember.addObserver(pathRoot, path, observer);
20276
20277       view.one('willClearRender', function() {
20278         Ember.removeObserver(pathRoot, path, observer);
20279       });
20280     }
20281   } else {
20282     // The object is not observable, so just render it out and
20283     // be done with it.
20284     data.buffer.push(handlebarsGet(pathRoot, path, options));
20285   }
20286 }
20287
20288 function simpleBind(property, options) {
20289   var data = options.data,
20290       view = data.view,
20291       currentContext = this,
20292       pathRoot, path, normalized;
20293
20294   normalized = normalizePath(currentContext, property, data);
20295
20296   pathRoot = normalized.root;
20297   path = normalized.path;
20298
20299   // Set up observers for observable objects
20300   if ('object' === typeof this) {
20301     var bindView = Ember._SimpleHandlebarsView.create().setProperties({
20302       path: path,
20303       pathRoot: pathRoot,
20304       isEscaped: !options.hash.unescaped,
20305       previousContext: currentContext,
20306       templateData: options.data
20307     });
20308
20309     view.createChildView(bindView);
20310     view.appendChild(bindView);
20311
20312     var observer = function() {
20313       Ember.run.scheduleOnce('render', bindView, 'rerender');
20314     };
20315
20316     // Observes the given property on the context and
20317     // tells the Ember._HandlebarsBoundView to re-render. If property
20318     // is an empty string, we are printing the current context
20319     // object ({{this}}) so updating it is not our responsibility.
20320     if (path !== '') {
20321       Ember.addObserver(pathRoot, path, observer);
20322
20323       view.one('willClearRender', function() {
20324         Ember.removeObserver(pathRoot, path, observer);
20325       });
20326     }
20327   } else {
20328     // The object is not observable, so just render it out and
20329     // be done with it.
20330     data.buffer.push(handlebarsGet(pathRoot, path, options));
20331   }
20332 }
20333
20334 /**
20335   @private
20336
20337   '_triageMustache' is used internally select between a binding and helper for
20338   the given context. Until this point, it would be hard to determine if the
20339   mustache is a property reference or a regular helper reference. This triage
20340   helper resolves that.
20341
20342   This would not be typically invoked by directly.
20343
20344   @method _triageMustache
20345   @for Ember.Handlebars.helpers
20346   @param {String} property Property/helperID to triage
20347   @param {Function} fn Context to provide for rendering
20348   @return {String} HTML string
20349 */
20350 EmberHandlebars.registerHelper('_triageMustache', function(property, fn) {
20351   Ember.assert("You cannot pass more than one argument to the _triageMustache helper", arguments.length <= 2);
20352   if (helpers[property]) {
20353     return helpers[property].call(this, fn);
20354   }
20355   else {
20356     return helpers.bind.apply(this, arguments);
20357   }
20358 });
20359
20360 /**
20361   @private
20362
20363   `bind` can be used to display a value, then update that value if it
20364   changes. For example, if you wanted to print the `title` property of
20365   `content`:
20366
20367   ``` handlebars
20368   {{bind "content.title"}}
20369   ```
20370
20371   This will return the `title` property as a string, then create a new
20372   observer at the specified path. If it changes, it will update the value in
20373   DOM. Note that if you need to support IE7 and IE8 you must modify the
20374   model objects properties using Ember.get() and Ember.set() for this to work as
20375   it relies on Ember's KVO system.  For all other browsers this will be handled
20376   for you automatically.
20377
20378   @method bind
20379   @for Ember.Handlebars.helpers
20380   @param {String} property Property to bind
20381   @param {Function} fn Context to provide for rendering
20382   @return {String} HTML string
20383 */
20384 EmberHandlebars.registerHelper('bind', function(property, options) {
20385   Ember.assert("You cannot pass more than one argument to the bind helper", arguments.length <= 2);
20386
20387   var context = (options.contexts && options.contexts[0]) || this;
20388
20389   if (!options.fn) {
20390     return simpleBind.call(context, property, options);
20391   }
20392
20393   return bind.call(context, property, options, false, function(result) {
20394     return !Ember.none(result);
20395   });
20396 });
20397
20398 /**
20399   @private
20400
20401   Use the `boundIf` helper to create a conditional that re-evaluates
20402   whenever the bound value changes.
20403
20404   ``` handlebars
20405   {{#boundIf "content.shouldDisplayTitle"}}
20406     {{content.title}}
20407   {{/boundIf}}
20408   ```
20409
20410   @method boundIf
20411   @for Ember.Handlebars.helpers
20412   @param {String} property Property to bind
20413   @param {Function} fn Context to provide for rendering
20414   @return {String} HTML string
20415 */
20416 EmberHandlebars.registerHelper('boundIf', function(property, fn) {
20417   var context = (fn.contexts && fn.contexts[0]) || this;
20418   var func = function(result) {
20419     if (Ember.typeOf(result) === 'array') {
20420       return get(result, 'length') !== 0;
20421     } else {
20422       return !!result;
20423     }
20424   };
20425
20426   return bind.call(context, property, fn, true, func, func);
20427 });
20428
20429 /**
20430   @method with
20431   @for Ember.Handlebars.helpers
20432   @param {Function} context
20433   @param {Hash} options
20434   @return {String} HTML string
20435 */
20436 EmberHandlebars.registerHelper('with', function(context, options) {
20437   if (arguments.length === 4) {
20438     var keywordName, path, rootPath, normalized;
20439
20440     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");
20441     options = arguments[3];
20442     keywordName = arguments[2];
20443     path = arguments[0];
20444
20445     Ember.assert("You must pass a block to the with helper", options.fn && options.fn !== Handlebars.VM.noop);
20446
20447     if (Ember.isGlobalPath(path)) {
20448       Ember.bind(options.data.keywords, keywordName, path);
20449     } else {
20450       normalized = normalizePath(this, path, options.data);
20451       path = normalized.path;
20452       rootPath = normalized.root;
20453
20454       // This is a workaround for the fact that you cannot bind separate objects
20455       // together. When we implement that functionality, we should use it here.
20456       var contextKey = Ember.$.expando + Ember.guidFor(rootPath);
20457       options.data.keywords[contextKey] = rootPath;
20458
20459       // if the path is '' ("this"), just bind directly to the current context
20460       var contextPath = path ? contextKey + '.' + path : contextKey;
20461       Ember.bind(options.data.keywords, keywordName, contextPath);
20462     }
20463
20464     return bind.call(this, path, options, true, function(result) {
20465       return !Ember.none(result);
20466     });
20467   } else {
20468     Ember.assert("You must pass exactly one argument to the with helper", arguments.length === 2);
20469     Ember.assert("You must pass a block to the with helper", options.fn && options.fn !== Handlebars.VM.noop);
20470     return helpers.bind.call(options.contexts[0], context, options);
20471   }
20472 });
20473
20474
20475 /**
20476   @method if
20477   @for Ember.Handlebars.helpers
20478   @param {Function} context
20479   @param {Hash} options
20480   @return {String} HTML string
20481 */
20482 EmberHandlebars.registerHelper('if', function(context, options) {
20483   Ember.assert("You must pass exactly one argument to the if helper", arguments.length === 2);
20484   Ember.assert("You must pass a block to the if helper", options.fn && options.fn !== Handlebars.VM.noop);
20485
20486   return helpers.boundIf.call(options.contexts[0], context, options);
20487 });
20488
20489 /**
20490   @method unless
20491   @for Ember.Handlebars.helpers
20492   @param {Function} context
20493   @param {Hash} options
20494   @return {String} HTML string
20495 */
20496 EmberHandlebars.registerHelper('unless', function(context, options) {
20497   Ember.assert("You must pass exactly one argument to the unless helper", arguments.length === 2);
20498   Ember.assert("You must pass a block to the unless helper", options.fn && options.fn !== Handlebars.VM.noop);
20499
20500   var fn = options.fn, inverse = options.inverse;
20501
20502   options.fn = inverse;
20503   options.inverse = fn;
20504
20505   return helpers.boundIf.call(options.contexts[0], context, options);
20506 });
20507
20508 /**
20509   `bindAttr` allows you to create a binding between DOM element attributes and
20510   Ember objects. For example:
20511
20512   ``` handlebars
20513   <img {{bindAttr src="imageUrl" alt="imageTitle"}}>
20514   ```
20515
20516   @method bindAttr
20517   @for Ember.Handlebars.helpers
20518   @param {Hash} options
20519   @return {String} HTML string
20520 */
20521 EmberHandlebars.registerHelper('bindAttr', function(options) {
20522
20523   var attrs = options.hash;
20524
20525   Ember.assert("You must specify at least one hash argument to bindAttr", !!Ember.keys(attrs).length);
20526
20527   var view = options.data.view;
20528   var ret = [];
20529   var ctx = this;
20530
20531   // Generate a unique id for this element. This will be added as a
20532   // data attribute to the element so it can be looked up when
20533   // the bound property changes.
20534   var dataId = ++Ember.uuid;
20535
20536   // Handle classes differently, as we can bind multiple classes
20537   var classBindings = attrs['class'];
20538   if (classBindings !== null && classBindings !== undefined) {
20539     var classResults = EmberHandlebars.bindClasses(this, classBindings, view, dataId, options);
20540     ret.push('class="' + Handlebars.Utils.escapeExpression(classResults.join(' ')) + '"');
20541     delete attrs['class'];
20542   }
20543
20544   var attrKeys = Ember.keys(attrs);
20545
20546   // For each attribute passed, create an observer and emit the
20547   // current value of the property as an attribute.
20548   forEach.call(attrKeys, function(attr) {
20549     var path = attrs[attr],
20550         pathRoot, normalized;
20551
20552     Ember.assert(fmt("You must provide a String for a bound attribute, not %@", [path]), typeof path === 'string');
20553
20554     normalized = normalizePath(ctx, path, options.data);
20555
20556     pathRoot = normalized.root;
20557     path = normalized.path;
20558
20559     var value = (path === 'this') ? pathRoot : handlebarsGet(pathRoot, path, options),
20560         type = Ember.typeOf(value);
20561
20562     Ember.assert(fmt("Attributes must be numbers, strings or booleans, not %@", [value]), value === null || value === undefined || type === 'number' || type === 'string' || type === 'boolean');
20563
20564     var observer, invoker;
20565
20566     observer = function observer() {
20567       var result = handlebarsGet(pathRoot, path, options);
20568
20569       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');
20570
20571       var elem = view.$("[data-bindattr-" + dataId + "='" + dataId + "']");
20572
20573       // If we aren't able to find the element, it means the element
20574       // to which we were bound has been removed from the view.
20575       // In that case, we can assume the template has been re-rendered
20576       // and we need to clean up the observer.
20577       if (!elem || elem.length === 0) {
20578         Ember.removeObserver(pathRoot, path, invoker);
20579         return;
20580       }
20581
20582       Ember.View.applyAttributeBindings(elem, attr, result);
20583     };
20584
20585     invoker = function() {
20586       Ember.run.scheduleOnce('render', observer);
20587     };
20588
20589     // Add an observer to the view for when the property changes.
20590     // When the observer fires, find the element using the
20591     // unique data id and update the attribute to the new value.
20592     if (path !== 'this') {
20593       Ember.addObserver(pathRoot, path, invoker);
20594
20595       view.one('willClearRender', function() {
20596         Ember.removeObserver(pathRoot, path, invoker);
20597       });
20598     }
20599
20600     // if this changes, also change the logic in ember-views/lib/views/view.js
20601     if ((type === 'string' || (type === 'number' && !isNaN(value)))) {
20602       ret.push(attr + '="' + Handlebars.Utils.escapeExpression(value) + '"');
20603     } else if (value && type === 'boolean') {
20604       // The developer controls the attr name, so it should always be safe
20605       ret.push(attr + '="' + attr + '"');
20606     }
20607   }, this);
20608
20609   // Add the unique identifier
20610   // NOTE: We use all lower-case since Firefox has problems with mixed case in SVG
20611   ret.push('data-bindattr-' + dataId + '="' + dataId + '"');
20612   return new EmberHandlebars.SafeString(ret.join(' '));
20613 });
20614
20615 /**
20616   @private
20617
20618   Helper that, given a space-separated string of property paths and a context,
20619   returns an array of class names. Calling this method also has the side
20620   effect of setting up observers at those property paths, such that if they
20621   change, the correct class name will be reapplied to the DOM element.
20622
20623   For example, if you pass the string "fooBar", it will first look up the
20624   "fooBar" value of the context. If that value is true, it will add the
20625   "foo-bar" class to the current element (i.e., the dasherized form of
20626   "fooBar"). If the value is a string, it will add that string as the class.
20627   Otherwise, it will not add any new class name.
20628
20629   @method bindClasses
20630   @for Ember.Handlebars
20631   @param {Ember.Object} context The context from which to lookup properties
20632   @param {String} classBindings A string, space-separated, of class bindings to use
20633   @param {Ember.View} view The view in which observers should look for the element to update
20634   @param {Srting} bindAttrId Optional bindAttr id used to lookup elements
20635   @return {Array} An array of class names to add
20636 */
20637 EmberHandlebars.bindClasses = function(context, classBindings, view, bindAttrId, options) {
20638   var ret = [], newClass, value, elem;
20639
20640   // Helper method to retrieve the property from the context and
20641   // determine which class string to return, based on whether it is
20642   // a Boolean or not.
20643   var classStringForPath = function(root, parsedPath, options) {
20644     var val,
20645         path = parsedPath.path;
20646
20647     if (path === 'this') {
20648       val = root;
20649     } else if (path === '') {
20650       val = true;
20651     } else {
20652       val = handlebarsGet(root, path, options);
20653     }
20654
20655     return Ember.View._classStringForValue(path, val, parsedPath.className, parsedPath.falsyClassName);
20656   };
20657
20658   // For each property passed, loop through and setup
20659   // an observer.
20660   forEach.call(classBindings.split(' '), function(binding) {
20661
20662     // Variable in which the old class value is saved. The observer function
20663     // closes over this variable, so it knows which string to remove when
20664     // the property changes.
20665     var oldClass;
20666
20667     var observer, invoker;
20668
20669     var parsedPath = Ember.View._parsePropertyPath(binding),
20670         path = parsedPath.path,
20671         pathRoot = context,
20672         normalized;
20673
20674     if (path !== '' && path !== 'this') {
20675       normalized = normalizePath(context, path, options.data);
20676
20677       pathRoot = normalized.root;
20678       path = normalized.path;
20679     }
20680
20681     // Set up an observer on the context. If the property changes, toggle the
20682     // class name.
20683     observer = function() {
20684       // Get the current value of the property
20685       newClass = classStringForPath(pathRoot, parsedPath, options);
20686       elem = bindAttrId ? view.$("[data-bindattr-" + bindAttrId + "='" + bindAttrId + "']") : view.$();
20687
20688       // If we can't find the element anymore, a parent template has been
20689       // re-rendered and we've been nuked. Remove the observer.
20690       if (!elem || elem.length === 0) {
20691         Ember.removeObserver(pathRoot, path, invoker);
20692       } else {
20693         // If we had previously added a class to the element, remove it.
20694         if (oldClass) {
20695           elem.removeClass(oldClass);
20696         }
20697
20698         // If necessary, add a new class. Make sure we keep track of it so
20699         // it can be removed in the future.
20700         if (newClass) {
20701           elem.addClass(newClass);
20702           oldClass = newClass;
20703         } else {
20704           oldClass = null;
20705         }
20706       }
20707     };
20708
20709     invoker = function() {
20710       Ember.run.scheduleOnce('render', observer);
20711     };
20712
20713     if (path !== '' && path !== 'this') {
20714       Ember.addObserver(pathRoot, path, invoker);
20715
20716       view.one('willClearRender', function() {
20717         Ember.removeObserver(pathRoot, path, invoker);
20718       });
20719     }
20720
20721     // We've already setup the observer; now we just need to figure out the
20722     // correct behavior right now on the first pass through.
20723     value = classStringForPath(pathRoot, parsedPath, options);
20724
20725     if (value) {
20726       ret.push(value);
20727
20728       // Make sure we save the current value so that it can be removed if the
20729       // observer fires.
20730       oldClass = value;
20731     }
20732   });
20733
20734   return ret;
20735 };
20736
20737
20738 })();
20739
20740
20741
20742 (function() {
20743 /*globals Handlebars */
20744
20745 // TODO: Don't require the entire module
20746 /**
20747 @module ember
20748 @submodule ember-handlebars
20749 */
20750
20751 var get = Ember.get, set = Ember.set;
20752 var PARENT_VIEW_PATH = /^parentView\./;
20753 var EmberHandlebars = Ember.Handlebars;
20754
20755 EmberHandlebars.ViewHelper = Ember.Object.create({
20756
20757   propertiesFromHTMLOptions: function(options, thisContext) {
20758     var hash = options.hash, data = options.data;
20759     var extensions = {},
20760         classes = hash['class'],
20761         dup = false;
20762
20763     if (hash.id) {
20764       extensions.elementId = hash.id;
20765       dup = true;
20766     }
20767
20768     if (classes) {
20769       classes = classes.split(' ');
20770       extensions.classNames = classes;
20771       dup = true;
20772     }
20773
20774     if (hash.classBinding) {
20775       extensions.classNameBindings = hash.classBinding.split(' ');
20776       dup = true;
20777     }
20778
20779     if (hash.classNameBindings) {
20780       if (extensions.classNameBindings === undefined) extensions.classNameBindings = [];
20781       extensions.classNameBindings = extensions.classNameBindings.concat(hash.classNameBindings.split(' '));
20782       dup = true;
20783     }
20784
20785     if (hash.attributeBindings) {
20786       Ember.assert("Setting 'attributeBindings' via Handlebars is not allowed. Please subclass Ember.View and set it there instead.");
20787       extensions.attributeBindings = null;
20788       dup = true;
20789     }
20790
20791     if (dup) {
20792       hash = Ember.$.extend({}, hash);
20793       delete hash.id;
20794       delete hash['class'];
20795       delete hash.classBinding;
20796     }
20797
20798     // Set the proper context for all bindings passed to the helper. This applies to regular attribute bindings
20799     // as well as class name bindings. If the bindings are local, make them relative to the current context
20800     // instead of the view.
20801     var path;
20802
20803     // Evaluate the context of regular attribute bindings:
20804     for (var prop in hash) {
20805       if (!hash.hasOwnProperty(prop)) { continue; }
20806
20807       // Test if the property ends in "Binding"
20808       if (Ember.IS_BINDING.test(prop) && typeof hash[prop] === 'string') {
20809         path = this.contextualizeBindingPath(hash[prop], data);
20810         if (path) { hash[prop] = path; }
20811       }
20812     }
20813
20814     // Evaluate the context of class name bindings:
20815     if (extensions.classNameBindings) {
20816       for (var b in extensions.classNameBindings) {
20817         var full = extensions.classNameBindings[b];
20818         if (typeof full === 'string') {
20819           // Contextualize the path of classNameBinding so this:
20820           //
20821           //     classNameBinding="isGreen:green"
20822           //
20823           // is converted to this:
20824           //
20825           //     classNameBinding="bindingContext.isGreen:green"
20826           var parsedPath = Ember.View._parsePropertyPath(full);
20827           path = this.contextualizeBindingPath(parsedPath.path, data);
20828           if (path) { extensions.classNameBindings[b] = path + parsedPath.classNames; }
20829         }
20830       }
20831     }
20832
20833     // Make the current template context available to the view
20834     // for the bindings set up above.
20835     extensions.bindingContext = thisContext;
20836
20837     return Ember.$.extend(hash, extensions);
20838   },
20839
20840   // Transform bindings from the current context to a context that can be evaluated within the view.
20841   // Returns null if the path shouldn't be changed.
20842   //
20843   // TODO: consider the addition of a prefix that would allow this method to return `path`.
20844   contextualizeBindingPath: function(path, data) {
20845     var normalized = Ember.Handlebars.normalizePath(null, path, data);
20846     if (normalized.isKeyword) {
20847       return 'templateData.keywords.' + path;
20848     } else if (Ember.isGlobalPath(path)) {
20849       return null;
20850     } else if (path === 'this') {
20851       return 'bindingContext';
20852     } else {
20853       return 'bindingContext.' + path;
20854     }
20855   },
20856
20857   helper: function(thisContext, path, options) {
20858     var inverse = options.inverse,
20859         data = options.data,
20860         view = data.view,
20861         fn = options.fn,
20862         hash = options.hash,
20863         newView;
20864
20865     if ('string' === typeof path) {
20866       newView = EmberHandlebars.get(thisContext, path, options);
20867       Ember.assert("Unable to find view at path '" + path + "'", !!newView);
20868     } else {
20869       newView = path;
20870     }
20871
20872     Ember.assert(Ember.String.fmt('You must pass a view class to the #view helper, not %@ (%@)', [path, newView]), Ember.View.detect(newView));
20873
20874     var viewOptions = this.propertiesFromHTMLOptions(options, thisContext);
20875     var currentView = data.view;
20876     viewOptions.templateData = options.data;
20877
20878     if (fn) {
20879       Ember.assert("You cannot provide a template block if you also specified a templateName", !get(viewOptions, 'templateName') && !get(newView.proto(), 'templateName'));
20880       viewOptions.template = fn;
20881     }
20882
20883     // We only want to override the `_context` computed property if there is
20884     // no specified controller. See View#_context for more information.
20885     if (!newView.proto().controller && !newView.proto().controllerBinding && !viewOptions.controller && !viewOptions.controllerBinding) {
20886       viewOptions._context = thisContext;
20887     }
20888
20889     currentView.appendChild(newView, viewOptions);
20890   }
20891 });
20892
20893 /**
20894   `{{view}}` inserts a new instance of `Ember.View` into a template passing its options
20895   to the `Ember.View`'s `create` method and using the supplied block as the view's own template.
20896
20897   An empty `<body>` and the following template:
20898
20899   ``` handlebars
20900   <script type="text/x-handlebars">
20901     A span:
20902     {{#view tagName="span"}}
20903       hello.
20904     {{/view}}
20905   </script>
20906   ```
20907
20908   Will result in HTML structure:
20909
20910   ``` html
20911   <body>
20912     <!-- Note: the handlebars template script 
20913          also results in a rendered Ember.View
20914          which is the outer <div> here -->
20915
20916     <div class="ember-view">
20917       A span:
20918       <span id="ember1" class="ember-view">
20919         Hello.
20920       </span>
20921     </div>
20922   </body>
20923   ```
20924
20925   ### parentView setting
20926
20927   The `parentView` property of the new `Ember.View` instance created through `{{view}}`
20928   will be set to the `Ember.View` instance of the template where `{{view}}` was called.
20929
20930   ``` javascript
20931   aView = Ember.View.create({
20932     template: Ember.Handlebars.compile("{{#view}} my parent: {{parentView.elementId}} {{/view}}")
20933   });
20934
20935   aView.appendTo('body');
20936   ```
20937     
20938   Will result in HTML structure:
20939
20940   ``` html
20941   <div id="ember1" class="ember-view">
20942     <div id="ember2" class="ember-view">
20943       my parent: ember1
20944     </div>
20945   </div>
20946   ```
20947
20948   ### Setting CSS id and class attributes
20949
20950   The HTML `id` attribute can be set on the `{{view}}`'s resulting element with the `id` option.
20951   This option will _not_ be passed to `Ember.View.create`.
20952
20953   ``` handlebars
20954   <script type="text/x-handlebars">
20955     {{#view tagName="span" id="a-custom-id"}}
20956       hello.
20957     {{/view}}
20958   </script>
20959   ```
20960
20961   Results in the following HTML structure:
20962
20963   ``` html
20964   <div class="ember-view">
20965     <span id="a-custom-id" class="ember-view">
20966       hello.
20967     </span>
20968   </div>
20969   ```
20970
20971   The HTML `class` attribute can be set on the `{{view}}`'s resulting element with
20972   the `class` or `classNameBindings` options. The `class` option
20973   will directly set the CSS `class` attribute and will not be passed to
20974   `Ember.View.create`. `classNameBindings` will be passed to `create` and use
20975   `Ember.View`'s class name binding functionality:
20976
20977   ``` handlebars
20978   <script type="text/x-handlebars">
20979     {{#view tagName="span" class="a-custom-class"}}
20980       hello.
20981     {{/view}}
20982   </script>
20983   ```
20984
20985   Results in the following HTML structure:
20986
20987   ``` html
20988   <div class="ember-view">
20989     <span id="ember2" class="ember-view a-custom-class">
20990       hello.
20991     </span>
20992   </div>
20993   ```
20994
20995   ### Supplying a different view class
20996
20997   `{{view}}` can take an optional first argument before its supplied options to specify a
20998   path to a custom view class.
20999
21000   ``` handlebars
21001   <script type="text/x-handlebars">
21002     {{#view "MyApp.CustomView"}}
21003       hello.
21004     {{/view}}
21005   </script>
21006   ```
21007
21008   The first argument can also be a relative path. Ember will search for the view class
21009   starting at the `Ember.View` of the template where `{{view}}` was used as the root object:
21010
21011   ``` javascript
21012   MyApp = Ember.Application.create({});
21013   MyApp.OuterView = Ember.View.extend({
21014     innerViewClass: Ember.View.extend({
21015       classNames: ['a-custom-view-class-as-property']
21016     }),
21017     template: Ember.Handlebars.compile('{{#view "innerViewClass"}} hi {{/view}}')
21018   });
21019
21020   MyApp.OuterView.create().appendTo('body');
21021   ```
21022
21023   Will result in the following HTML:
21024
21025   ``` html
21026   <div id="ember1" class="ember-view">
21027     <div id="ember2" class="ember-view a-custom-view-class-as-property"> 
21028       hi
21029     </div>
21030   </div>
21031   ```
21032
21033   ### Blockless use
21034
21035   If you supply a custom `Ember.View` subclass that specifies its own template
21036   or provide a `templateName` option to `{{view}}` it can be used without supplying a block.
21037   Attempts to use both a `templateName` option and supply a block will throw an error.
21038
21039   ``` handlebars
21040   <script type="text/x-handlebars">
21041     {{view "MyApp.ViewWithATemplateDefined"}}
21042   </script>
21043   ```
21044
21045   ### viewName property
21046
21047   You can supply a `viewName` option to `{{view}}`. The `Ember.View` instance will
21048   be referenced as a property of its parent view by this name.
21049
21050   ``` javascript
21051   aView = Ember.View.create({
21052     template: Ember.Handlebars.compile('{{#view viewName="aChildByName"}} hi {{/view}}')
21053   });
21054
21055   aView.appendTo('body');
21056   aView.get('aChildByName') // the instance of Ember.View created by {{view}} helper
21057   ```
21058
21059   @method view
21060   @for Ember.Handlebars.helpers
21061   @param {String} path
21062   @param {Hash} options
21063   @return {String} HTML string
21064 */
21065 EmberHandlebars.registerHelper('view', function(path, options) {
21066   Ember.assert("The view helper only takes a single argument", arguments.length <= 2);
21067
21068   // If no path is provided, treat path param as options.
21069   if (path && path.data && path.data.isRenderData) {
21070     options = path;
21071     path = "Ember.View";
21072   }
21073
21074   return EmberHandlebars.ViewHelper.helper(this, path, options);
21075 });
21076
21077
21078 })();
21079
21080
21081
21082 (function() {
21083 /*globals Handlebars */
21084
21085 // TODO: Don't require all of this module
21086 /**
21087 @module ember
21088 @submodule ember-handlebars
21089 */
21090
21091 var get = Ember.get, handlebarsGet = Ember.Handlebars.get, fmt = Ember.String.fmt;
21092
21093 /**
21094   `{{collection}}` is a `Ember.Handlebars` helper for adding instances of
21095   `Ember.CollectionView` to a template.  See `Ember.CollectionView` for additional
21096   information on how a `CollectionView` functions.
21097
21098   `{{collection}}`'s primary use is as a block helper with a `contentBinding` option
21099   pointing towards an `Ember.Array`-compatible object.  An `Ember.View` instance will
21100   be created for each item in its `content` property. Each view will have its own
21101   `content` property set to the appropriate item in the collection.
21102
21103   The provided block will be applied as the template for each item's view.
21104
21105   Given an empty `<body>` the following template:
21106
21107   ``` handlebars
21108   <script type="text/x-handlebars">
21109     {{#collection contentBinding="App.items"}}
21110       Hi {{view.content.name}}
21111     {{/collection}}
21112   </script>
21113   ```
21114
21115   And the following application code
21116
21117   ``` javascript
21118   App = Ember.Application.create()
21119   App.items = [
21120     Ember.Object.create({name: 'Dave'}),
21121     Ember.Object.create({name: 'Mary'}),
21122     Ember.Object.create({name: 'Sara'})
21123   ]
21124   ```
21125
21126   Will result in the HTML structure below
21127
21128   ``` html
21129   <div class="ember-view">
21130     <div class="ember-view">Hi Dave</div>
21131     <div class="ember-view">Hi Mary</div>
21132     <div class="ember-view">Hi Sara</div>
21133   </div>
21134   ```
21135
21136   ### Blockless Use
21137   If you provide an `itemViewClass` option that has its own `template` you can omit
21138   the block.
21139
21140   The following template:
21141
21142   ``` handlebars
21143   <script type="text/x-handlebars">
21144     {{collection contentBinding="App.items" itemViewClass="App.AnItemView"}}
21145   </script>
21146   ```
21147
21148   And application code
21149
21150   ``` javascript
21151   App = Ember.Application.create();
21152   App.items = [
21153     Ember.Object.create({name: 'Dave'}),
21154     Ember.Object.create({name: 'Mary'}),
21155     Ember.Object.create({name: 'Sara'})
21156   ];
21157
21158   App.AnItemView = Ember.View.extend({
21159     template: Ember.Handlebars.compile("Greetings {{view.content.name}}")
21160   });
21161   ```
21162
21163   Will result in the HTML structure below
21164
21165   ``` html
21166   <div class="ember-view">
21167     <div class="ember-view">Greetings Dave</div>
21168     <div class="ember-view">Greetings Mary</div>
21169     <div class="ember-view">Greetings Sara</div>
21170   </div>
21171   ```
21172
21173   ### Specifying a CollectionView subclass
21174
21175   By default the `{{collection}}` helper will create an instance of `Ember.CollectionView`.
21176   You can supply a `Ember.CollectionView` subclass to the helper by passing it
21177   as the first argument:
21178
21179   ``` handlebars
21180   <script type="text/x-handlebars">
21181     {{#collection App.MyCustomCollectionClass contentBinding="App.items"}}
21182       Hi {{view.content.name}}
21183     {{/collection}}
21184   </script>
21185   ```
21186
21187
21188   ### Forwarded `item.*`-named Options
21189
21190   As with the `{{view}}`, helper options passed to the `{{collection}}` will be set on
21191   the resulting `Ember.CollectionView` as properties. Additionally, options prefixed with
21192   `item` will be applied to the views rendered for each item (note the camelcasing):
21193
21194   ``` handlebars
21195   <script type="text/x-handlebars">
21196     {{#collection contentBinding="App.items"
21197                   itemTagName="p"
21198                   itemClassNames="greeting"}}
21199       Howdy {{view.content.name}}
21200     {{/collection}}
21201   </script>
21202   ```
21203
21204   Will result in the following HTML structure:
21205
21206   ``` html
21207   <div class="ember-view">
21208     <p class="ember-view greeting">Howdy Dave</p>
21209     <p class="ember-view greeting">Howdy Mary</p>
21210     <p class="ember-view greeting">Howdy Sara</p>
21211   </div>
21212   ```
21213
21214   @method collection
21215   @for Ember.Handlebars.helpers
21216   @param {String} path
21217   @param {Hash} options
21218   @return {String} HTML string
21219   @deprecated Use `{{each}}` helper instead.
21220 */
21221 Ember.Handlebars.registerHelper('collection', function(path, options) {
21222   Ember.deprecate("Using the {{collection}} helper without specifying a class has been deprecated as the {{each}} helper now supports the same functionality.", path !== 'collection');
21223
21224   // If no path is provided, treat path param as options.
21225   if (path && path.data && path.data.isRenderData) {
21226     options = path;
21227     path = undefined;
21228     Ember.assert("You cannot pass more than one argument to the collection helper", arguments.length === 1);
21229   } else {
21230     Ember.assert("You cannot pass more than one argument to the collection helper", arguments.length === 2);
21231   }
21232
21233   var fn = options.fn;
21234   var data = options.data;
21235   var inverse = options.inverse;
21236
21237   // If passed a path string, convert that into an object.
21238   // Otherwise, just default to the standard class.
21239   var collectionClass;
21240   collectionClass = path ? handlebarsGet(this, path, options) : Ember.CollectionView;
21241   Ember.assert(fmt("%@ #collection: Could not find collection class %@", [data.view, path]), !!collectionClass);
21242
21243   var hash = options.hash, itemHash = {}, match;
21244
21245   // Extract item view class if provided else default to the standard class
21246   var itemViewClass, itemViewPath = hash.itemViewClass;
21247   var collectionPrototype = collectionClass.proto();
21248   delete hash.itemViewClass;
21249   itemViewClass = itemViewPath ? handlebarsGet(collectionPrototype, itemViewPath, options) : collectionPrototype.itemViewClass;
21250   Ember.assert(fmt("%@ #collection: Could not find itemViewClass %@", [data.view, itemViewPath]), !!itemViewClass);
21251
21252   // Go through options passed to the {{collection}} helper and extract options
21253   // that configure item views instead of the collection itself.
21254   for (var prop in hash) {
21255     if (hash.hasOwnProperty(prop)) {
21256       match = prop.match(/^item(.)(.*)$/);
21257
21258       if(match) {
21259         // Convert itemShouldFoo -> shouldFoo
21260         itemHash[match[1].toLowerCase() + match[2]] = hash[prop];
21261         // Delete from hash as this will end up getting passed to the
21262         // {{view}} helper method.
21263         delete hash[prop];
21264       }
21265     }
21266   }
21267
21268   var tagName = hash.tagName || collectionPrototype.tagName;
21269
21270   if (fn) {
21271     itemHash.template = fn;
21272     delete options.fn;
21273   }
21274
21275   var emptyViewClass;
21276   if (inverse && inverse !== Handlebars.VM.noop) {
21277     emptyViewClass = get(collectionPrototype, 'emptyViewClass');
21278     emptyViewClass = emptyViewClass.extend({
21279           template: inverse,
21280           tagName: itemHash.tagName
21281     });
21282   } else if (hash.emptyViewClass) {
21283     emptyViewClass = handlebarsGet(this, hash.emptyViewClass, options);
21284   }
21285   hash.emptyView = emptyViewClass;
21286
21287   if (hash.eachHelper === 'each') {
21288     itemHash._context = Ember.computed(function() {
21289       return get(this, 'content');
21290     }).property('content');
21291     delete hash.eachHelper;
21292   }
21293
21294   var viewOptions = Ember.Handlebars.ViewHelper.propertiesFromHTMLOptions({ data: data, hash: itemHash }, this);
21295   hash.itemViewClass = itemViewClass.extend(viewOptions);
21296
21297   return Ember.Handlebars.helpers.view.call(this, collectionClass, options);
21298 });
21299
21300
21301 })();
21302
21303
21304
21305 (function() {
21306 /*globals Handlebars */
21307 /**
21308 @module ember
21309 @submodule ember-handlebars
21310 */
21311
21312 var handlebarsGet = Ember.Handlebars.get;
21313
21314 /**
21315   `unbound` allows you to output a property without binding. *Important:* The
21316   output will not be updated if the property changes. Use with caution.
21317
21318   ``` handlebars
21319   <div>{{unbound somePropertyThatDoesntChange}}</div>
21320   ```
21321
21322   @method unbound
21323   @for Ember.Handlebars.helpers
21324   @param {String} property
21325   @return {String} HTML string
21326 */
21327 Ember.Handlebars.registerHelper('unbound', function(property, fn) {
21328   var context = (fn.contexts && fn.contexts[0]) || this;
21329   return handlebarsGet(context, property, fn);
21330 });
21331
21332 })();
21333
21334
21335
21336 (function() {
21337 /*jshint debug:true*/
21338 /**
21339 @module ember
21340 @submodule ember-handlebars
21341 */
21342
21343 var handlebarsGet = Ember.Handlebars.get, normalizePath = Ember.Handlebars.normalizePath;
21344
21345 /**
21346   `log` allows you to output the value of a value in the current rendering
21347   context.
21348
21349   ``` handlebars
21350   {{log myVariable}}
21351   ```
21352
21353   @method log
21354   @for Ember.Handlebars.helpers
21355   @param {String} property
21356 */
21357 Ember.Handlebars.registerHelper('log', function(property, options) {
21358   var context = (options.contexts && options.contexts[0]) || this,
21359       normalized = normalizePath(context, property, options.data),
21360       pathRoot = normalized.root,
21361       path = normalized.path,
21362       value = (path === 'this') ? pathRoot : handlebarsGet(pathRoot, path, options);
21363   Ember.Logger.log(value);
21364 });
21365
21366 /**
21367   The `debugger` helper executes the `debugger` statement in the current
21368   context.
21369
21370   ``` handlebars
21371   {{debugger}}
21372   ```
21373
21374   @method debugger
21375   @for Ember.Handlebars.helpers
21376   @param {String} property
21377 */
21378 Ember.Handlebars.registerHelper('debugger', function() {
21379   debugger;
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 Ember.Handlebars.EachView = Ember.CollectionView.extend(Ember._Metamorph, {
21395   itemViewClass: Ember._MetamorphView,
21396   emptyViewClass: Ember._MetamorphView,
21397
21398   createChildView: function(view, attrs) {
21399     view = this._super(view, attrs);
21400
21401     // At the moment, if a container view subclass wants
21402     // to insert keywords, it is responsible for cloning
21403     // the keywords hash. This will be fixed momentarily.
21404     var keyword = get(this, 'keyword');
21405
21406     if (keyword) {
21407       var data = get(view, 'templateData');
21408
21409       data = Ember.copy(data);
21410       data.keywords = view.cloneKeywords();
21411       set(view, 'templateData', data);
21412
21413       var content = get(view, 'content');
21414
21415       // In this case, we do not bind, because the `content` of
21416       // a #each item cannot change.
21417       data.keywords[keyword] = content;
21418     }
21419
21420     return view;
21421   }
21422 });
21423
21424 /**
21425   The `{{#each}}` helper loops over elements in a collection, rendering its block once for each item:
21426
21427   ``` javascript
21428   Developers = [{name: 'Yehuda'},{name: 'Tom'}, {name: 'Paul'}];
21429   ```
21430
21431   ``` handlebars
21432   {{#each Developers}}
21433     {{name}}
21434   {{/each}}
21435   ```
21436
21437   `{{each}}` supports an alternative syntax with element naming:
21438
21439   ``` handlebars
21440   {{#each person in Developers}}
21441     {{person.name}}
21442   {{/each}}
21443   ```
21444
21445   When looping over objects that do not have properties, `{{this}}` can be used to render the object:
21446
21447   ``` javascript
21448   DeveloperNames = ['Yehuda', 'Tom', 'Paul']
21449   ```
21450
21451   ``` handlebars
21452   {{#each DeveloperNames}}
21453     {{this}}
21454   {{/each}}
21455   ```
21456
21457   ### Blockless Use
21458
21459   If you provide an `itemViewClass` option that has its own `template` you can omit
21460   the block in a similar way to how it can be done with the collection helper.
21461
21462   The following template:
21463
21464   ``` handlebars
21465   <script type="text/x-handlebars">
21466     {{#view App.MyView }}
21467       {{each view.items itemViewClass="App.AnItemView"}} 
21468     {{/view}}
21469   </script>
21470   ```
21471
21472   And application code
21473
21474   ``` javascript
21475   App = Ember.Application.create({
21476     MyView: Ember.View.extend({
21477       items: [
21478         Ember.Object.create({name: 'Dave'}),
21479         Ember.Object.create({name: 'Mary'}),
21480         Ember.Object.create({name: 'Sara'})
21481       ]
21482     })
21483   });
21484
21485   App.AnItemView = Ember.View.extend({
21486     template: Ember.Handlebars.compile("Greetings {{name}}")
21487   });
21488       
21489   App.initialize();
21490   ```
21491       
21492   Will result in the HTML structure below
21493
21494   ``` html
21495   <div class="ember-view">
21496     <div class="ember-view">Greetings Dave</div>
21497     <div class="ember-view">Greetings Mary</div>
21498     <div class="ember-view">Greetings Sara</div>
21499   </div>
21500   ```
21501
21502
21503   @method each
21504   @for Ember.Handlebars.helpers
21505   @param [name] {String} name for item (used with `in`)
21506   @param path {String} path
21507 */
21508 Ember.Handlebars.registerHelper('each', function(path, options) {
21509   if (arguments.length === 4) {
21510     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");
21511
21512     var keywordName = arguments[0];
21513
21514     options = arguments[3];
21515     path = arguments[2];
21516     if (path === '') { path = "this"; }
21517
21518     options.hash.keyword = keywordName;
21519   } else {
21520     options.hash.eachHelper = 'each';
21521   }
21522
21523   options.hash.contentBinding = path;
21524   // Set up emptyView as a metamorph with no tag
21525   //options.hash.emptyViewClass = Ember._MetamorphView;
21526
21527   return Ember.Handlebars.helpers.collection.call(this, 'Ember.Handlebars.EachView', options);
21528 });
21529
21530 })();
21531
21532
21533
21534 (function() {
21535 /**
21536 @module ember
21537 @submodule ember-handlebars
21538 */
21539
21540 /**
21541   `template` allows you to render a template from inside another template.
21542   This allows you to re-use the same template in multiple places. For example:
21543
21544   ``` handlebars
21545   <script type="text/x-handlebars">
21546     {{#with loggedInUser}}
21547       Last Login: {{lastLogin}}
21548       User Info: {{template "user_info"}}
21549     {{/with}}
21550   </script>
21551
21552   <script type="text/x-handlebars" data-template-name="user_info">
21553     Name: <em>{{name}}</em>
21554     Karma: <em>{{karma}}</em>
21555   </script>
21556   ```
21557
21558   This helper looks for templates in the global Ember.TEMPLATES hash. If you
21559   add &lt;script&gt; tags to your page with the `data-template-name` attribute set,
21560   they will be compiled and placed in this hash automatically.
21561
21562   You can also manually register templates by adding them to the hash:
21563
21564   ``` javascript
21565   Ember.TEMPLATES["my_cool_template"] = Ember.Handlebars.compile('<b>{{user}}</b>');
21566   ```
21567
21568   @method template
21569   @for Ember.Handlebars.helpers
21570   @param {String} templateName the template to render
21571 */
21572
21573 Ember.Handlebars.registerHelper('template', function(name, options) {
21574   var template = Ember.TEMPLATES[name];
21575
21576   Ember.assert("Unable to find template with name '"+name+"'.", !!template);
21577
21578   Ember.TEMPLATES[name](this, { data: options.data });
21579 });
21580
21581 })();
21582
21583
21584
21585 (function() {
21586 /**
21587 @module ember
21588 @submodule ember-handlebars
21589 */
21590
21591 var EmberHandlebars = Ember.Handlebars,
21592     handlebarsGet = EmberHandlebars.get,
21593     get = Ember.get,
21594     a_slice = Array.prototype.slice;
21595
21596 var ActionHelper = EmberHandlebars.ActionHelper = {
21597   registeredActions: {}
21598 };
21599
21600 ActionHelper.registerAction = function(actionName, options) {
21601   var actionId = (++Ember.uuid).toString();
21602
21603   ActionHelper.registeredActions[actionId] = {
21604     eventName: options.eventName,
21605     handler: function(event) {
21606       var modifier = event.shiftKey || event.metaKey || event.altKey || event.ctrlKey,
21607           secondaryClick = event.which > 1, // IE9 may return undefined
21608           nonStandard = modifier || secondaryClick;
21609
21610       if (options.link && nonStandard) {
21611         // Allow the browser to handle special link clicks normally
21612         return;
21613       }
21614
21615       event.preventDefault();
21616
21617       event.view = options.view;
21618
21619       if (options.hasOwnProperty('context')) {
21620         event.context = options.context;
21621       }
21622
21623       if (options.hasOwnProperty('contexts')) {
21624         event.contexts = options.contexts;
21625       }
21626
21627       var target = options.target;
21628
21629       // Check for StateManager (or compatible object)
21630       if (target.isState && typeof target.send === 'function') {
21631         return target.send(actionName, event);
21632       } else {
21633         Ember.assert(Ember.String.fmt('Target %@ does not have action %@', [target, actionName]), target[actionName]);
21634         return target[actionName].call(target, event);
21635       }
21636     }
21637   };
21638
21639   options.view.on('willClearRender', function() {
21640     delete ActionHelper.registeredActions[actionId];
21641   });
21642
21643   return actionId;
21644 };
21645
21646 /**
21647   The `{{action}}` helper registers an HTML element within a template for
21648   DOM event handling and forwards that interaction to the view's `controller.target`
21649   or supplied `target` option (see 'Specifying a Target'). By default the
21650   `controller.target` is set to the Application's router.
21651
21652   User interaction with that element will invoke the supplied action name on
21653   the appropriate target.
21654
21655   Given the following Handlebars template on the page
21656
21657   ``` handlebars
21658   <script type="text/x-handlebars" data-template-name='a-template'>
21659     <div {{action anActionName target="view"}}>
21660       click me
21661     </div>
21662   </script>
21663   ```
21664
21665   And application code
21666
21667   ``` javascript
21668   AView = Ember.View.extend({
21669     templateName: 'a-template',
21670     anActionName: function(event){}
21671   });
21672
21673   aView = AView.create();
21674   aView.appendTo('body');
21675   ```
21676
21677   Will results in the following rendered HTML
21678
21679   ``` html
21680   <div class="ember-view">
21681     <div data-ember-action="1">
21682       click me
21683     </div>
21684   </div>
21685   ```
21686
21687   Clicking "click me" will trigger the `anActionName` method of the `aView`
21688   object with a  `jQuery.Event` object as its argument. The `jQuery.Event`
21689   object will be extended to include a `view` property that is set to the
21690   original view interacted with (in this case the `aView` object).
21691
21692   ### Event Propagation
21693
21694   Events triggered through the action helper will automatically have
21695   `.preventDefault()` called on them. You do not need to do so in your event
21696   handlers. To stop propagation of the event, simply return `false` from your
21697   handler.
21698
21699   If you need the default handler to trigger you should either register your
21700   own event handler, or use event methods on your view class. See Ember.View
21701   'Responding to Browser Events' for more information.
21702
21703   ### Specifying DOM event type
21704
21705   By default the `{{action}}` helper registers for DOM `click` events. You can
21706   supply an `on` option to the helper to specify a different DOM event name:
21707
21708   ``` handlebars
21709   <script type="text/x-handlebars" data-template-name='a-template'>
21710     <div {{action anActionName on="doubleClick"}}>
21711       click me
21712     </div>
21713   </script>
21714   ```
21715
21716   See Ember.View 'Responding to Browser Events' for a list of
21717   acceptable DOM event names.
21718
21719   Because `{{action}}` depends on Ember's event dispatch system it will only
21720   function if an `Ember.EventDispatcher` instance is available. An
21721   `Ember.EventDispatcher` instance will be created when a new
21722   `Ember.Application` is created. Having an instance of `Ember.Application`
21723   will satisfy this requirement.
21724
21725
21726   ### Specifying a Target
21727
21728   There are several possible target objects for `{{action}}` helpers:
21729
21730   In a typical `Ember.Router`-backed Application where views are managed
21731   through use of the `{{outlet}}` helper, actions will be forwarded to the
21732   current state of the Applications's Router. See Ember.Router 'Responding
21733   to User-initiated Events' for more information.
21734
21735   If you manually set the `target` property on the controller of a template's
21736   `Ember.View` instance, the specifed `controller.target` will become the target
21737   for any actions. Likely custom values for a controller's `target` are the
21738   controller itself or a StateManager other than the Application's Router.
21739
21740   If the templates's view lacks a controller property the view itself is the target.
21741
21742   Finally, a `target` option can be provided to the helper to change which object
21743   will receive the method call. This option must be a string representing a
21744   path to an object:
21745
21746   ``` handlebars
21747   <script type="text/x-handlebars" data-template-name='a-template'>
21748     <div {{action anActionName target="MyApplication.someObject"}}>
21749       click me
21750     </div>
21751   </script>
21752   ```
21753
21754   Clicking "click me" in the rendered HTML of the above template will trigger
21755   the  `anActionName` method of the object at `MyApplication.someObject`.
21756   The first argument to this method will be a `jQuery.Event` extended to
21757   include a `view` property that is set to the original view interacted with.
21758
21759   A path relative to the template's `Ember.View` instance can also be used as
21760   a target:
21761
21762   ``` handlebars
21763   <script type="text/x-handlebars" data-template-name='a-template'>
21764     <div {{action anActionName target="parentView"}}>
21765       click me
21766     </div>
21767   </script>
21768   ```
21769
21770   Clicking "click me" in the rendered HTML of the above template will trigger
21771   the `anActionName` method of the view's parent view.
21772
21773   The `{{action}}` helper is `Ember.StateManager` aware. If the target of the
21774   action is an `Ember.StateManager` instance `{{action}}` will use the `send`
21775   functionality of StateManagers. The documentation for `Ember.StateManager`
21776   has additional information about this use.
21777
21778   If an action's target does not implement a method that matches the supplied
21779   action name an error will be thrown.
21780
21781   ``` handlebars
21782   <script type="text/x-handlebars" data-template-name='a-template'>
21783     <div {{action aMethodNameThatIsMissing}}>
21784       click me
21785     </div>
21786   </script>
21787   ```
21788
21789   With the following application code
21790
21791   ``` javascript
21792   AView = Ember.View.extend({
21793     templateName; 'a-template',
21794     // note: no method 'aMethodNameThatIsMissing'
21795     anActionName: function(event){}
21796   });
21797
21798   aView = AView.create();
21799   aView.appendTo('body');
21800   ```
21801
21802   Will throw `Uncaught TypeError: Cannot call method 'call' of undefined` when
21803   "click me" is clicked.
21804
21805   ### Specifying a context
21806
21807   You may optionally specify objects to pass as contexts to the `{{action}}` helper
21808   by providing property paths as the subsequent parameters. These objects are made
21809   available as the `contexts` (also `context` if there is only one) properties in the
21810   `jQuery.Event` object:
21811
21812   ``` handlebars
21813   <script type="text/x-handlebars" data-template-name='a-template'>
21814     {{#each person in people}}
21815       <div {{action edit person}}>
21816         click me
21817       </div>
21818     {{/each}}
21819   </script>
21820   ```
21821
21822   Clicking "click me" will trigger the `edit` method of the view's context with a
21823   `jQuery.Event` object containing the person object as its context.
21824
21825   @method action
21826   @for Ember.Handlebars.helpers
21827   @param {String} actionName
21828   @param {Object...} contexts
21829   @param {Hash} options
21830 */
21831 EmberHandlebars.registerHelper('action', function(actionName) {
21832   var options = arguments[arguments.length - 1],
21833       contexts = a_slice.call(arguments, 1, -1);
21834
21835   var hash = options.hash,
21836       view = options.data.view,
21837       target, controller, link;
21838
21839   // create a hash to pass along to registerAction
21840   var action = {
21841     eventName: hash.on || "click"
21842   };
21843
21844   action.view = view = get(view, 'concreteView');
21845
21846   if (hash.target) {
21847     target = handlebarsGet(this, hash.target, options);
21848   } else if (controller = options.data.keywords.controller) {
21849     target = get(controller, 'target');
21850   }
21851
21852   action.target = target = target || view;
21853
21854   if (contexts.length) {
21855     action.contexts = contexts = Ember.EnumerableUtils.map(contexts, function(context) {
21856       return handlebarsGet(this, context, options);
21857     }, this);
21858     action.context = contexts[0];
21859   }
21860
21861   var output = [], url;
21862
21863   if (hash.href && target.urlForEvent) {
21864     url = target.urlForEvent.apply(target, [actionName].concat(contexts));
21865     output.push('href="' + url + '"');
21866     action.link = true;
21867   }
21868
21869   var actionId = ActionHelper.registerAction(actionName, action);
21870   output.push('data-ember-action="' + actionId + '"');
21871
21872   return new EmberHandlebars.SafeString(output.join(" "));
21873 });
21874
21875 })();
21876
21877
21878
21879 (function() {
21880 /**
21881 @module ember
21882 @submodule ember-handlebars
21883 */
21884
21885 var get = Ember.get, set = Ember.set;
21886
21887 /**
21888
21889   When used in a Handlebars template that is assigned to an `Ember.View` instance's
21890   `layout` property Ember will render the layout template first, inserting the view's
21891   own rendered output at the `{{ yield }}` location.
21892
21893   An empty `<body>` and the following application code:
21894
21895   ``` javascript
21896   AView = Ember.View.extend({
21897     classNames: ['a-view-with-layout'],
21898     layout: Ember.Handlebars.compile('<div class="wrapper">{{ yield }}</div>'),
21899     template: Ember.Handlebars.compile('<span>I am wrapped</span>')
21900   });
21901
21902   aView = AView.create();
21903   aView.appendTo('body');
21904   ```
21905
21906   Will result in the following HTML output:
21907
21908   ``` html
21909   <body>
21910     <div class='ember-view a-view-with-layout'>
21911       <div class="wrapper">
21912         <span>I am wrapped</span>
21913       </div>
21914     </div>
21915   </body>
21916   ```
21917
21918   The yield helper cannot be used outside of a template assigned to an `Ember.View`'s `layout` property
21919   and will throw an error if attempted.
21920
21921   ``` javascript
21922   BView = Ember.View.extend({
21923     classNames: ['a-view-with-layout'],
21924     template: Ember.Handlebars.compile('{{yield}}')
21925   });
21926
21927   bView = BView.create();
21928   bView.appendTo('body');
21929
21930   // throws
21931   // Uncaught Error: assertion failed: You called yield in a template that was not a layout
21932   ```
21933
21934   @method yield
21935   @for Ember.Handlebars.helpers
21936   @param {Hash} options
21937   @return {String} HTML string
21938 */
21939 Ember.Handlebars.registerHelper('yield', function(options) {
21940   var view = options.data.view, template;
21941
21942   while (view && !get(view, 'layout')) {
21943     view = get(view, 'parentView');
21944   }
21945
21946   Ember.assert("You called yield in a template that was not a layout", !!view);
21947
21948   template = get(view, 'template');
21949
21950   if (template) { template(this, options); }
21951 });
21952
21953 })();
21954
21955
21956
21957 (function() {
21958 /**
21959 @module ember
21960 @submodule ember-handlebars
21961 */
21962
21963 Ember.Handlebars.OutletView = Ember.ContainerView.extend(Ember._Metamorph);
21964
21965 /**
21966   The `outlet` helper allows you to specify that the current
21967   view's controller will fill in the view for a given area.
21968
21969   ``` handlebars
21970   {{outlet}}
21971   ```
21972
21973   By default, when the the current controller's `view` property changes, the
21974   outlet will replace its current view with the new view. You can set the
21975   `view` property directly, but it's normally best to use `connectOutlet`.
21976
21977   ``` javascript
21978   # Instantiate App.PostsView and assign to `view`, so as to render into outlet.
21979   controller.connectOutlet('posts');
21980   ```
21981
21982   You can also specify a particular name other than `view`:
21983
21984   ``` handlebars
21985   {{outlet masterView}}
21986   {{outlet detailView}}
21987   ```
21988
21989   Then, you can control several outlets from a single controller.
21990
21991   ``` javascript
21992   # Instantiate App.PostsView and assign to controller.masterView.
21993   controller.connectOutlet('masterView', 'posts');
21994   # Also, instantiate App.PostInfoView and assign to controller.detailView.
21995   controller.connectOutlet('detailView', 'postInfo');
21996   ```
21997
21998   @method outlet
21999   @for Ember.Handlebars.helpers
22000   @param {String} property the property on the controller
22001     that holds the view for this outlet
22002 */
22003 Ember.Handlebars.registerHelper('outlet', function(property, options) {
22004   if (property && property.data && property.data.isRenderData) {
22005     options = property;
22006     property = 'view';
22007   }
22008
22009   options.hash.currentViewBinding = "view.context." + property;
22010
22011   return Ember.Handlebars.helpers.view.call(this, Ember.Handlebars.OutletView, options);
22012 });
22013
22014 })();
22015
22016
22017
22018 (function() {
22019
22020 })();
22021
22022
22023
22024 (function() {
22025
22026 })();
22027
22028
22029
22030 (function() {
22031 /**
22032 @module ember
22033 @submodule ember-handlebars
22034 */
22035
22036 var set = Ember.set, get = Ember.get;
22037
22038 /**
22039   The `Ember.Checkbox` view class renders a checkbox [input](https://developer.mozilla.org/en/HTML/Element/Input) 
22040   element. It allows for binding an Ember property (`checked`) to the status of the checkbox.
22041
22042   Example:
22043
22044   ``` handlebars
22045   {{view Ember.Checkbox checkedBinding="receiveEmail"}}
22046   ```
22047
22048   You can add a `label` tag yourself in the template where the Ember.Checkbox is being used.
22049
22050   ``` html
22051   <label>        
22052     {{view Ember.Checkbox classNames="applicaton-specific-checkbox"}}
22053     Some Title
22054   </label>
22055   ```
22056
22057
22058   The `checked` attribute of an Ember.Checkbox object should always be set
22059   through the Ember object or by interacting with its rendered element representation
22060   via the mouse, keyboard, or touch.  Updating the value of the checkbox via jQuery will
22061   result in the checked value of the object and its element losing synchronization.
22062
22063   ## Layout and LayoutName properties
22064   Because HTML `input` elements are self closing `layout` and `layoutName` properties will
22065   not be applied. See `Ember.View`'s layout section for more information.
22066
22067   @class Checkbox
22068   @namespace Ember
22069   @extends Ember.View
22070 */
22071 Ember.Checkbox = Ember.View.extend({
22072   classNames: ['ember-checkbox'],
22073
22074   tagName: 'input',
22075
22076   attributeBindings: ['type', 'checked', 'disabled', 'tabindex'],
22077
22078   type: "checkbox",
22079   checked: false,
22080   disabled: false,
22081
22082   init: function() {
22083     this._super();
22084     this.on("change", this, this._updateElementValue);
22085   },
22086
22087   _updateElementValue: function() {
22088     set(this, 'checked', this.$().prop('checked'));
22089   }
22090 });
22091
22092 })();
22093
22094
22095
22096 (function() {
22097 /**
22098 @module ember
22099 @submodule ember-handlebars
22100 */
22101
22102 var get = Ember.get, set = Ember.set;
22103
22104 /**
22105   Shared mixin used by Ember.TextField and Ember.TextArea.
22106
22107   @class TextSupport
22108   @namespace Ember
22109   @extends Ember.Mixin
22110   @private
22111 */
22112 Ember.TextSupport = Ember.Mixin.create({
22113   value: "",
22114
22115   attributeBindings: ['placeholder', 'disabled', 'maxlength', 'tabindex'],
22116   placeholder: null,
22117   disabled: false,
22118   maxlength: null,
22119
22120   insertNewline: Ember.K,
22121   cancel: Ember.K,
22122
22123   init: function() {
22124     this._super();
22125     this.on("focusOut", this, this._elementValueDidChange);
22126     this.on("change", this, this._elementValueDidChange);
22127     this.on("keyUp", this, this.interpretKeyEvents);
22128   },
22129
22130   interpretKeyEvents: function(event) {
22131     var map = Ember.TextSupport.KEY_EVENTS;
22132     var method = map[event.keyCode];
22133
22134     this._elementValueDidChange();
22135     if (method) { return this[method](event); }
22136   },
22137
22138   _elementValueDidChange: function() {
22139     set(this, 'value', this.$().val());
22140   }
22141
22142 });
22143
22144 Ember.TextSupport.KEY_EVENTS = {
22145   13: 'insertNewline',
22146   27: 'cancel'
22147 };
22148
22149 })();
22150
22151
22152
22153 (function() {
22154 /**
22155 @module ember
22156 @submodule ember-handlebars
22157 */
22158
22159 var get = Ember.get, set = Ember.set;
22160
22161 /**
22162   The `Ember.TextField` view class renders a text
22163   [input](https://developer.mozilla.org/en/HTML/Element/Input) element. It
22164   allows for binding Ember properties to the text field contents (`value`),
22165   live-updating as the user inputs text.
22166
22167   Example:
22168
22169   ``` handlebars
22170   {{view Ember.TextField valueBinding="firstName"}}
22171   ```
22172
22173   ## Layout and LayoutName properties
22174   Because HTML `input` elements are self closing `layout` and `layoutName` properties will
22175   not be applied. See `Ember.View`'s layout section for more information.
22176
22177   ## HTML Attributes
22178
22179   By default `Ember.TextField` provides support for `type`, `value`, `size`, `placeholder`,
22180   `disabled`, `maxlength` and `tabindex` attributes on a textarea. If you need to support
22181   more attributes have a look at the `attributeBindings` property in `Ember.View`'s
22182   HTML Attributes section.
22183
22184   To globally add support for additional attributes you can reopen `Ember.TextField` or
22185   `Ember.TextSupport`.
22186
22187   ``` javascript
22188   Ember.TextSupport.reopen({
22189     attributeBindings: ["required"]
22190   })
22191   ```
22192
22193   @class TextField
22194   @namespace Ember
22195   @extends Ember.View
22196   @uses Ember.TextSupport
22197 */
22198 Ember.TextField = Ember.View.extend(Ember.TextSupport,
22199   /** @scope Ember.TextField.prototype */ {
22200
22201   classNames: ['ember-text-field'],
22202   tagName: "input",
22203   attributeBindings: ['type', 'value', 'size'],
22204
22205   /**
22206     The value attribute of the input element. As the user inputs text, this
22207     property is updated live.
22208
22209     @property value
22210     @type String
22211     @default ""
22212   */
22213   value: "",
22214
22215   /**
22216     The type attribute of the input element.
22217
22218     @property type
22219     @type String
22220     @default "text"
22221   */
22222   type: "text",
22223
22224   /**
22225     The size of the text field in characters.
22226
22227     @property size
22228     @type String
22229     @default null
22230   */
22231   size: null
22232 });
22233
22234 })();
22235
22236
22237
22238 (function() {
22239 /**
22240 @module ember
22241 @submodule ember-handlebars
22242 */
22243
22244 var get = Ember.get, set = Ember.set;
22245
22246 /**
22247   @class Button
22248   @namespace Ember
22249   @extends Ember.View
22250   @uses Ember.TargetActionSupport
22251   @deprecated
22252 */
22253 Ember.Button = Ember.View.extend(Ember.TargetActionSupport, {
22254   classNames: ['ember-button'],
22255   classNameBindings: ['isActive'],
22256
22257   tagName: 'button',
22258
22259   propagateEvents: false,
22260
22261   attributeBindings: ['type', 'disabled', 'href', 'tabindex'],
22262
22263   /**
22264     @private
22265
22266     Overrides TargetActionSupport's targetObject computed
22267     property to use Handlebars-specific path resolution.
22268
22269     @property targetObject
22270   */
22271   targetObject: Ember.computed(function() {
22272     var target = get(this, 'target'),
22273         root = get(this, 'context'),
22274         data = get(this, 'templateData');
22275
22276     if (typeof target !== 'string') { return target; }
22277
22278     return Ember.Handlebars.get(root, target, { data: data });
22279   }).property('target'),
22280
22281   // Defaults to 'button' if tagName is 'input' or 'button'
22282   type: Ember.computed(function(key, value) {
22283     var tagName = this.get('tagName');
22284     if (value !== undefined) { this._type = value; }
22285     if (this._type !== undefined) { return this._type; }
22286     if (tagName === 'input' || tagName === 'button') { return 'button'; }
22287   }).property('tagName'),
22288
22289   disabled: false,
22290
22291   // Allow 'a' tags to act like buttons
22292   href: Ember.computed(function() {
22293     return this.get('tagName') === 'a' ? '#' : null;
22294   }).property('tagName'),
22295
22296   mouseDown: function() {
22297     if (!get(this, 'disabled')) {
22298       set(this, 'isActive', true);
22299       this._mouseDown = true;
22300       this._mouseEntered = true;
22301     }
22302     return get(this, 'propagateEvents');
22303   },
22304
22305   mouseLeave: function() {
22306     if (this._mouseDown) {
22307       set(this, 'isActive', false);
22308       this._mouseEntered = false;
22309     }
22310   },
22311
22312   mouseEnter: function() {
22313     if (this._mouseDown) {
22314       set(this, 'isActive', true);
22315       this._mouseEntered = true;
22316     }
22317   },
22318
22319   mouseUp: function(event) {
22320     if (get(this, 'isActive')) {
22321       // Actually invoke the button's target and action.
22322       // This method comes from the Ember.TargetActionSupport mixin.
22323       this.triggerAction();
22324       set(this, 'isActive', false);
22325     }
22326
22327     this._mouseDown = false;
22328     this._mouseEntered = false;
22329     return get(this, 'propagateEvents');
22330   },
22331
22332   keyDown: function(event) {
22333     // Handle space or enter
22334     if (event.keyCode === 13 || event.keyCode === 32) {
22335       this.mouseDown();
22336     }
22337   },
22338
22339   keyUp: function(event) {
22340     // Handle space or enter
22341     if (event.keyCode === 13 || event.keyCode === 32) {
22342       this.mouseUp();
22343     }
22344   },
22345
22346   // TODO: Handle proper touch behavior.  Including should make inactive when
22347   // finger moves more than 20x outside of the edge of the button (vs mouse
22348   // which goes inactive as soon as mouse goes out of edges.)
22349
22350   touchStart: function(touch) {
22351     return this.mouseDown(touch);
22352   },
22353
22354   touchEnd: function(touch) {
22355     return this.mouseUp(touch);
22356   },
22357
22358   init: function() {
22359     Ember.deprecate("Ember.Button is deprecated and will be removed from future releases. Consider using the `{{action}}` helper.");
22360     this._super();
22361   }
22362 });
22363
22364 })();
22365
22366
22367
22368 (function() {
22369 /**
22370 @module ember
22371 @submodule ember-handlebars
22372 */
22373
22374 var get = Ember.get, set = Ember.set;
22375
22376 /**
22377   The `Ember.TextArea` view class renders a
22378   [textarea](https://developer.mozilla.org/en/HTML/Element/textarea) element.
22379   It allows for binding Ember properties to the text area contents (`value`),
22380   live-updating as the user inputs text.
22381
22382   ## Layout and LayoutName properties
22383
22384   Because HTML `textarea` elements do not contain inner HTML the `layout` and `layoutName` 
22385   properties will not be applied. See `Ember.View`'s layout section for more information.
22386
22387   ## HTML Attributes
22388
22389   By default `Ember.TextArea` provides support for `rows`, `cols`, `placeholder`, `disabled`,
22390   `maxlength` and `tabindex` attributes on a textarea. If you need to support  more
22391   attributes have a look at the `attributeBindings` property in `Ember.View`'s HTML Attributes section.
22392
22393   To globally add support for additional attributes you can reopen `Ember.TextArea` or `Ember.TextSupport`.
22394
22395   ``` javascript
22396   Ember.TextSupport.reopen({
22397     attributeBindings: ["required"]
22398   })
22399   ```
22400
22401   @class TextArea
22402   @namespace Ember
22403   @extends Ember.View
22404   @uses Ember.TextSupport
22405 */
22406 Ember.TextArea = Ember.View.extend(Ember.TextSupport, {
22407   classNames: ['ember-text-area'],
22408
22409   tagName: "textarea",
22410   attributeBindings: ['rows', 'cols'],
22411   rows: null,
22412   cols: null,
22413
22414   _updateElementValue: Ember.observer(function() {
22415     // We do this check so cursor position doesn't get affected in IE
22416     var value = get(this, 'value'),
22417         $el = this.$();
22418     if ($el && value !== $el.val()) {
22419       $el.val(value);
22420     }
22421   }, 'value'),
22422
22423   init: function() {
22424     this._super();
22425     this.on("didInsertElement", this, this._updateElementValue);
22426   }
22427
22428 });
22429
22430 })();
22431
22432
22433
22434 (function() {
22435 /**
22436 @module ember
22437 @submodule ember-handlebars
22438 */
22439
22440 /**
22441 @class TabContainerView
22442 @namespace Ember
22443 @deprecated
22444 @extends Ember.View
22445 */
22446 Ember.TabContainerView = Ember.View.extend({
22447   init: function() {
22448     Ember.deprecate("Ember.TabContainerView is deprecated and will be removed from future releases.");
22449     this._super();
22450   }
22451 });
22452
22453 })();
22454
22455
22456
22457 (function() {
22458 /**
22459 @module ember
22460 @submodule ember-handlebars
22461 */
22462
22463 var get = Ember.get;
22464
22465 /**
22466   @class TabPaneView
22467   @namespace Ember
22468   @extends Ember.View
22469   @deprecated
22470 */
22471 Ember.TabPaneView = Ember.View.extend({
22472   tabsContainer: Ember.computed(function() {
22473     return this.nearestOfType(Ember.TabContainerView);
22474   }).property().volatile(),
22475
22476   isVisible: Ember.computed(function() {
22477     return get(this, 'viewName') === get(this, 'tabsContainer.currentView');
22478   }).property('tabsContainer.currentView').volatile(),
22479
22480   init: function() {
22481     Ember.deprecate("Ember.TabPaneView is deprecated and will be removed from future releases.");
22482     this._super();
22483   }
22484 });
22485
22486 })();
22487
22488
22489
22490 (function() {
22491 /**
22492 @module ember
22493 @submodule ember-handlebars
22494 */
22495
22496 var get = Ember.get, setPath = Ember.setPath;
22497
22498 /**
22499 @class TabView
22500 @namespace Ember
22501 @extends Ember.View
22502 @deprecated
22503 */
22504 Ember.TabView = Ember.View.extend({
22505   tabsContainer: Ember.computed(function() {
22506     return this.nearestInstanceOf(Ember.TabContainerView);
22507   }).property().volatile(),
22508
22509   mouseUp: function() {
22510     setPath(this, 'tabsContainer.currentView', get(this, 'value'));
22511   },
22512
22513   init: function() {
22514     Ember.deprecate("Ember.TabView is deprecated and will be removed from future releases.");
22515     this._super();
22516   }
22517 });
22518
22519 })();
22520
22521
22522
22523 (function() {
22524
22525 })();
22526
22527
22528
22529 (function() {
22530 /*jshint eqeqeq:false */
22531
22532 /**
22533 @module ember
22534 @submodule ember-handlebars
22535 */
22536
22537 var set = Ember.set,
22538     get = Ember.get,
22539     indexOf = Ember.EnumerableUtils.indexOf,
22540     indexesOf = Ember.EnumerableUtils.indexesOf,
22541     replace = Ember.EnumerableUtils.replace,
22542     isArray = Ember.isArray;
22543
22544 /**
22545   The Ember.Select view class renders a
22546   [select](https://developer.mozilla.org/en/HTML/Element/select) HTML element,
22547   allowing the user to choose from a list of options. 
22548
22549   The text and `value` property of each `<option>` element within the `<select>` element
22550   are populated from the objects in the Element.Select's `content` property. The
22551   underlying data object of the selected `<option>` is stored in the
22552   Element.Select's `value` property.
22553
22554   ### `content` as an array of Strings
22555   The simplest version of an Ember.Select takes an array of strings as its `content` property.
22556   The string will be used as both the `value` property and the inner text of each `<option>`
22557   element inside the rendered `<select>`.
22558
22559   Example:
22560
22561   ``` javascript
22562   App.names = ["Yehuda", "Tom"];
22563   ```
22564
22565   ``` handlebars
22566   {{view Ember.Select contentBinding="App.names"}}
22567   ```
22568
22569   Would result in the following HTML:
22570
22571   ``` html
22572   <select class="ember-select">
22573     <option value="Yehuda">Yehuda</option>
22574     <option value="Tom">Tom</option>
22575   </select>
22576   ```
22577
22578   You can control which `<option>` is selected through the Ember.Select's
22579   `value` property directly or as a binding:
22580
22581   ``` javascript
22582   App.names = Ember.Object.create({
22583     selected: 'Tom',
22584     content: ["Yehuda", "Tom"]
22585   });
22586   ```
22587
22588   ``` handlebars
22589   {{view Ember.Select
22590          contentBinding="App.names.content"
22591          valueBinding="App.names.selected"
22592   }}
22593   ```
22594
22595   Would result in the following HTML with the `<option>` for 'Tom' selected:
22596
22597   ``` html
22598   <select class="ember-select">
22599     <option value="Yehuda">Yehuda</option>
22600     <option value="Tom" selected="selected">Tom</option>
22601   </select>
22602   ```
22603
22604   A user interacting with the rendered `<select>` to choose "Yehuda" would update
22605   the value of `App.names.selected` to "Yehuda".
22606
22607   ### `content` as an Array of Objects
22608   An Ember.Select can also take an array of JavaScript or Ember objects
22609   as its `content` property.
22610
22611   When using objects you need to tell the Ember.Select which property should be
22612   accessed on each object to supply the `value` attribute of the `<option>`
22613   and which property should be used to supply the element text.
22614
22615   The `optionValuePath` option is used to specify the path on each object to
22616   the desired property for the `value` attribute.  The `optionLabelPath` 
22617   specifies the path on each object to the desired property for the 
22618   element's text. Both paths must reference each object itself as 'content':
22619
22620   ``` javascript
22621   App.programmers = [
22622       Ember.Object.create({firstName: "Yehuda", id: 1}),
22623       Ember.Object.create({firstName: "Tom",    id: 2})
22624     ];
22625   ```
22626
22627   ``` handlebars
22628   {{view Ember.Select
22629          contentBinding="App.programmers"
22630          optionValuePath="content.id"
22631          optionLabelPath="content.firstName"}}
22632   ```
22633
22634   Would result in the following HTML:
22635
22636   ``` html
22637   <select class="ember-select">
22638     <option value>Please Select</option>
22639     <option value="1">Yehuda</option>
22640     <option value="2">Tom</option>
22641   </select>
22642   ```
22643
22644
22645   The `value` attribute of the selected `<option>` within an Ember.Select
22646   can be bound to a property on another object by providing a
22647   `valueBinding` option:
22648
22649   ``` javascript
22650   App.programmers = [
22651       Ember.Object.create({firstName: "Yehuda", id: 1}),
22652       Ember.Object.create({firstName: "Tom",    id: 2})
22653     ];
22654
22655   App.currentProgrammer = Ember.Object.create({
22656     id: 2
22657   });
22658   ```
22659
22660   ``` handlebars
22661   {{view Ember.Select
22662          contentBinding="App.programmers"
22663          optionValuePath="content.id"
22664          optionLabelPath="content.firstName"
22665          valueBinding="App.currentProgrammer.id"}}
22666   ```
22667
22668   Would result in the following HTML with a selected option:
22669
22670   ``` html
22671   <select class="ember-select">
22672     <option value>Please Select</option>
22673     <option value="1">Yehuda</option>
22674     <option value="2" selected="selected">Tom</option>
22675   </select>
22676   ```
22677
22678   Interacting with the rendered element by selecting the first option
22679   ('Yehuda') will update the `id` value of `App.currentProgrammer`
22680   to match the `value` property of the newly selected `<option>`.
22681
22682   Alternatively, you can control selection through the underlying objects
22683   used to render each object providing a `selectionBinding`. When the selected
22684   `<option>` is changed, the property path provided to `selectionBinding`
22685   will be updated to match the content object of the rendered `<option>`
22686   element: 
22687
22688   ``` javascript
22689   App.controller = Ember.Object.create({
22690     selectedPerson: null,
22691     content: [
22692       Ember.Object.create({firstName: "Yehuda", id: 1}),
22693       Ember.Object.create({firstName: "Tom",    id: 2})
22694     ]
22695   });
22696   ```
22697
22698   ``` handlebars
22699   {{view Ember.Select
22700          contentBinding="App.controller.content"
22701          optionValuePath="content.id"
22702          optionLabelPath="content.firstName"
22703          selectionBinding="App.controller.selectedPerson"}}
22704   ```
22705
22706   Would result in the following HTML with a selected option:
22707
22708   ``` html
22709   <select class="ember-select">
22710     <option value>Please Select</option>
22711     <option value="1">Yehuda</option>
22712     <option value="2" selected="selected">Tom</option>
22713   </select>
22714   ```
22715
22716
22717   Interacting with the rendered element by selecting the first option
22718   ('Yehuda') will update the `selectedPerson` value of `App.controller`
22719   to match the content object of the newly selected `<option>`. In this
22720   case it is the first object in the `App.content.content` 
22721
22722   ### Supplying a Prompt
22723
22724   A `null` value for the Ember.Select's `value` or `selection` property
22725   results in there being no `<option>` with a `selected` attribute:
22726
22727   ``` javascript
22728   App.controller = Ember.Object.create({
22729     selected: null,
22730     content: [
22731       "Yehuda",
22732       "Tom"
22733     ]
22734   });
22735   ```
22736
22737   ``` handlebars
22738   {{view Ember.Select
22739          contentBinding="App.controller.content"
22740          valueBinding="App.controller.selected"
22741   }}
22742   ```
22743
22744   Would result in the following HTML:
22745
22746   ``` html
22747   <select class="ember-select">
22748     <option value="Yehuda">Yehuda</option>
22749     <option value="Tom">Tom</option>
22750   </select>
22751   ```
22752
22753   Although `App.controller.selected` is `null` and no `<option>`
22754   has a `selected` attribute the rendered HTML will display the
22755   first item as though it were selected. You can supply a string
22756   value for the Ember.Select to display when there is no selection
22757   with the `prompt` option:
22758
22759   ``` javascript
22760   App.controller = Ember.Object.create({
22761     selected: null,
22762     content: [
22763       "Yehuda",
22764       "Tom"
22765     ]
22766   });
22767   ```
22768
22769   ``` handlebars
22770   {{view Ember.Select
22771          contentBinding="App.controller.content"
22772          valueBinding="App.controller.selected"
22773          prompt="Please select a name"
22774   }}
22775   ```
22776
22777   Would result in the following HTML:
22778
22779   ``` html
22780   <select class="ember-select">
22781     <option>Please select a name</option>
22782     <option value="Yehuda">Yehuda</option>
22783     <option value="Tom">Tom</option>
22784   </select>
22785   ```
22786
22787   @class Select
22788   @namespace Ember
22789   @extends Ember.View
22790 */
22791 Ember.Select = Ember.View.extend(
22792   /** @scope Ember.Select.prototype */ {
22793
22794   tagName: 'select',
22795   classNames: ['ember-select'],
22796   defaultTemplate: Ember.Handlebars.compile('{{#if view.prompt}}<option value>{{view.prompt}}</option>{{/if}}{{#each view.content}}{{view Ember.SelectOption contentBinding="this"}}{{/each}}'),
22797   attributeBindings: ['multiple', 'disabled', 'tabindex'],
22798
22799   /**
22800     The `multiple` attribute of the select element. Indicates whether multiple
22801     options can be selected.
22802
22803     @property multiple
22804     @type Boolean
22805     @default false
22806   */
22807   multiple: false,
22808
22809   disabled: false,
22810
22811   /**
22812     The list of options.
22813
22814     If `optionLabelPath` and `optionValuePath` are not overridden, this should
22815     be a list of strings, which will serve simultaneously as labels and values.
22816
22817     Otherwise, this should be a list of objects. For instance:
22818
22819         content: Ember.A([
22820             { id: 1, firstName: 'Yehuda' },
22821             { id: 2, firstName: 'Tom' }
22822           ]),
22823         optionLabelPath: 'content.firstName',
22824         optionValuePath: 'content.id'
22825
22826     @property content
22827     @type Array
22828     @default null
22829   */
22830   content: null,
22831
22832   /**
22833     When `multiple` is false, the element of `content` that is currently
22834     selected, if any.
22835
22836     When `multiple` is true, an array of such elements.
22837
22838     @property selection
22839     @type Object or Array
22840     @default null
22841   */
22842   selection: null,
22843
22844   /**
22845     In single selection mode (when `multiple` is false), value can be used to get
22846     the current selection's value or set the selection by it's value.
22847
22848     It is not currently supported in multiple selection mode.
22849
22850     @property value
22851     @type String
22852     @default null
22853   */
22854   value: Ember.computed(function(key, value) {
22855     if (arguments.length === 2) { return value; }
22856
22857     var valuePath = get(this, 'optionValuePath').replace(/^content\.?/, '');
22858     return valuePath ? get(this, 'selection.' + valuePath) : get(this, 'selection');
22859   }).property('selection'),
22860
22861   /**
22862     If given, a top-most dummy option will be rendered to serve as a user
22863     prompt.
22864
22865     @property prompt
22866     @type String
22867     @default null
22868   */
22869   prompt: null,
22870
22871   /**
22872     The path of the option labels. See `content`.
22873
22874     @property optionLabelPath
22875     @type String
22876     @default 'content'
22877   */
22878   optionLabelPath: 'content',
22879
22880   /**
22881     The path of the option values. See `content`.
22882
22883     @property optionValuePath
22884     @type String
22885     @default 'content'
22886   */
22887   optionValuePath: 'content',
22888
22889   _change: function() {
22890     if (get(this, 'multiple')) {
22891       this._changeMultiple();
22892     } else {
22893       this._changeSingle();
22894     }
22895   },
22896
22897   selectionDidChange: Ember.observer(function() {
22898     var selection = get(this, 'selection');
22899     if (get(this, 'multiple')) {
22900       if (!isArray(selection)) {
22901         set(this, 'selection', Ember.A([selection]));
22902         return;
22903       }
22904       this._selectionDidChangeMultiple();
22905     } else {
22906       this._selectionDidChangeSingle();
22907     }
22908   }, 'selection.@each'),
22909
22910   valueDidChange: Ember.observer(function() {
22911     var content = get(this, 'content'),
22912         value = get(this, 'value'),
22913         valuePath = get(this, 'optionValuePath').replace(/^content\.?/, ''),
22914         selectedValue = (valuePath ? get(this, 'selection.' + valuePath) : get(this, 'selection')),
22915         selection;
22916
22917     if (value !== selectedValue) {
22918       selection = content.find(function(obj) {
22919         return value === (valuePath ? get(obj, valuePath) : obj);
22920       });
22921
22922       this.set('selection', selection);
22923     }
22924   }, 'value'),
22925
22926
22927   _triggerChange: function() {
22928     var selection = get(this, 'selection');
22929     var value = get(this, 'value');
22930
22931     if (selection) { this.selectionDidChange(); }
22932     if (value) { this.valueDidChange(); }
22933
22934     this._change();
22935   },
22936
22937   _changeSingle: function() {
22938     var selectedIndex = this.$()[0].selectedIndex,
22939         content = get(this, 'content'),
22940         prompt = get(this, 'prompt');
22941
22942     if (!content) { return; }
22943     if (prompt && selectedIndex === 0) { set(this, 'selection', null); return; }
22944
22945     if (prompt) { selectedIndex -= 1; }
22946     set(this, 'selection', content.objectAt(selectedIndex));
22947   },
22948
22949
22950   _changeMultiple: function() {
22951     var options = this.$('option:selected'),
22952         prompt = get(this, 'prompt'),
22953         offset = prompt ? 1 : 0,
22954         content = get(this, 'content'),
22955         selection = get(this, 'selection');
22956
22957     if (!content){ return; }
22958     if (options) {
22959       var selectedIndexes = options.map(function(){
22960         return this.index - offset;
22961       }).toArray();
22962       var newSelection = content.objectsAt(selectedIndexes);
22963
22964       if (isArray(selection)) {
22965         replace(selection, 0, get(selection, 'length'), newSelection);
22966       } else {
22967         set(this, 'selection', newSelection);
22968       }
22969     }
22970   },
22971
22972   _selectionDidChangeSingle: function() {
22973     var el = this.get('element');
22974     if (!el) { return; }
22975
22976     var content = get(this, 'content'),
22977         selection = get(this, 'selection'),
22978         selectionIndex = content ? indexOf(content, selection) : -1,
22979         prompt = get(this, 'prompt');
22980
22981     if (prompt) { selectionIndex += 1; }
22982     if (el) { el.selectedIndex = selectionIndex; }
22983   },
22984
22985   _selectionDidChangeMultiple: function() {
22986     var content = get(this, 'content'),
22987         selection = get(this, 'selection'),
22988         selectedIndexes = content ? indexesOf(content, selection) : [-1],
22989         prompt = get(this, 'prompt'),
22990         offset = prompt ? 1 : 0,
22991         options = this.$('option'),
22992         adjusted;
22993
22994     if (options) {
22995       options.each(function() {
22996         adjusted = this.index > -1 ? this.index - offset : -1;
22997         this.selected = indexOf(selectedIndexes, adjusted) > -1;
22998       });
22999     }
23000   },
23001
23002   init: function() {
23003     this._super();
23004     this.on("didInsertElement", this, this._triggerChange);
23005     this.on("change", this, this._change);
23006   }
23007 });
23008
23009 Ember.SelectOption = Ember.View.extend({
23010   tagName: 'option',
23011   attributeBindings: ['value', 'selected'],
23012
23013   defaultTemplate: function(context, options) {
23014     options = { data: options.data, hash: {} };
23015     Ember.Handlebars.helpers.bind.call(context, "view.label", options);
23016   },
23017
23018   init: function() {
23019     this.labelPathDidChange();
23020     this.valuePathDidChange();
23021
23022     this._super();
23023   },
23024
23025   selected: Ember.computed(function() {
23026     var content = get(this, 'content'),
23027         selection = get(this, 'parentView.selection');
23028     if (get(this, 'parentView.multiple')) {
23029       return selection && indexOf(selection, content.valueOf()) > -1;
23030     } else {
23031       // Primitives get passed through bindings as objects... since
23032       // `new Number(4) !== 4`, we use `==` below
23033       return content == selection;
23034     }
23035   }).property('content', 'parentView.selection').volatile(),
23036
23037   labelPathDidChange: Ember.observer(function() {
23038     var labelPath = get(this, 'parentView.optionLabelPath');
23039
23040     if (!labelPath) { return; }
23041
23042     Ember.defineProperty(this, 'label', Ember.computed(function() {
23043       return get(this, labelPath);
23044     }).property(labelPath));
23045   }, 'parentView.optionLabelPath'),
23046
23047   valuePathDidChange: Ember.observer(function() {
23048     var valuePath = get(this, 'parentView.optionValuePath');
23049
23050     if (!valuePath) { return; }
23051
23052     Ember.defineProperty(this, 'value', Ember.computed(function() {
23053       return get(this, valuePath);
23054     }).property(valuePath));
23055   }, 'parentView.optionValuePath')
23056 });
23057
23058 })();
23059
23060
23061
23062 (function() {
23063
23064 })();
23065
23066
23067
23068 (function() {
23069 /*globals Handlebars */
23070 /**
23071 @module ember
23072 @submodule ember-handlebars
23073 */
23074
23075 /**
23076   @private
23077
23078   Find templates stored in the head tag as script tags and make them available
23079   to Ember.CoreView in the global Ember.TEMPLATES object. This will be run as as
23080   jQuery DOM-ready callback.
23081
23082   Script tags with "text/x-handlebars" will be compiled
23083   with Ember's Handlebars and are suitable for use as a view's template.
23084   Those with type="text/x-raw-handlebars" will be compiled with regular
23085   Handlebars and are suitable for use in views' computed properties.
23086
23087   @method bootstrap
23088   @for Ember.Handlebars
23089   @static
23090   @param ctx
23091 */
23092 Ember.Handlebars.bootstrap = function(ctx) {
23093   var selectors = 'script[type="text/x-handlebars"], script[type="text/x-raw-handlebars"]';
23094
23095   Ember.$(selectors, ctx)
23096     .each(function() {
23097     // Get a reference to the script tag
23098     var script = Ember.$(this),
23099         type   = script.attr('type');
23100
23101     var compile = (script.attr('type') === 'text/x-raw-handlebars') ?
23102                   Ember.$.proxy(Handlebars.compile, Handlebars) :
23103                   Ember.$.proxy(Ember.Handlebars.compile, Ember.Handlebars),
23104       // Get the name of the script, used by Ember.View's templateName property.
23105       // First look for data-template-name attribute, then fall back to its
23106       // id if no name is found.
23107       templateName = script.attr('data-template-name') || script.attr('id') || 'application',
23108       template = compile(script.html());
23109
23110     // For templates which have a name, we save them and then remove them from the DOM
23111     Ember.TEMPLATES[templateName] = template;
23112
23113     // Remove script tag from DOM
23114     script.remove();
23115   });
23116 };
23117
23118 function bootstrap() {
23119   Ember.Handlebars.bootstrap( Ember.$(document) );
23120 }
23121
23122 /*
23123   We tie this to application.load to ensure that we've at least
23124   attempted to bootstrap at the point that the application is loaded.
23125
23126   We also tie this to document ready since we're guaranteed that all
23127   the inline templates are present at this point.
23128
23129   There's no harm to running this twice, since we remove the templates
23130   from the DOM after processing.
23131 */
23132
23133 Ember.onLoad('application', bootstrap);
23134
23135 })();
23136
23137
23138
23139 (function() {
23140 /**
23141 Ember Handlebars
23142
23143 @module ember
23144 @submodule ember-handlebars
23145 @requires ember-views
23146 */
23147
23148 })();
23149
23150 // Version: v1.0.0-pre.2-1-gd1a2e84
23151 // Last commit: d1a2e84 (2012-10-25 13:51:08 -0700)
23152
23153
23154 (function() {
23155 /**
23156 Ember
23157
23158 @module ember
23159 */
23160
23161 })();
23162