/*!
 * @overview  Ember - JavaScript Application Framework
 * @copyright Copyright 2011-2014 Tilde Inc. and contributors
 *            Portions Copyright 2006-2011 Strobe Inc.
 *            Portions Copyright 2008-2011 Apple Inc. All rights reserved.
 * @license   Licensed under MIT license
 *            See https://raw.github.com/emberjs/ember.js/master/LICENSE
 * @version   1.7.0-beta.4+pre.4b6ff143
 */

(function() {
    var define, requireModule, require, requirejs, Ember;

    (function() {
        Ember = this.Ember = this.Ember || {};
        if (typeof Ember === 'undefined') {
            Ember = {}
        };

        if (typeof Ember.__loader === 'undefined') {
            var registry = {}, seen = {};

            define = function(name, deps, callback) {
                registry[name] = {
                    deps: deps,
                    callback: callback 
                };
            };

            requirejs = require = requireModule = function(name) {
                if (seen.hasOwnProperty(name)) {
                    return seen[name];
                }
                seen[name] = {};

                if (!registry[name]) {
                    throw new Error("Could not find module " + name);
                }

                var mod = registry[name],
                deps = mod.deps,
                callback = mod.callback,
                reified = [],
                exports;

                for (var i = 0, l = deps.length; i < l; i++) {
                    if (deps[i] === 'exports') {
                        reified.push(exports = {});
                    } else {
                        reified.push(requireModule(resolve(deps[i])));
                    }
                }

                var value = callback.apply(this, reified);
                return seen[name] = exports || value;

                function resolve(child) {
                    if (child.charAt(0) !== '.') {
                        return child;
                    }
                    var parts = child.split("/");
                    var parentBase = name.split("/").slice(0, -1);

                    for (var i = 0, l = parts.length; i < l; i++) {
                        var part = parts[i];

                        if (part === '..') {
                            parentBase.pop();
                        } else if (part === '.') {
                            continue;
                        } else {
                            parentBase.push(part);
                        }
                    }

                    return parentBase.join("/");
                }
            };
            requirejs._eak_seen = registry;

            Ember.__loader = {
                define: define,
                require: require,
                registry: registry
            };
        } else {
            define = Ember.__loader.define;
            requirejs = require = requireModule = Ember.__loader.require;
        }
    })();

    define("backburner",
    ["backburner/utils", "backburner/deferred_action_queues", "exports"],
    function(__dependency1__, __dependency2__, __exports__) {
        "use strict";
        var Utils = __dependency1__["default"];
        var DeferredActionQueues = __dependency2__.DeferredActionQueues;

        var slice = [].slice,
        pop = [].pop,
        each = Utils.each,
        isString = Utils.isString,
        isFunction = Utils.isFunction,
        isNumber = Utils.isNumber,
        timers = [],
        global = this,
        NUMBER = /\d+/;

        // In IE 6-8, try/finally doesn't work without a catch.
        // Unfortunately, this is impossible to test for since wrapping it in a parent try/catch doesn't trigger the bug.
        // This tests for another broken try/catch behavior that only exhibits in the same versions of IE.
        var needsIETryCatchFix = (function(e, x) {
            try {
                x();
            } catch (e) {}
            // jshint ignore:line
            return !!e;
        })();

        function isCoercableNumber(number) {
            return isNumber(number) || NUMBER.test(number);
        }

        function Backburner(queueNames, options) {
            this.queueNames = queueNames;
            this.options = options || {};
            if (!this.options.defaultQueue) {
                this.options.defaultQueue = queueNames[0];
            }
            this.instanceStack = [];
            this._debouncees = [];
            this._throttlers = [];
        }

        Backburner.prototype = {
            queueNames: null,
            options: null,
            currentInstance: null,
            instanceStack: null,

            begin: function() {
                var options = this.options,
                onBegin = options && options.onBegin,
                previousInstance = this.currentInstance;

                if (previousInstance) {
                    this.instanceStack.push(previousInstance);
                }

                this.currentInstance = new DeferredActionQueues(this.queueNames, options);
                if (onBegin) {
                    onBegin(this.currentInstance, previousInstance);
                }
            },

            end: function() {
                var options = this.options,
                onEnd = options && options.onEnd,
                currentInstance = this.currentInstance,
                nextInstance = null;

                // Prevent double-finally bug in Safari 6.0.2 and iOS 6
                // This bug appears to be resolved in Safari 6.0.5 and iOS 7
                var finallyAlreadyCalled = false;
                try {
                    currentInstance.flush();
                } finally {
                    if (!finallyAlreadyCalled) {
                        finallyAlreadyCalled = true;

                        this.currentInstance = null;

                        if (this.instanceStack.length) {
                            nextInstance = this.instanceStack.pop();
                            this.currentInstance = nextInstance;
                        }

                        if (onEnd) {
                            onEnd(currentInstance, nextInstance);
                        }
                    }
                }
            },

            run: function(target, method /*, args */
            ) {
                var onError = getOnError(this.options);

                this.begin();

                if (!method) {
                    method = target;
                    target = null;
                }

                if (isString(method)) {
                    method = target[method];
                }

                var args = slice.call(arguments, 2);

                // guard against Safari 6's double-finally bug
                var didFinally = false;

                if (onError) {
                    try {
                        return method.apply(target, args);
                    } catch (error) {
                        onError(error);
                    } finally {
                        if (!didFinally) {
                            didFinally = true;
                            this.end();
                        }
                    }
                } else {
                    try {
                        return method.apply(target, args);
                    } finally {
                        if (!didFinally) {
                            didFinally = true;
                            this.end();
                        }
                    }
                }
            },

            defer: function(queueName, target, method /* , args */
            ) {
                if (!method) {
                    method = target;
                    target = null;
                }

                if (isString(method)) {
                    method = target[method];
                }

                var stack = this.DEBUG ? new Error() : undefined,
                args = arguments.length > 3 ? slice.call(arguments, 3) : undefined;
                if (!this.currentInstance) {
                    createAutorun(this);
                }
                return this.currentInstance.schedule(queueName, target, method, args, false, stack);
            },

            deferOnce: function(queueName, target, method /* , args */
            ) {
                if (!method) {
                    method = target;
                    target = null;
                }

                if (isString(method)) {
                    method = target[method];
                }

                var stack = this.DEBUG ? new Error() : undefined,
                args = arguments.length > 3 ? slice.call(arguments, 3) : undefined;
                if (!this.currentInstance) {
                    createAutorun(this);
                }
                return this.currentInstance.schedule(queueName, target, method, args, true, stack);
            },

            setTimeout: function() {
                var args = slice.call(arguments),
                length = args.length,
                method, wait, target,
                methodOrTarget, methodOrWait, methodOrArgs;

                if (length === 0) {
                    return;
                } else if (length === 1) {
                    method = args.shift();
                    wait = 0;
                } else if (length === 2) {
                    methodOrTarget = args[0];
                    methodOrWait = args[1];

                    if (isFunction(methodOrWait) || isFunction(methodOrTarget[methodOrWait])) {
                        target = args.shift();
                        method = args.shift();
                        wait = 0;
                    } else if (isCoercableNumber(methodOrWait)) {
                        method = args.shift();
                        wait = args.shift();
                    } else {
                        method = args.shift();
                        wait = 0;
                    }
                } else {
                    var last = args[args.length - 1];

                    if (isCoercableNumber(last)) {
                        wait = args.pop();
                    } else {
                        wait = 0;
                    }

                    methodOrTarget = args[0];
                    methodOrArgs = args[1];

                    if (isFunction(methodOrArgs) || (isString(methodOrArgs) &&
                    methodOrTarget !== null &&
                    methodOrArgs in methodOrTarget)) {
                        target = args.shift();
                        method = args.shift();
                    } else {
                        method = args.shift();
                    }
                }

                var executeAt = ( + new Date()) + parseInt(wait, 10);

                if (isString(method)) {
                    method = target[method];
                }

                var onError = getOnError(this.options);

                function fn() {
                    if (onError) {
                        try {
                            method.apply(target, args);
                        } catch (e) {
                            onError(e);
                        }
                    } else {
                        method.apply(target, args);
                    }
                }

                // find position to insert
                var i = searchTimer(executeAt, timers);

                timers.splice(i, 0, executeAt, fn);

                updateLaterTimer(this, executeAt, wait);

                return fn;
            },

            throttle: function(target, method /* , args, wait, [immediate] */
            ) {
                var self = this,
                args = arguments,
                immediate = pop.call(args),
                wait,
                throttler,
                index,
                timer;

                if (isNumber(immediate) || isString(immediate)) {
                    wait = immediate;
                    immediate = true;
                } else {
                    wait = pop.call(args);
                }

                wait = parseInt(wait, 10);

                index = findThrottler(target, method, this._throttlers);
                if (index > -1) {
                    return this._throttlers[index];
                }
                // throttled

                timer = global.setTimeout(function() {
                    if (!immediate) {
                        self.run.apply(self, args);
                    }
                    var index = findThrottler(target, method, self._throttlers);
                    if (index > -1) {
                        self._throttlers.splice(index, 1);
                    }
                }, wait);

                if (immediate) {
                    self.run.apply(self, args);
                }

                throttler = [target, method, timer];

                this._throttlers.push(throttler);

                return throttler;
            },

            debounce: function(target, method /* , args, wait, [immediate] */
            ) {
                var self = this,
                args = arguments,
                immediate = pop.call(args),
                wait,
                index,
                debouncee,
                timer;

                if (isNumber(immediate) || isString(immediate)) {
                    wait = immediate;
                    immediate = false;
                } else {
                    wait = pop.call(args);
                }

                wait = parseInt(wait, 10);
                // Remove debouncee
                index = findDebouncee(target, method, this._debouncees);

                if (index > -1) {
                    debouncee = this._debouncees[index];
                    this._debouncees.splice(index, 1);
                    clearTimeout(debouncee[2]);
                }

                timer = global.setTimeout(function() {
                    if (!immediate) {
                        self.run.apply(self, args);
                    }
                    var index = findDebouncee(target, method, self._debouncees);
                    if (index > -1) {
                        self._debouncees.splice(index, 1);
                    }
                }, wait);

                if (immediate && index === -1) {
                    self.run.apply(self, args);
                }

                debouncee = [target, method, timer];

                self._debouncees.push(debouncee);

                return debouncee;
            },

            cancelTimers: function() {
                var clearItems = function(item) {
                    clearTimeout(item[2]);
                };

                each(this._throttlers, clearItems);
                this._throttlers = [];

                each(this._debouncees, clearItems);
                this._debouncees = [];

                if (this._laterTimer) {
                    clearTimeout(this._laterTimer);
                    this._laterTimer = null;
                }
                timers = [];

                if (this._autorun) {
                    clearTimeout(this._autorun);
                    this._autorun = null;
                }
            },

            hasTimers: function() {
                return !!timers.length || !!this._debouncees.length || !!this._throttlers.length || this._autorun;
            },

            cancel: function(timer) {
                var timerType = typeof timer;

                if (timer && timerType === 'object' && timer.queue && timer.method) {
                    // we're cancelling a deferOnce
                    return timer.queue.cancel(timer);
                } else if (timerType === 'function') {
                    // we're cancelling a setTimeout
                    for (var i = 0, l = timers.length; i < l; i += 2) {
                        if (timers[i + 1] === timer) {
                            timers.splice(i, 2); // remove the two elements
                            return true;
                        }
                    }
                } else if (Object.prototype.toString.call(timer) === "[object Array]") {
                    // we're cancelling a throttle or debounce
                    return this._cancelItem(findThrottler, this._throttlers, timer) ||
                    this._cancelItem(findDebouncee, this._debouncees, timer);
                } else {
                    return; // timer was null or not a timer
                }
            },

            _cancelItem: function(findMethod, array, timer) {
                var item,
                index;

                if (timer.length < 3) {
                    return false;
                }

                index = findMethod(timer[0], timer[1], array);

                if (index > -1) {

                    item = array[index];

                    if (item[2] === timer[2]) {
                        array.splice(index, 1);
                        clearTimeout(timer[2]);
                        return true;
                    }
                }

                return false;
            }
        };

        Backburner.prototype.schedule = Backburner.prototype.defer;
        Backburner.prototype.scheduleOnce = Backburner.prototype.deferOnce;
        Backburner.prototype.later = Backburner.prototype.setTimeout;

        if (needsIETryCatchFix) {
            var originalRun = Backburner.prototype.run;
            Backburner.prototype.run = wrapInTryCatch(originalRun);

            var originalEnd = Backburner.prototype.end;
            Backburner.prototype.end = wrapInTryCatch(originalEnd);
        }

        function wrapInTryCatch(func) {
            return function () {
                try {
                    return func.apply(this, arguments);
                } catch (e) {
                    throw e;
                }
            };
        }

        function getOnError(options) {
            return options.onError || (options.onErrorTarget && options.onErrorTarget[options.onErrorMethod]);
        }


        function createAutorun(backburner) {
            backburner.begin();
            backburner._autorun = global.setTimeout(function() {
                backburner._autorun = null;
                backburner.end();
            });
        }

        function updateLaterTimer(self, executeAt, wait) {
            if (!self._laterTimer || executeAt < self._laterTimerExpiresAt) {
                self._laterTimer = global.setTimeout(function() {
                    self._laterTimer = null;
                    self._laterTimerExpiresAt = null;
                    executeTimers(self);
                }, wait);
                self._laterTimerExpiresAt = executeAt;
            }
        }

        function executeTimers(self) {
            var now = + new Date(),
            time, fns, i, l;

            self.run(function() {
                i = searchTimer(now, timers);

                fns = timers.splice(0, i);

                for (i = 1, l = fns.length; i < l; i += 2) {
                    self.schedule(self.options.defaultQueue, null, fns[i]);
                }
            });

            if (timers.length) {
                updateLaterTimer(self, timers[0], timers[0] - now);
            }
        }

        function findDebouncee(target, method, debouncees) {
            return findItem(target, method, debouncees);
        }

        function findThrottler(target, method, throttlers) {
            return findItem(target, method, throttlers);
        }

        function findItem(target, method, collection) {
            var item,
            index = -1;

            for (var i = 0, l = collection.length; i < l; i++) {
                item = collection[i];
                if (item[0] === target && item[1] === method) {
                    index = i;
                    break;
                }
            }

            return index;
        }

        function searchTimer(time, timers) {
            var start = 0,
            end = timers.length - 2,
            middle, l;

            while (start < end) {
                // since timers is an array of pairs 'l' will always
                // be an integer
                l = (end - start) / 2;

                // compensate for the index in case even number
                // of pairs inside timers
                middle = start + l - (l % 2);

                if (time >= timers[middle]) {
                    start = middle + 2;
                } else {
                    end = middle;
                }
            }

            return (time >= timers[start]) ? start + 2 : start;
        }

        __exports__.Backburner = Backburner;
    });
    define("backburner/deferred_action_queues",
    ["backburner/utils", "backburner/queue", "exports"],
    function(__dependency1__, __dependency2__, __exports__) {
        "use strict";
        var Utils = __dependency1__["default"];
        var Queue = __dependency2__.Queue;

        var each = Utils.each,
        isString = Utils.isString;

        function DeferredActionQueues(queueNames, options) {
            var queues = this.queues = {};
            this.queueNames = queueNames = queueNames || [];

            this.options = options;

            each(queueNames, function(queueName) {
                queues[queueName] = new Queue(this, queueName, options);
            });
        }

        DeferredActionQueues.prototype = {
            queueNames: null,
            queues: null,
            options: null,

            schedule: function(queueName, target, method, args, onceFlag, stack) {
                var queues = this.queues,
                queue = queues[queueName];

                if (!queue) {
                    throw new Error("You attempted to schedule an action in a queue (" + queueName + ") that doesn't exist");
                }

                if (onceFlag) {
                    return queue.pushUnique(target, method, args, stack);
                } else {
                    return queue.push(target, method, args, stack);
                }
            },

            invoke: function(target, method, args, _) {
                if (args && args.length > 0) {
                    method.apply(target, args);
                } else {
                    method.call(target);
                }
            },

            invokeWithOnError: function(target, method, args, onError) {
                try {
                    if (args && args.length > 0) {
                        method.apply(target, args);
                    } else {
                        method.call(target);
                    }
                } catch (error) {
                    onError(error);
                }
            },

            flush: function() {
                var queues = this.queues,
                queueNames = this.queueNames,
                queueName, queue, queueItems, priorQueueNameIndex,
                queueNameIndex = 0, numberOfQueues = queueNames.length,
                options = this.options,
                onError = options.onError || (options.onErrorTarget && options.onErrorTarget[options.onErrorMethod]),
                invoke = onError ? this.invokeWithOnError : this.invoke;

                outerloop:
                while (queueNameIndex < numberOfQueues) {
                    queueName = queueNames[queueNameIndex];
                    queue = queues[queueName];
                    queueItems = queue._queueBeingFlushed = queue._queue.slice();
                    queue._queue = [];

                    var queueOptions = queue.options, // TODO: write a test for this
                    before = queueOptions && queueOptions.before,
                    after = queueOptions && queueOptions.after,
                    target, method, args, stack,
                    queueIndex = 0, numberOfQueueItems = queueItems.length;

                    if (numberOfQueueItems && before) {
                        before();
                    }

                    while (queueIndex < numberOfQueueItems) {
                        target = queueItems[queueIndex];
                        method = queueItems[queueIndex + 1];
                        args = queueItems[queueIndex + 2];
                        stack = queueItems[queueIndex + 3]; // Debugging assistance

                        if (isString(method)) {
                            method = target[method];
                        }

                        // method could have been nullified / canceled during flush
                        if (method) {
                            invoke(target, method, args, onError);
                        }

                        queueIndex += 4;
                    }

                    queue._queueBeingFlushed = null;
                    if (numberOfQueueItems && after) {
                        after();
                    }

                    if ((priorQueueNameIndex = indexOfPriorQueueWithActions(this, queueNameIndex)) !== -1) {
                        queueNameIndex = priorQueueNameIndex;
                        continue outerloop;
                    }

                    queueNameIndex++;
                }
            }
        };

        function indexOfPriorQueueWithActions(daq, currentQueueIndex) {
            var queueName, queue;

            for (var i = 0, l = currentQueueIndex; i <= l; i++) {
                queueName = daq.queueNames[i];
                queue = daq.queues[queueName];
                if (queue._queue.length) {
                    return i;
                }
            }

            return -1;
        }

        __exports__.DeferredActionQueues = DeferredActionQueues;
    });
    define("backburner/queue",
    ["exports"],
    function(__exports__) {
        "use strict";
        function Queue(daq, name, options) {
            this.daq = daq;
            this.name = name;
            this.globalOptions = options;
            this.options = options[name];
            this._queue = [];
        }

        Queue.prototype = {
            daq: null,
            name: null,
            options: null,
            onError: null,
            _queue: null,

            push: function(target, method, args, stack) {
                var queue = this._queue;
                queue.push(target, method, args, stack);
                return {
                    queue: this,
                    target: target,
                    method: method
                };
            },

            pushUnique: function(target, method, args, stack) {
                var queue = this._queue, currentTarget, currentMethod, i, l;

                for (i = 0, l = queue.length; i < l; i += 4) {
                    currentTarget = queue[i];
                    currentMethod = queue[i + 1];

                    if (currentTarget === target && currentMethod === method) {
                        queue[i + 2] = args; // replace args
                        queue[i + 3] = stack; // replace stack
                        return {
                            queue: this,
                            target: target,
                            method: method
                        };
                    }
                }

                queue.push(target, method, args, stack);
                return {
                    queue: this,
                    target: target,
                    method: method
                };
            },

            // TODO: remove me, only being used for Ember.run.sync
            flush: function() {
                var queue = this._queue,
                globalOptions = this.globalOptions,
                options = this.options,
                before = options && options.before,
                after = options && options.after,
                onError = globalOptions.onError || (globalOptions.onErrorTarget && globalOptions.onErrorTarget[globalOptions.onErrorMethod]),
                target, method, args, stack, i, l = queue.length;

                if (l && before) {
                    before();
                }
                for (i = 0; i < l; i += 4) {
                    target = queue[i];
                    method = queue[i + 1];
                    args = queue[i + 2];
                    stack = queue[i + 3]; // Debugging assistance

                    // TODO: error handling
                    if (args && args.length > 0) {
                        if (onError) {
                            try {
                                method.apply(target, args);
                            } catch (e) {
                                onError(e);
                            }
                        } else {
                            method.apply(target, args);
                        }
                    } else {
                        if (onError) {
                            try {
                                method.call(target);
                            } catch (e) {
                                onError(e);
                            }
                        } else {
                            method.call(target);
                        }
                    }
                }
                if (l && after) {
                    after();
                }

                // check if new items have been added
                if (queue.length > l) {
                    this._queue = queue.slice(l);
                    this.flush();
                } else {
                    this._queue.length = 0;
                }
            },

            cancel: function(actionToCancel) {
                var queue = this._queue, currentTarget, currentMethod, i, l;

                for (i = 0, l = queue.length; i < l; i += 4) {
                    currentTarget = queue[i];
                    currentMethod = queue[i + 1];

                    if (currentTarget === actionToCancel.target && currentMethod === actionToCancel.method) {
                        queue.splice(i, 4);
                        return true;
                    }
                }

                // if not found in current queue
                // could be in the queue that is being flushed
                queue = this._queueBeingFlushed;
                if (!queue) {
                    return;
                }
                for (i = 0, l = queue.length; i < l; i += 4) {
                    currentTarget = queue[i];
                    currentMethod = queue[i + 1];

                    if (currentTarget === actionToCancel.target && currentMethod === actionToCancel.method) {
                        // don't mess with array during flush
                        // just nullify the method
                        queue[i + 1] = null;
                        return true;
                    }
                }
            }
        };

        __exports__.Queue = Queue;
    });
    define("backburner/utils",
    ["exports"],
    function(__exports__) {
        "use strict";
        __exports__["default"] = {
            each: function(collection, callback) {
                for (var i = 0; i < collection.length; i++) {
                    callback(collection[i]);
                }
            },

            isString: function(suspect) {
                return typeof suspect === 'string';
            },

            isFunction: function(suspect) {
                return typeof suspect === 'function';
            },

            isNumber: function(suspect) {
                return typeof suspect === 'number';
            }
        };
    });

    define("container",
    ["container/container", "exports"],
    function(__dependency1__, __exports__) {
        "use strict";
        /*
            Public api for the container is still in flux.
            The public api, specified on the application namespace should be considered the stable api.
            // @module container
              @private
            */

        /*
             Flag to enable/disable model factory injections (disabled by default)
             If model factory injections are enabled, models should not be
             accessed globally (only through `container.lookupFactory('model:modelName'))`);
            */
        Ember.MODEL_FACTORY_INJECTIONS = false;

        if (Ember.ENV && typeof Ember.ENV.MODEL_FACTORY_INJECTIONS !== 'undefined') {
            Ember.MODEL_FACTORY_INJECTIONS = !!Ember.ENV.MODEL_FACTORY_INJECTIONS;
        }


        var Container = __dependency1__["default"];

        __exports__["default"] = Container;
    });
    define("container/container",
    ["container/inheriting_dict", "ember-metal/core", "exports"],
    function(__dependency1__, __dependency2__, __exports__) {
        "use strict";
        var InheritingDict = __dependency1__["default"];
        var Ember = __dependency2__["default"];
        // Ember.assert

        // A lightweight container that helps to assemble and decouple components.
        // Public api for the container is still in flux.
        // The public api, specified on the application namespace should be considered the stable api.
        function Container(parent) {
            this.parent = parent;
            this.children = [];

            this.resolver = parent && parent.resolver || function() {};

            this.registry = new InheritingDict(parent && parent.registry);
            this.cache = new InheritingDict(parent && parent.cache);
            this.factoryCache = new InheritingDict(parent && parent.factoryCache);
            this.resolveCache = new InheritingDict(parent && parent.resolveCache);
            this.typeInjections = new InheritingDict(parent && parent.typeInjections);
            this.injections = {};

            this.factoryTypeInjections = new InheritingDict(parent && parent.factoryTypeInjections);
            this.factoryInjections = {};

            this._options = new InheritingDict(parent && parent._options);
            this._typeOptions = new InheritingDict(parent && parent._typeOptions);
        }

        Container.prototype = {

            /**
                    @property parent
                    @type Container
                    @default null
                  */
            parent: null,

            /**
                    @property children
                    @type Array
                    @default []
                  */
            children: null,

            /**
                    @property resolver
                    @type function
                  */
            resolver: null,

            /**
                    @property registry
                    @type InheritingDict
                  */
            registry: null,

            /**
                    @property cache
                    @type InheritingDict
                  */
            cache: null,

            /**
                    @property typeInjections
                    @type InheritingDict
                  */
            typeInjections: null,

            /**
                    @property injections
                    @type Object
                    @default {}
                  */
            injections: null,

            /**
                    @private

                    @property _options
                    @type InheritingDict
                    @default null
                  */
            _options: null,

            /**
                    @private

                    @property _typeOptions
                    @type InheritingDict
                  */
            _typeOptions: null,

            /**
                    Returns a new child of the current container. These children are configured
                    to correctly inherit from the current container.

                    @method child
                    @return {Container}
                  */
            child: function() {
                var container = new Container(this);
                this.children.push(container);
                return container;
            },

            /**
                    Sets a key-value pair on the current container. If a parent container,
                    has the same key, once set on a child, the parent and child will diverge
                    as expected.

                    @method set
                    @param {Object} object
                    @param {String} key
                    @param {any} value
                  */
            set: function(object, key, value) {
                object[key] = value;
            },

            /**
                    Registers a factory for later injection.

                    Example:

                    ```javascript
                    var container = new Container();

                    container.register('model:user', Person, {singleton: false });
                    container.register('fruit:favorite', Orange);
                    container.register('communication:main', Email, {singleton: false});
                    ```

                    @method register
                    @param {String} fullName
                    @param {Function} factory
                    @param {Object} options
                  */
            register: function(fullName, factory, options) {
                Ember.assert('fullName must be a proper full name', validateFullName(fullName));

                if (factory === undefined) {
                    throw new TypeError('Attempting to register an unknown factory: `' + fullName + '`');
                }

                var normalizedName = this.normalize(fullName);

                if (this.cache.has(normalizedName)) {
                    throw new Error('Cannot re-register: `' + fullName + '`, as it has already been looked up.');
                }

                this.registry.set(normalizedName, factory);
                this._options.set(normalizedName, options || {});
            },

            /**
                    Unregister a fullName

                    ```javascript
                    var container = new Container();
                    container.register('model:user', User);

                    container.lookup('model:user') instanceof User //=> true

                    container.unregister('model:user')
                    container.lookup('model:user') === undefined //=> true
                    ```

                    @method unregister
                    @param {String} fullName
                   */
            unregister: function(fullName) {
                Ember.assert('fullName must be a proper full name', validateFullName(fullName));

                var normalizedName = this.normalize(fullName);

                this.registry.remove(normalizedName);
                this.cache.remove(normalizedName);
                this.factoryCache.remove(normalizedName);
                this.resolveCache.remove(normalizedName);
                this._options.remove(normalizedName);
            },

            /**
                    Given a fullName return the corresponding factory.

                    By default `resolve` will retrieve the factory from
                    its container's registry.

                    ```javascript
                    var container = new Container();
                    container.register('api:twitter', Twitter);

                    container.resolve('api:twitter') // => Twitter
                    ```

                    Optionally the container can be provided with a custom resolver.
                    If provided, `resolve` will first provide the custom resolver
                    the opportunity to resolve the fullName, otherwise it will fallback
                    to the registry.

                    ```javascript
                    var container = new Container();
                    container.resolver = function(fullName) {
                      // lookup via the module system of choice
                    };

                    // the twitter factory is added to the module system
                    container.resolve('api:twitter') // => Twitter
                    ```

                    @method resolve
                    @param {String} fullName
                    @return {Function} fullName's factory
                  */
            resolve: function(fullName) {
                Ember.assert('fullName must be a proper full name', validateFullName(fullName));
                return resolve(this, this.normalize(fullName));
            },

            /**
                    A hook that can be used to describe how the resolver will
                    attempt to find the factory.

                    For example, the default Ember `.describe` returns the full
                    class name (including namespace) where Ember's resolver expects
                    to find the `fullName`.

                    @method describe
                    @param {String} fullName
                    @return {string} described fullName
                  */
            describe: function(fullName) {
                return fullName;
            },

            /**
                    A hook to enable custom fullName normalization behaviour

                    @method normalize
                    @param {String} fullName
                    @return {string} normalized fullName
                  */
            normalize: function(fullName) {
                return fullName;
            },

            /**
                    @method makeToString

                    @param {any} factory
                    @param {string} fullName
                    @return {function} toString function
                  */
            makeToString: function(factory, fullName) {
                return factory.toString();
            },

            /**
                    Given a fullName return a corresponding instance.

                    The default behaviour is for lookup to return a singleton instance.
                    The singleton is scoped to the container, allowing multiple containers
                    to all have their own locally scoped singletons.

                    ```javascript
                    var container = new Container();
                    container.register('api:twitter', Twitter);

                    var twitter = container.lookup('api:twitter');

                    twitter instanceof Twitter; // => true

                    // by default the container will return singletons
                    var twitter2 = container.lookup('api:twitter');
                    twitter2 instanceof Twitter; // => true

                    twitter === twitter2; //=> true
                    ```

                    If singletons are not wanted an optional flag can be provided at lookup.

                    ```javascript
                    var container = new Container();
                    container.register('api:twitter', Twitter);

                    var twitter = container.lookup('api:twitter', { singleton: false });
                    var twitter2 = container.lookup('api:twitter', { singleton: false });

                    twitter === twitter2; //=> false
                    ```

                    @method lookup
                    @param {String} fullName
                    @param {Object} options
                    @return {any}
                  */
            lookup: function(fullName, options) {
                Ember.assert('fullName must be a proper full name', validateFullName(fullName));
                return lookup(this, this.normalize(fullName), options);
            },

            /**
                    Given a fullName return the corresponding factory.

                    @method lookupFactory
                    @param {String} fullName
                    @return {any}
                  */
            lookupFactory: function(fullName) {
                Ember.assert('fullName must be a proper full name', validateFullName(fullName));
                return factoryFor(this, this.normalize(fullName));
            },

            /**
                    Given a fullName check if the container is aware of its factory
                    or singleton instance.

                    @method has
                    @param {String} fullName
                    @return {Boolean}
                  */
            has: function(fullName) {
                Ember.assert('fullName must be a proper full name', validateFullName(fullName));
                return has(this, this.normalize(fullName));
            },

            /**
                    Allow registering options for all factories of a type.

                    ```javascript
                    var container = new Container();

                    // if all of type `connection` must not be singletons
                    container.optionsForType('connection', { singleton: false });

                    container.register('connection:twitter', TwitterConnection);
                    container.register('connection:facebook', FacebookConnection);

                    var twitter = container.lookup('connection:twitter');
                    var twitter2 = container.lookup('connection:twitter');

                    twitter === twitter2; // => false

                    var facebook = container.lookup('connection:facebook');
                    var facebook2 = container.lookup('connection:facebook');

                    facebook === facebook2; // => false
                    ```

                    @method optionsForType
                    @param {String} type
                    @param {Object} options
                  */
            optionsForType: function(type, options) {
                if (this.parent) {
                    illegalChildOperation('optionsForType');
                }

                this._typeOptions.set(type, options);
            },

            /**
                    @method options
                    @param {String} type
                    @param {Object} options
                  */
            options: function(type, options) {
                this.optionsForType(type, options);
            },

            /**
                    Used only via `injection`.

                    Provides a specialized form of injection, specifically enabling
                    all objects of one type to be injected with a reference to another
                    object.

                    For example, provided each object of type `controller` needed a `router`.
                    one would do the following:

                    ```javascript
                    var container = new Container();

                    container.register('router:main', Router);
                    container.register('controller:user', UserController);
                    container.register('controller:post', PostController);

                    container.typeInjection('controller', 'router', 'router:main');

                    var user = container.lookup('controller:user');
                    var post = container.lookup('controller:post');

                    user.router instanceof Router; //=> true
                    post.router instanceof Router; //=> true

                    // both controllers share the same router
                    user.router === post.router; //=> true
                    ```

                    @private
                    @method typeInjection
                    @param {String} type
                    @param {String} property
                    @param {String} fullName
                  */
            typeInjection: function(type, property, fullName) {
                Ember.assert('fullName must be a proper full name', validateFullName(fullName));
                if (this.parent) {
                    illegalChildOperation('typeInjection');
                }

                var fullNameType = fullName.split(':')[0];
                if (fullNameType === type) {
                    throw new Error('Cannot inject a `' + fullName + '` on other ' + type + '(s). Register the `' + fullName + '` as a different type and perform the typeInjection.');
                }
                addTypeInjection(this.typeInjections, type, property, fullName);
            },

            /**
                    Defines injection rules.

                    These rules are used to inject dependencies onto objects when they
                    are instantiated.

                    Two forms of injections are possible:

                    * Injecting one fullName on another fullName
                    * Injecting one fullName on a type

                    Example:

                    ```javascript
                    var container = new Container();

                    container.register('source:main', Source);
                    container.register('model:user', User);
                    container.register('model:post', Post);

                    // injecting one fullName on another fullName
                    // eg. each user model gets a post model
                    container.injection('model:user', 'post', 'model:post');

                    // injecting one fullName on another type
                    container.injection('model', 'source', 'source:main');

                    var user = container.lookup('model:user');
                    var post = container.lookup('model:post');

                    user.source instanceof Source; //=> true
                    post.source instanceof Source; //=> true

                    user.post instanceof Post; //=> true

                    // and both models share the same source
                    user.source === post.source; //=> true
                    ```

                    @method injection
                    @param {String} factoryName
                    @param {String} property
                    @param {String} injectionName
                  */
            injection: function(fullName, property, injectionName) {
                if (this.parent) {
                    illegalChildOperation('injection');
                }

                validateFullName(injectionName);
                var normalizedInjectionName = this.normalize(injectionName);

                if (fullName.indexOf(':') === -1) {
                    return this.typeInjection(fullName, property, normalizedInjectionName);
                }

                Ember.assert('fullName must be a proper full name', validateFullName(fullName));
                var normalizedName = this.normalize(fullName);

                if (this.cache.has(normalizedName)) {
                    throw new Error("Attempted to register an injection for a type that has already been looked up. ('" + normalizedName + "', '" + property + "', '" + injectionName + "')");
                }
                addInjection(this.injections, normalizedName, property, normalizedInjectionName);
            },


            /**
                    Used only via `factoryInjection`.

                    Provides a specialized form of injection, specifically enabling
                    all factory of one type to be injected with a reference to another
                    object.

                    For example, provided each factory of type `model` needed a `store`.
                    one would do the following:

                    ```javascript
                    var container = new Container();

                    container.register('store:main', SomeStore);

                    container.factoryTypeInjection('model', 'store', 'store:main');

                    var store = container.lookup('store:main');
                    var UserFactory = container.lookupFactory('model:user');

                    UserFactory.store instanceof SomeStore; //=> true
                    ```

                    @private
                    @method factoryTypeInjection
                    @param {String} type
                    @param {String} property
                    @param {String} fullName
                  */
            factoryTypeInjection: function(type, property, fullName) {
                if (this.parent) {
                    illegalChildOperation('factoryTypeInjection');
                }

                addTypeInjection(this.factoryTypeInjections, type, property, this.normalize(fullName));
            },

            /**
                    Defines factory injection rules.

                    Similar to regular injection rules, but are run against factories, via
                    `Container#lookupFactory`.

                    These rules are used to inject objects onto factories when they
                    are looked up.

                    Two forms of injections are possible:

                  * Injecting one fullName on another fullName
                  * Injecting one fullName on a type

                    Example:

                    ```javascript
                    var container = new Container();

                    container.register('store:main', Store);
                    container.register('store:secondary', OtherStore);
                    container.register('model:user', User);
                    container.register('model:post', Post);

                    // injecting one fullName on another type
                    container.factoryInjection('model', 'store', 'store:main');

                    // injecting one fullName on another fullName
                    container.factoryInjection('model:post', 'secondaryStore', 'store:secondary');

                    var UserFactory = container.lookupFactory('model:user');
                    var PostFactory = container.lookupFactory('model:post');
                    var store = container.lookup('store:main');

                    UserFactory.store instanceof Store; //=> true
                    UserFactory.secondaryStore instanceof OtherStore; //=> false

                    PostFactory.store instanceof Store; //=> true
                    PostFactory.secondaryStore instanceof OtherStore; //=> true

                    // and both models share the same source instance
                    UserFactory.store === PostFactory.store; //=> true
                    ```

                    @method factoryInjection
                    @param {String} factoryName
                    @param {String} property
                    @param {String} injectionName
                  */
            factoryInjection: function(fullName, property, injectionName) {
                if (this.parent) {
                    illegalChildOperation('injection');
                }

                var normalizedName = this.normalize(fullName);
                var normalizedInjectionName = this.normalize(injectionName);

                validateFullName(injectionName);

                if (fullName.indexOf(':') === -1) {
                    return this.factoryTypeInjection(normalizedName, property, normalizedInjectionName);
                }

                Ember.assert('fullName must be a proper full name', validateFullName(fullName));

                if (this.factoryCache.has(normalizedName)) {
                    throw new Error('Attempted to register a factoryInjection for a type that has already ' +
                    'been looked up. (\'' + normalizedName + '\', \'' + property + '\', \'' + injectionName + '\')');
                }

                addInjection(this.factoryInjections, normalizedName, property, normalizedInjectionName);
            },

            /**
                    A depth first traversal, destroying the container, its descendant containers and all
                    their managed objects.

                    @method destroy
                  */
            destroy: function() {
                for (var i = 0, length = this.children.length; i < length; i++) {
                    this.children[i].destroy();
                }

                this.children = [];

                eachDestroyable(this, function(item) {
                    item.destroy();
                });

                this.parent = undefined;
                this.isDestroyed = true;
            },

            /**
                    @method reset
                  */
            reset: function() {
                for (var i = 0, length = this.children.length; i < length; i++) {
                    resetCache(this.children[i]);
                }

                resetCache(this);
            }
        };

        function resolve(container, normalizedName) {
            var cached = container.resolveCache.get(normalizedName);
            if (cached) {
                return cached;
            }

            var resolved = container.resolver(normalizedName) || container.registry.get(normalizedName);
            container.resolveCache.set(normalizedName, resolved);

            return resolved;
        }

        function has(container, fullName) {
            if (container.cache.has(fullName)) {
                return true;
            }

            return !!container.resolve(fullName);
        }

        function lookup(container, fullName, options) {
            options = options || {};

            if (container.cache.has(fullName) && options.singleton !== false) {
                return container.cache.get(fullName);
            }

            var value = instantiate(container, fullName);

            if (value === undefined) {
                return;
            }

            if (isSingleton(container, fullName) && options.singleton !== false) {
                container.cache.set(fullName, value);
            }

            return value;
        }

        function illegalChildOperation(operation) {
            throw new Error(operation + ' is not currently supported on child containers');
        }

        function isSingleton(container, fullName) {
            var singleton = option(container, fullName, 'singleton');

            return singleton !== false;
        }

        function buildInjections(container, injections) {
            var hash = {};

            if (!injections) {
                return hash;
            }

            var injection, injectable;

            for (var i = 0, length = injections.length; i < length; i++) {
                injection = injections[i];
                injectable = lookup(container, injection.fullName);

                if (injectable !== undefined) {
                    hash[injection.property] = injectable;
                } else {
                    throw new Error('Attempting to inject an unknown injection: `' + injection.fullName + '`');
                }
            }

            return hash;
        }

        function option(container, fullName, optionName) {
            var options = container._options.get(fullName);

            if (options && options[optionName] !== undefined) {
                return options[optionName];
            }

            var type = fullName.split(':')[0];
            options = container._typeOptions.get(type);

            if (options) {
                return options[optionName];
            }
        }

        function factoryFor(container, fullName) {
            var cache = container.factoryCache;
            if (cache.has(fullName)) {
                return cache.get(fullName);
            }
            var factory = container.resolve(fullName);
            if (factory === undefined) {
                return;
            }

            var type = fullName.split(':')[0];
            if (!factory || typeof factory.extend !== 'function' || (!Ember.MODEL_FACTORY_INJECTIONS && type === 'model')) {
                // TODO: think about a 'safe' merge style extension
                // for now just fallback to create time injection
                return factory;
            } else {
                var injections = injectionsFor(container, fullName);
                var factoryInjections = factoryInjectionsFor(container, fullName);

                factoryInjections._toString = container.makeToString(factory, fullName);

                var injectedFactory = factory.extend(injections);
                injectedFactory.reopenClass(factoryInjections);

                cache.set(fullName, injectedFactory);

                return injectedFactory;
            }
        }

        function injectionsFor(container, fullName) {
            var splitName = fullName.split(':'),
            type = splitName[0],
            injections = [];

            injections = injections.concat(container.typeInjections.get(type) || []);
            injections = injections.concat(container.injections[fullName] || []);

            injections = buildInjections(container, injections);
            injections._debugContainerKey = fullName;
            injections.container = container;

            return injections;
        }

        function factoryInjectionsFor(container, fullName) {
            var splitName = fullName.split(':'),
            type = splitName[0],
            factoryInjections = [];

            factoryInjections = factoryInjections.concat(container.factoryTypeInjections.get(type) || []);
            factoryInjections = factoryInjections.concat(container.factoryInjections[fullName] || []);

            factoryInjections = buildInjections(container, factoryInjections);
            factoryInjections._debugContainerKey = fullName;

            return factoryInjections;
        }

        function instantiate(container, fullName) {
            var factory = factoryFor(container, fullName);

            if (option(container, fullName, 'instantiate') === false) {
                return factory;
            }

            if (factory) {
                if (typeof factory.create !== 'function') {
                    throw new Error('Failed to create an instance of \'' + fullName + '\'. ' +
                    'Most likely an improperly defined class or an invalid module export.');
                }

                if (typeof factory.extend === 'function') {
                    // assume the factory was extendable and is already injected
                    return factory.create();
                } else {
                    // assume the factory was extendable
                    // to create time injections
                    // TODO: support new'ing for instantiation and merge injections for pure JS Functions
                    return factory.create(injectionsFor(container, fullName));
                }
            }
        }

        function eachDestroyable(container, callback) {
            container.cache.eachLocal(function(key, value) {
                if (option(container, key, 'instantiate') === false) {
                    return;
                }
                callback(value);
            });
        }

        function resetCache(container) {
            container.cache.eachLocal(function(key, value) {
                if (option(container, key, 'instantiate') === false) {
                    return;
                }
                value.destroy();
            });
            container.cache.dict = {};
        }

        function addTypeInjection(rules, type, property, fullName) {
            var injections = rules.get(type);

            if (!injections) {
                injections = [];
                rules.set(type, injections);
            }

            injections.push({
                property: property,
                fullName: fullName
            });
        }

        var VALID_FULL_NAME_REGEXP = /^[^:]+.+:[^:]+$/;
        function validateFullName(fullName) {
            if (!VALID_FULL_NAME_REGEXP.test(fullName)) {
                throw new TypeError('Invalid Fullname, expected: `type:name` got: ' + fullName);
            }
            return true;
        }

        function addInjection(rules, factoryName, property, injectionName) {
            var injections = rules[factoryName] = rules[factoryName] || [];
            injections.push({
                property: property,
                fullName: injectionName 
            });
        }

        __exports__["default"] = Container;
    });
    define("container/inheriting_dict",
    ["exports"],
    function(__exports__) {
        "use strict";
        // A safe and simple inheriting object.
        function InheritingDict(parent) {
            this.parent = parent;
            this.dict = {};
        }

        InheritingDict.prototype = {

            /**
                    @property parent
                    @type InheritingDict
                    @default null
                  */

            parent: null,

            /**
                    Object used to store the current nodes data.

                    @property dict
                    @type Object
                    @default Object
                  */
            dict: null,

            /**
                    Retrieve the value given a key, if the value is present at the current
                    level use it, otherwise walk up the parent hierarchy and try again. If
                    no matching key is found, return undefined.

                    @method get
                    @param {String} key
                    @return {any}
                  */
            get: function(key) {
                var dict = this.dict;

                if (dict.hasOwnProperty(key)) {
                    return dict[key];
                }

                if (this.parent) {
                    return this.parent.get(key);
                }
            },

            /**
                    Set the given value for the given key, at the current level.

                    @method set
                    @param {String} key
                    @param {Any} value
                  */
            set: function(key, value) {
                this.dict[key] = value;
            },

            /**
                    Delete the given key

                    @method remove
                    @param {String} key
                  */
            remove: function(key) {
                delete this.dict[key];
            },

            /**
                    Check for the existence of given a key, if the key is present at the current
                    level return true, otherwise walk up the parent hierarchy and try again. If
                    no matching key is found, return false.

                    @method has
                    @param {String} key
                    @return {Boolean}
                  */
            has: function(key) {
                var dict = this.dict;

                if (dict.hasOwnProperty(key)) {
                    return true;
                }

                if (this.parent) {
                    return this.parent.has(key);
                }

                return false;
            },

            /**
                    Iterate and invoke a callback for each local key-value pair.

                    @method eachLocal
                    @param {Function} callback
                    @param {Object} binding
                  */
            eachLocal: function(callback, binding) {
                var dict = this.dict;

                for (var prop in dict) {
                    if (dict.hasOwnProperty(prop)) {
                        callback.call(binding, prop, dict[prop]);
                    }
                }
            }
        };

        __exports__["default"] = InheritingDict;
    });
    define("ember-application",
    ["ember-metal/core", "ember-runtime/system/lazy_load", "ember-application/system/dag", "ember-application/system/resolver", "ember-application/system/application", "ember-application/ext/controller"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__) {
        "use strict";
        var Ember = __dependency1__["default"];
        var runLoadHooks = __dependency2__.runLoadHooks;

        /**
            Ember Application

            @module ember
            @submodule ember-application
            @requires ember-views, ember-routing
            */

        var DAG = __dependency3__["default"];
        var Resolver = __dependency4__.Resolver;
        var DefaultResolver = __dependency4__["default"];
        var Application = __dependency5__["default"];
        // side effect of extending ControllerMixin

        Ember.Application = Application;
        Ember.DAG = DAG;
        Ember.Resolver = Resolver;
        Ember.DefaultResolver = DefaultResolver;

        runLoadHooks('Ember.Application', Application);
    });
    define("ember-application/ext/controller",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/error", "ember-metal/utils", "ember-metal/computed", "ember-runtime/mixins/controller", "ember-routing/system/controller_for", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-application
            */

        var Ember = __dependency1__["default"];
        // Ember.assert
        var get = __dependency2__.get;
        var set = __dependency3__.set;
        var EmberError = __dependency4__["default"];
        var inspect = __dependency5__.inspect;
        var computed = __dependency6__.computed;
        var ControllerMixin = __dependency7__["default"];
        var meta = __dependency5__.meta;
        var controllerFor = __dependency8__["default"];

        function verifyNeedsDependencies(controller, container, needs) {
            var dependency, i, l, missing = [];

            for (i = 0, l = needs.length; i < l; i++) {
                dependency = needs[i];

                Ember.assert(inspect(controller) + "#needs must not specify dependencies with periods in their names (" + dependency + ")", dependency.indexOf('.') === -1);

                if (dependency.indexOf(':') === -1) {
                    dependency = "controller:" + dependency;
                }

                // Structure assert to still do verification but not string concat in production
                if (!container.has(dependency)) {
                    missing.push(dependency);
                }
            }
            if (missing.length) {
                throw new EmberError(inspect(controller) + " needs [ " + missing.join(', ') + " ] but " + (missing.length > 1 ? 'they' : 'it') + " could not be found");
            }
        }

        var defaultControllersComputedProperty = computed(function() {
            var controller = this;

            return {
                needs: get(controller, 'needs'),
                container: get(controller, 'container'),
                unknownProperty: function(controllerName) {
                    var needs = this.needs,
                    dependency, i, l;
                    for (i = 0, l = needs.length; i < l; i++) {
                        dependency = needs[i];
                        if (dependency === controllerName) {
                            return this.container.lookup('controller:' + controllerName);
                        }
                    }

                    var errorMessage = inspect(controller) + '#needs does not include `' + controllerName + '`. To access the ' + controllerName + ' controller from ' + inspect(controller) + ', ' + inspect(controller) + ' should have a `needs` property that is an array of the controllers it has access to.';
                    throw new ReferenceError(errorMessage);
                },
                setUnknownProperty: function (key, value) {
                    throw new Error("You cannot overwrite the value of `controllers." + key + "` of " + inspect(controller));
                }
            };
        });

        /**
              @class ControllerMixin
              @namespace Ember
            */
        ControllerMixin.reopen({
            concatenatedProperties: ['needs'],

            /**
                    An array of other controller objects available inside
                    instances of this controller via the `controllers`
                    property:

                    For example, when you define a controller:

                    ```javascript
                    App.CommentsController = Ember.ArrayController.extend({
                      needs: ['post']
                    });
                    ```

                    The application's single instance of these other
                    controllers are accessible by name through the
                    `controllers` property:

                    ```javascript
                    this.get('controllers.post'); // instance of App.PostController
                    ```

                    Given that you have a nested controller (nested resource):

                    ```javascript
                    App.CommentsNewController = Ember.ObjectController.extend({
                    });
                    ```

                    When you define a controller that requires access to a nested one:

                    ```javascript
                    App.IndexController = Ember.ObjectController.extend({
                      needs: ['commentsNew']
                    });
                    ```

                    You will be able to get access to it:

                    ```javascript
                    this.get('controllers.commentsNew'); // instance of App.CommentsNewController
                    ```

                    This is only available for singleton controllers.

                    @property {Array} needs
                    @default []
                  */
            needs: [],

            init: function() {
                var needs = get(this, 'needs');
                var length = get(needs, 'length');

                if (length > 0) {
                    Ember.assert(' `' + inspect(this) + ' specifies `needs`, but does ' +
                    "not have a container. Please ensure this controller was " +
                    "instantiated with a container.",
                    this.container || meta(this, false).descs.controllers !== defaultControllersComputedProperty);

                    if (this.container) {
                        verifyNeedsDependencies(this, this.container, needs);
                    }

                    // if needs then initialize controllers proxy
                    get(this, 'controllers');
                }

                this._super.apply(this, arguments);
            },

            /**
                    @method controllerFor
                    @see {Ember.Route#controllerFor}
                    @deprecated Use `needs` instead
                  */
            controllerFor: function(controllerName) {
                Ember.deprecate("Controller#controllerFor is deprecated, please use Controller#needs instead");
                return controllerFor(get(this, 'container'), controllerName);
            },

            /**
                    Stores the instances of other controllers available from within
                    this controller. Any controller listed by name in the `needs`
                    property will be accessible by name through this property.

                    ```javascript
                    App.CommentsController = Ember.ArrayController.extend({
                      needs: ['post'],
                      postTitle: function(){
                        var currentPost = this.get('controllers.post'); // instance of App.PostController
                        return currentPost.get('title');
                      }.property('controllers.post.title')
                    });
                    ```

                    @see {Ember.ControllerMixin#needs}
                    @property {Object} controllers
                    @default null
                  */
            controllers: defaultControllersComputedProperty
        });

        __exports__["default"] = ControllerMixin;
    });
    define("ember-application/system/application",
    ["ember-metal", "ember-metal/property_get", "ember-metal/property_set", "ember-runtime/system/lazy_load", "ember-application/system/dag", "ember-runtime/system/namespace", "ember-runtime/mixins/deferred", "ember-application/system/resolver", "ember-metal/platform", "ember-metal/run_loop", "ember-metal/utils", "container/container", "ember-runtime/controllers/controller", "ember-metal/enumerable_utils", "ember-runtime/controllers/object_controller", "ember-runtime/controllers/array_controller", "ember-views/system/event_dispatcher", "ember-views/system/jquery", "ember-routing/system/route", "ember-routing/system/router", "ember-routing/location/hash_location", "ember-routing/location/history_location", "ember-routing/location/auto_location", "ember-routing/location/none_location", "ember-routing/system/cache", "ember-metal/core", "ember-handlebars-compiler", "ember-application/system/deprecated-container", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __dependency19__, __dependency20__, __dependency21__, __dependency22__, __dependency23__, __dependency24__, __dependency25__, __dependency26__, __dependency27__, __dependency28__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-application
            */

        var Ember = __dependency1__["default"];
        // Ember.FEATURES, Ember.deprecate, Ember.assert, Ember.libraries, LOG_VERSION, Namespace, BOOTED
        var get = __dependency2__.get;
        var set = __dependency3__.set;
        var runLoadHooks = __dependency4__.runLoadHooks;
        var DAG = __dependency5__["default"];
        var Namespace = __dependency6__["default"];
        var DeferredMixin = __dependency7__["default"];
        var DefaultResolver = __dependency8__["default"];
        var create = __dependency9__.create;
        var run = __dependency10__["default"];
        var canInvoke = __dependency11__.canInvoke;
        var Container = __dependency12__["default"];
        var Controller = __dependency13__["default"];
        var EnumerableUtils = __dependency14__["default"];
        var ObjectController = __dependency15__["default"];
        var ArrayController = __dependency16__["default"];
        var EventDispatcher = __dependency17__["default"];
        //import ContainerDebugAdapter from "ember-extension-support/container_debug_adapter";
        var jQuery = __dependency18__["default"];
        var Route = __dependency19__["default"];
        var Router = __dependency20__["default"];
        var HashLocation = __dependency21__["default"];
        var HistoryLocation = __dependency22__["default"];
        var AutoLocation = __dependency23__["default"];
        var NoneLocation = __dependency24__["default"];
        var BucketCache = __dependency25__["default"];

        var K = __dependency26__.K;
        var EmberHandlebars = __dependency27__["default"];
        var DeprecatedContainer = __dependency28__["default"];

        var ContainerDebugAdapter;

        /**
              An instance of `Ember.Application` is the starting point for every Ember
              application. It helps to instantiate, initialize and coordinate the many
              objects that make up your app.

              Each Ember app has one and only one `Ember.Application` object. In fact, the
              very first thing you should do in your application is create the instance:

              ```javascript
              window.App = Ember.Application.create();
              ```

              Typically, the application object is the only global variable. All other
              classes in your app should be properties on the `Ember.Application` instance,
              which highlights its first role: a global namespace.

              For example, if you define a view class, it might look like this:

              ```javascript
              App.MyView = Ember.View.extend();
              ```

              By default, calling `Ember.Application.create()` will automatically initialize
              your application by calling the `Ember.Application.initialize()` method. If
              you need to delay initialization, you can call your app's `deferReadiness()`
              method. When you are ready for your app to be initialized, call its
              `advanceReadiness()` method.

              You can define a `ready` method on the `Ember.Application` instance, which
              will be run by Ember when the application is initialized.

              Because `Ember.Application` inherits from `Ember.Namespace`, any classes
              you create will have useful string representations when calling `toString()`.
              See the `Ember.Namespace` documentation for more information.

              While you can think of your `Ember.Application` as a container that holds the
              other classes in your application, there are several other responsibilities
              going on under-the-hood that you may want to understand.

              ### Event Delegation

              Ember uses a technique called _event delegation_. This allows the framework
              to set up a global, shared event listener instead of requiring each view to
              do it manually. For example, instead of each view registering its own
              `mousedown` listener on its associated element, Ember sets up a `mousedown`
              listener on the `body`.

              If a `mousedown` event occurs, Ember will look at the target of the event and
              start walking up the DOM node tree, finding corresponding views and invoking
              their `mouseDown` method as it goes.

              `Ember.Application` has a number of default events that it listens for, as
              well as a mapping from lowercase events to camel-cased view method names. For
              example, the `keypress` event causes the `keyPress` method on the view to be
              called, the `dblclick` event causes `doubleClick` to be called, and so on.

              If there is a bubbling browser event that Ember does not listen for by
              default, you can specify custom events and their corresponding view method
              names by setting the application's `customEvents` property:

              ```javascript
              App = Ember.Application.create({
                customEvents: {
                  // add support for the paste event
                  paste: "paste"
                }
              });
              ```

              By default, the application sets up these event listeners on the document
              body. However, in cases where you are embedding an Ember application inside
              an existing page, you may want it to set up the listeners on an element
              inside the body.

              For example, if only events inside a DOM element with the ID of `ember-app`
              should be delegated, set your application's `rootElement` property:

              ```javascript
              window.App = Ember.Application.create({
                rootElement: '#ember-app'
              });
              ```

              The `rootElement` can be either a DOM element or a jQuery-compatible selector
              string. Note that *views appended to the DOM outside the root element will
              not receive events.* If you specify a custom root element, make sure you only
              append views inside it!

              To learn more about the advantages of event delegation and the Ember view
              layer, and a list of the event listeners that are setup by default, visit the
              [Ember View Layer guide](http://emberjs.com/guides/understanding-ember/the-view-layer/#toc_event-delegation).

              ### Initializers

              Libraries on top of Ember can add initializers, like so:

              ```javascript
              Ember.Application.initializer({
                name: 'api-adapter',

                initialize: function(container, application) {
                  application.register('api-adapter:main', ApiAdapter);
                }
              });
              ```

              Initializers provide an opportunity to access the container, which
              organizes the different components of an Ember application. Additionally
              they provide a chance to access the instantiated application. Beyond
              being used for libraries, initializers are also a great way to organize
              dependency injection or setup in your own application.

              ### Routing

              In addition to creating your application's router, `Ember.Application` is
              also responsible for telling the router when to start routing. Transitions
              between routes can be logged with the `LOG_TRANSITIONS` flag, and more
              detailed intra-transition logging can be logged with
              the `LOG_TRANSITIONS_INTERNAL` flag:

              ```javascript
              window.App = Ember.Application.create({
                LOG_TRANSITIONS: true, // basic logging of successful transitions
                LOG_TRANSITIONS_INTERNAL: true // detailed logging of all routing steps
              });
              ```

              By default, the router will begin trying to translate the current URL into
              application state once the browser emits the `DOMContentReady` event. If you
              need to defer routing, you can call the application's `deferReadiness()`
              method. Once routing can begin, call the `advanceReadiness()` method.

              If there is any setup required before routing begins, you can implement a
              `ready()` method on your app that will be invoked immediately before routing
              begins.
              ```

              @class Application
              @namespace Ember
              @extends Ember.Namespace
            */

        var Application = Namespace.extend(DeferredMixin, {
            _suppressDeferredDeprecation: true,

            /**
                    The root DOM element of the Application. This can be specified as an
                    element or a
                    [jQuery-compatible selector string](http://api.jquery.com/category/selectors/).

                    This is the element that will be passed to the Application's,
                    `eventDispatcher`, which sets up the listeners for event delegation. Every
                    view in your application should be a child of the element you specify here.

                    @property rootElement
                    @type DOMElement
                    @default 'body'
                  */
            rootElement: 'body',

            /**
                    The `Ember.EventDispatcher` responsible for delegating events to this
                    application's views.

                    The event dispatcher is created by the application at initialization time
                    and sets up event listeners on the DOM element described by the
                    application's `rootElement` property.

                    See the documentation for `Ember.EventDispatcher` for more information.

                    @property eventDispatcher
                    @type Ember.EventDispatcher
                    @default null
                  */
            eventDispatcher: null,

            /**
                    The DOM events for which the event dispatcher should listen.

                    By default, the application's `Ember.EventDispatcher` listens
                    for a set of standard DOM events, such as `mousedown` and
                    `keyup`, and delegates them to your application's `Ember.View`
                    instances.

                    If you would like additional bubbling events to be delegated to your
                    views, set your `Ember.Application`'s `customEvents` property
                    to a hash containing the DOM event name as the key and the
                    corresponding view method name as the value. For example:

                    ```javascript
                    App = Ember.Application.create({
                      customEvents: {
                        // add support for the paste event
                        paste: "paste"
                      }
                    });
                    ```

                    @property customEvents
                    @type Object
                    @default null
                  */
            customEvents: null,

            // Start off the number of deferrals at 1. This will be
            // decremented by the Application's own `initialize` method.
            _readinessDeferrals: 1,

            init: function() {
                if (!this.$) {
                    this.$ = jQuery;
                }
                this.__container__ = this.buildContainer();

                this.Router = this.defaultRouter();

                this._super();

                this.scheduleInitialize();

                Ember.libraries.registerCoreLibrary('Handlebars', EmberHandlebars.VERSION);
                Ember.libraries.registerCoreLibrary('jQuery', jQuery().jquery);

                if ( Ember.LOG_VERSION ) {
                    Ember.LOG_VERSION = false; // we only need to see this once per Application#init

                    var nameLengths = EnumerableUtils.map(Ember.libraries, function(item) {
                        return get(item, "name.length");
                    });

                    var maxNameLength = Math.max.apply(this, nameLengths);

                    Ember.debug('-------------------------------');
                    Ember.libraries.each(function(name, version) {
                        var spaces = new Array(maxNameLength - name.length + 1).join(" ");
                        Ember.debug([name, spaces, ' : ', version].join(""));
                    });
                    Ember.debug('-------------------------------');
                }
            },

            /**
                    Build the container for the current application.

                    Also register a default application view in case the application
                    itself does not.

                    @private
                    @method buildContainer
                    @return {Ember.Container} the configured container
                  */
            buildContainer: function() {
                var container = this.__container__ = Application.buildContainer(this);

                return container;
            },

            /**
                    If the application has not opted out of routing and has not explicitly
                    defined a router, supply a default router for the application author
                    to configure.

                    This allows application developers to do:

                    ```javascript
                    var App = Ember.Application.create();

                    App.Router.map(function() {
                      this.resource('posts');
                    });
                    ```

                    @private
                    @method defaultRouter
                    @return {Ember.Router} the default router
                  */

            defaultRouter: function() {
                if (this.Router === false) {
                    return;
                }
                var container = this.__container__;

                if (this.Router) {
                    container.unregister('router:main');
                    container.register('router:main', this.Router);
                }

                return container.lookupFactory('router:main');
            },

            /**
                    Automatically initialize the application once the DOM has
                    become ready.

                    The initialization itself is scheduled on the actions queue
                    which ensures that application loading finishes before
                    booting.

                    If you are asynchronously loading code, you should call
                    `deferReadiness()` to defer booting, and then call
                    `advanceReadiness()` once all of your code has finished
                    loading.

                    @private
                    @method scheduleInitialize
                  */
            scheduleInitialize: function() {
                var self = this;

                if (!this.$ || this.$.isReady) {
                    run.schedule('actions', self, '_initialize');
                } else {
                    this.$().ready(function runInitialize() {
                        run(self, '_initialize');
                    });
                }
            },

            /**
                    Use this to defer readiness until some condition is true.

                    Example:

                    ```javascript
                    App = Ember.Application.create();
                    App.deferReadiness();

                    jQuery.getJSON("/auth-token", function(token) {
                      App.token = token;
                      App.advanceReadiness();
                    });
                    ```

                    This allows you to perform asynchronous setup logic and defer
                    booting your application until the setup has finished.

                    However, if the setup requires a loading UI, it might be better
                    to use the router for this purpose.

                    @method deferReadiness
                  */
            deferReadiness: function() {
                Ember.assert("You must call deferReadiness on an instance of Ember.Application", this instanceof Application);
                Ember.assert("You cannot defer readiness since the `ready()` hook has already been called.", this._readinessDeferrals > 0);
                this._readinessDeferrals++;
            },

            /**
                    Call `advanceReadiness` after any asynchronous setup logic has completed.
                    Each call to `deferReadiness` must be matched by a call to `advanceReadiness`
                    or the application will never become ready and routing will not begin.

                    @method advanceReadiness
                    @see {Ember.Application#deferReadiness}
                  */
            advanceReadiness: function() {
                Ember.assert("You must call advanceReadiness on an instance of Ember.Application", this instanceof Application);
                this._readinessDeferrals--;

                if (this._readinessDeferrals === 0) {
                    run.once(this, this.didBecomeReady);
                }
            },

            /**
                    Registers a factory that can be used for dependency injection (with
                    `App.inject`) or for service lookup. Each factory is registered with
                    a full name including two parts: `type:name`.

                    A simple example:

                    ```javascript
                    var App = Ember.Application.create();
                    App.Orange  = Ember.Object.extend();
                    App.register('fruit:favorite', App.Orange);
                    ```

                    Ember will resolve factories from the `App` namespace automatically.
                    For example `App.CarsController` will be discovered and returned if
                    an application requests `controller:cars`.

                    An example of registering a controller with a non-standard name:

                    ```javascript
                    var App = Ember.Application.create(),
                        Session  = Ember.Controller.extend();

                    App.register('controller:session', Session);

                    // The Session controller can now be treated like a normal controller,
                    // despite its non-standard name.
                    App.ApplicationController = Ember.Controller.extend({
                      needs: ['session']
                    });
                    ```

                    Registered factories are **instantiated** by having `create`
                    called on them. Additionally they are **singletons**, each time
                    they are looked up they return the same instance.

                    Some examples modifying that default behavior:

                    ```javascript
                    var App = Ember.Application.create();

                    App.Person  = Ember.Object.extend();
                    App.Orange  = Ember.Object.extend();
                    App.Email   = Ember.Object.extend();
                    App.session = Ember.Object.create();

                    App.register('model:user', App.Person, {singleton: false });
                    App.register('fruit:favorite', App.Orange);
                    App.register('communication:main', App.Email, {singleton: false});
                    App.register('session', App.session, {instantiate: false});
                    ```

                    @method register
                    @param  fullName {String} type:name (e.g., 'model:user')
                    @param  factory {Function} (e.g., App.Person)
                    @param  options {Object} (optional) disable instantiation or singleton usage
                  **/
            register: function() {
                var container = this.__container__;
                container.register.apply(container, arguments);
            },

            /**
                    Define a dependency injection onto a specific factory or all factories
                    of a type.

                    When Ember instantiates a controller, view, or other framework component
                    it can attach a dependency to that component. This is often used to
                    provide services to a set of framework components.

                    An example of providing a session object to all controllers:

                    ```javascript
                    var App = Ember.Application.create(),
                        Session = Ember.Object.extend({ isAuthenticated: false });

                    // A factory must be registered before it can be injected
                    App.register('session:main', Session);

                    // Inject 'session:main' onto all factories of the type 'controller'
                    // with the name 'session'
                    App.inject('controller', 'session', 'session:main');

                    App.IndexController = Ember.Controller.extend({
                      isLoggedIn: Ember.computed.alias('session.isAuthenticated')
                    });
                    ```

                    Injections can also be performed on specific factories.

                    ```javascript
                    App.inject(<full_name or type>, <property name>, <full_name>)
                    App.inject('route', 'source', 'source:main')
                    App.inject('route:application', 'email', 'model:email')
                    ```

                    It is important to note that injections can only be performed on
                    classes that are instantiated by Ember itself. Instantiating a class
                    directly (via `create` or `new`) bypasses the dependency injection
                    system.

                    Ember-Data instantiates its models in a unique manner, and consequently
                    injections onto models (or all models) will not work as expected. Injections
                    on models can be enabled by setting `Ember.MODEL_FACTORY_INJECTIONS`
                    to `true`.

                    @method inject
                    @param  factoryNameOrType {String}
                    @param  property {String}
                    @param  injectionName {String}
                  **/
            inject: function() {
                var container = this.__container__;
                container.injection.apply(container, arguments);
            },

            /**
                    Calling initialize manually is not supported.

                    Please see Ember.Application#advanceReadiness and
                    Ember.Application#deferReadiness.

                    @private
                    @deprecated
                    @method initialize
                   **/
            initialize: function() {
                Ember.deprecate('Calling initialize manually is not supported. Please see Ember.Application#advanceReadiness and Ember.Application#deferReadiness');
            },

            /**
                    Initialize the application. This happens automatically.

                    Run any initializers and run the application load hook. These hooks may
                    choose to defer readiness. For example, an authentication hook might want
                    to defer readiness until the auth token has been retrieved.

                    @private
                    @method _initialize
                  */
            _initialize: function() {
                if (this.isDestroyed) {
                    return;
                }

                // At this point, the App.Router must already be assigned
                if (this.Router) {
                    var container = this.__container__;
                    container.unregister('router:main');
                    container.register('router:main', this.Router);
                }

                this.runInitializers();
                runLoadHooks('application', this);

                // At this point, any initializers or load hooks that would have wanted
                // to defer readiness have fired. In general, advancing readiness here
                // will proceed to didBecomeReady.
                this.advanceReadiness();

                return this;
            },

            /**
                    Reset the application. This is typically used only in tests. It cleans up
                    the application in the following order:

                    1. Deactivate existing routes
                    2. Destroy all objects in the container
                    3. Create a new application container
                    4. Re-route to the existing url

                    Typical Example:

                    ```javascript

                    var App;

                    run(function() {
                      App = Ember.Application.create();
                    });

                    module("acceptance test", {
                      setup: function() {
                        App.reset();
                      }
                    });

                    test("first test", function() {
                      // App is freshly reset
                    });

                    test("first test", function() {
                      // App is again freshly reset
                    });
                    ```

                    Advanced Example:

                    Occasionally you may want to prevent the app from initializing during
                    setup. This could enable extra configuration, or enable asserting prior
                    to the app becoming ready.

                    ```javascript

                    var App;

                    run(function() {
                      App = Ember.Application.create();
                    });

                    module("acceptance test", {
                      setup: function() {
                        run(function() {
                          App.reset();
                          App.deferReadiness();
                        });
                      }
                    });

                    test("first test", function() {
                      ok(true, 'something before app is initialized');

                      run(function() {
                        App.advanceReadiness();
                      });
                      ok(true, 'something after app is initialized');
                    });
                    ```

                    @method reset
                  **/
            reset: function() {
                this._readinessDeferrals = 1;

                function handleReset() {
                    var router = this.__container__.lookup('router:main');
                    router.reset();

                    run(this.__container__, 'destroy');

                    this.buildContainer();

                    run.schedule('actions', this, function() {
                        this._initialize();
                    });
                }

                run.join(this, handleReset);
            },

            /**
                    @private
                    @method runInitializers
                  */
            runInitializers: function() {
                var initializers = get(this.constructor, 'initializers');
                var container = this.__container__;
                var graph = new DAG();
                var namespace = this;
                var name, initializer;

                for (name in initializers) {
                    initializer = initializers[name];
                    graph.addEdges(initializer.name, initializer.initialize, initializer.before, initializer.after);
                }

                graph.topsort(function (vertex) {
                    var initializer = vertex.value;
                    Ember.assert("No application initializer named '" + vertex.name + "'", initializer);
                    initializer(container, namespace);
                });
            },

            /**
                    @private
                    @method didBecomeReady
                  */
            didBecomeReady: function() {
                this.setupEventDispatcher();
                this.ready(); // user hook
                this.startRouting();

                if (!Ember.testing) {
                    // Eagerly name all classes that are already loaded
                    Ember.Namespace.processAll();
                    Ember.BOOTED = true;
                }

                this.resolve(this);
            },

            /**
                    Setup up the event dispatcher to receive events on the
                    application's `rootElement` with any registered
                    `customEvents`.

                    @private
                    @method setupEventDispatcher
                  */
            setupEventDispatcher: function() {
                var customEvents = get(this, 'customEvents');
                var rootElement = get(this, 'rootElement');
                var dispatcher = this.__container__.lookup('event_dispatcher:main');

                set(this, 'eventDispatcher', dispatcher);
                dispatcher.setup(customEvents, rootElement);
            },

            /**
                    If the application has a router, use it to route to the current URL, and
                    trigger a new call to `route` whenever the URL changes.

                    @private
                    @method startRouting
                    @property router {Ember.Router}
                  */
            startRouting: function() {
                var router = this.__container__.lookup('router:main');
                if (!router) {
                    return;
                }

                router.startRouting();
            },

            handleURL: function(url) {
                var router = this.__container__.lookup('router:main');

                router.handleURL(url);
            },

            /**
                    Called when the Application has become ready.
                    The call will be delayed until the DOM has become ready.

                    @event ready
                  */
            ready: K,

            /**
                    @deprecated Use 'Resolver' instead
                    Set this to provide an alternate class to `Ember.DefaultResolver`


                    @property resolver
                  */
            resolver: null,

            /**
                    Set this to provide an alternate class to `Ember.DefaultResolver`

                    @property resolver
                  */
            Resolver: null,

            willDestroy: function() {
                Ember.BOOTED = false;
                // Ensure deactivation of routes before objects are destroyed
                this.__container__.lookup('router:main').reset();

                this.__container__.destroy();
            },

            initializer: function(options) {
                this.constructor.initializer(options);
            },

            /**
                    @method then
                    @private
                    @deprecated
                  */
            then: function() {
                Ember.deprecate('Do not use `.then` on an instance of Ember.Application.  Please use the `.ready` hook instead.');

                this._super.apply(this, arguments);
            }
        });

        Application.reopenClass({
            initializers: {},

            /**
                    Initializer receives an object which has the following attributes:
                    `name`, `before`, `after`, `initialize`. The only required attribute is
                    `initialize, all others are optional.

                    * `name` allows you to specify under which name the initializer is registered.
                    This must be a unique name, as trying to register two initializers with the
                    same name will result in an error.

                    ```javascript
                    Ember.Application.initializer({
                      name: 'namedInitializer',
                      initialize: function(container, application) {
                        Ember.debug("Running namedInitializer!");
                      }
                    });
                    ```

                    * `before` and `after` are used to ensure that this initializer is ran prior
                    or after the one identified by the value. This value can be a single string
                    or an array of strings, referencing the `name` of other initializers.

                    An example of ordering initializers, we create an initializer named `first`:

                    ```javascript
                    Ember.Application.initializer({
                      name: 'first',
                      initialize: function(container, application) {
                        Ember.debug("First initializer!");
                      }
                    });

                    // DEBUG: First initializer!
                    ```

                    We add another initializer named `second`, specifying that it should run
                    after the initializer named `first`:

                    ```javascript
                    Ember.Application.initializer({
                      name: 'second',
                      after: 'first',

                      initialize: function(container, application) {
                        Ember.debug("Second initializer!");
                      }
                    });

                    // DEBUG: First initializer!
                    // DEBUG: Second initializer!
                    ```

                    Afterwards we add a further initializer named `pre`, this time specifying
                    that it should run before the initializer named `first`:

                    ```javascript
                    Ember.Application.initializer({
                      name: 'pre',
                      before: 'first',

                      initialize: function(container, application) {
                        Ember.debug("Pre initializer!");
                      }
                    });

                    // DEBUG: Pre initializer!
                    // DEBUG: First initializer!
                    // DEBUG: Second initializer!
                    ```

                    Finally we add an initializer named `post`, specifying it should run after
                    both the `first` and the `second` initializers:

                    ```javascript
                    Ember.Application.initializer({
                      name: 'post',
                      after: ['first', 'second'],

                      initialize: function(container, application) {
                        Ember.debug("Post initializer!");
                      }
                    });

                    // DEBUG: Pre initializer!
                    // DEBUG: First initializer!
                    // DEBUG: Second initializer!
                    // DEBUG: Post initializer!
                    ```

                    * `initialize` is a callback function that receives two arguments, `container`
                    and `application` on which you can operate.

                    Example of using `container` to preload data into the store:

                    ```javascript
                    Ember.Application.initializer({
                      name: "preload-data",

                      initialize: function(container, application) {
                        var store = container.lookup('store:main');
                        store.pushPayload(preloadedData);
                      }
                    });
                    ```

                    Example of using `application` to register an adapter:

                    ```javascript
                    Ember.Application.initializer({
                      name: 'api-adapter',

                      initialize: function(container, application) {
                        application.register('api-adapter:main', ApiAdapter);
                      }
                    });
                    ```

                    @method initializer
                    @param initializer {Object}
                   */
            initializer: function(initializer) {
                // If this is the first initializer being added to a subclass, we are going to reopen the class
                // to make sure we have a new `initializers` object, which extends from the parent class' using
                // prototypal inheritance. Without this, attempting to add initializers to the subclass would
                // pollute the parent class as well as other subclasses.
                if (this.superclass.initializers !== undefined && this.superclass.initializers === this.initializers) {
                    this.reopenClass({
                        initializers: create(this.initializers)
                    });
                }

                Ember.assert("The initializer '" + initializer.name + "' has already been registered", !this.initializers[initializer.name]);
                Ember.assert("An initializer cannot be registered without an initialize function", canInvoke(initializer, 'initialize'));

                this.initializers[initializer.name] = initializer;
            },

            /**
                    This creates a container with the default Ember naming conventions.

                    It also configures the container:

                    * registered views are created every time they are looked up (they are
                      not singletons)
                    * registered templates are not factories; the registered value is
                      returned directly.
                    * the router receives the application as its `namespace` property
                    * all controllers receive the router as their `target` and `controllers`
                      properties
                    * all controllers receive the application as their `namespace` property
                    * the application view receives the application controller as its
                      `controller` property
                    * the application view receives the application template as its
                      `defaultTemplate` property

                    @private
                    @method buildContainer
                    @static
                    @param {Ember.Application} namespace the application to build the
                      container for.
                    @return {Ember.Container} the built container
                  */
            buildContainer: function(namespace) {
                var container = new Container();

                Container.defaultContainer = new DeprecatedContainer(container);

                container.set = set;
                container.resolver = resolverFor(namespace);
                container.normalize = container.resolver.normalize;
                container.describe = container.resolver.describe;
                container.makeToString = container.resolver.makeToString;

                container.optionsForType('component', {
                    singleton: false 
                });
                container.optionsForType('view', {
                    singleton: false 
                });
                container.optionsForType('template', {
                    instantiate: false 
                });
                container.optionsForType('helper', {
                    instantiate: false 
                });

                container.register('application:main', namespace, {
                    instantiate: false 
                });

                container.register('controller:basic', Controller, {
                    instantiate: false 
                });
                container.register('controller:object', ObjectController, {
                    instantiate: false 
                });
                container.register('controller:array', ArrayController, {
                    instantiate: false 
                });
                container.register('route:basic', Route, {
                    instantiate: false 
                });
                container.register('event_dispatcher:main', EventDispatcher);

                container.register('router:main', Router);
                container.injection('router:main', 'namespace', 'application:main');

                container.register('location:auto', AutoLocation);
                container.register('location:hash', HashLocation);
                container.register('location:history', HistoryLocation);
                container.register('location:none', NoneLocation);

                container.injection('controller', 'target', 'router:main');
                container.injection('controller', 'namespace', 'application:main');

                container.register('-bucket-cache:main', BucketCache);
                container.injection('router', '_bucketCache', '-bucket-cache:main');
                container.injection('route', '_bucketCache', '-bucket-cache:main');
                container.injection('controller', '_bucketCache', '-bucket-cache:main');

                container.injection('route', 'router', 'router:main');
                container.injection('location', 'rootURL', '-location-setting:root-url');

                // DEBUGGING
                container.register('resolver-for-debugging:main', container.resolver.__resolver__, {
                    instantiate: false 
                });
                container.injection('container-debug-adapter:main', 'resolver', 'resolver-for-debugging:main');
                container.injection('data-adapter:main', 'containerDebugAdapter', 'container-debug-adapter:main');
                // Custom resolver authors may want to register their own ContainerDebugAdapter with this key

                // ES6TODO: resolve this via import once ember-application package is ES6'ed
                if (!ContainerDebugAdapter) {
                    ContainerDebugAdapter = requireModule('ember-extension-support/container_debug_adapter')['default'];
                }
                container.register('container-debug-adapter:main', ContainerDebugAdapter);

                return container;
            }
        });

        /**
              This function defines the default lookup rules for container lookups:

              * templates are looked up on `Ember.TEMPLATES`
              * other names are looked up on the application after classifying the name.
                For example, `controller:post` looks up `App.PostController` by default.
              * if the default lookup fails, look for registered classes on the container

              This allows the application to register default injections in the container
              that could be overridden by the normal naming convention.

              @private
              @method resolverFor
              @param {Ember.Namespace} namespace the namespace to look for classes
              @return {*} the resolved value for a given lookup
            */
        function resolverFor(namespace) {
            if (namespace.get('resolver')) {
                Ember.deprecate('Application.resolver is deprecated in favor of Application.Resolver', false);
            }

            var ResolverClass = namespace.get('resolver') || namespace.get('Resolver') || DefaultResolver;
            var resolver = ResolverClass.create({
                namespace: namespace
            });

            function resolve(fullName) {
                return resolver.resolve(fullName);
            }

            resolve.describe = function(fullName) {
                return resolver.lookupDescription(fullName);
            };

            resolve.makeToString = function(factory, fullName) {
                return resolver.makeToString(factory, fullName);
            };

            resolve.normalize = function(fullName) {
                if (resolver.normalize) {
                    return resolver.normalize(fullName);
                } else {
                    Ember.deprecate('The Resolver should now provide a \'normalize\' function', false);
                    return fullName;
                }
            };

            resolve.__resolver__ = resolver;

            return resolve;
        }

        __exports__["default"] = Application;
    });
    define("ember-application/system/dag",
    ["ember-metal/error", "exports"],
    function(__dependency1__, __exports__) {
        "use strict";
        var EmberError = __dependency1__["default"];

        function visit(vertex, fn, visited, path) {
            var name = vertex.name;
            var vertices = vertex.incoming;
            var names = vertex.incomingNames;
            var len = names.length;
            var i;

            if (!visited) {
                visited = {};
            }
            if (!path) {
                path = [];
            }
            if (visited.hasOwnProperty(name)) {
                return;
            }
            path.push(name);
            visited[name] = true;
            for (i = 0; i < len; i++) {
                visit(vertices[names[i]], fn, visited, path);
            }
            fn(vertex, path);
            path.pop();
        }

        function DAG() {
            this.names = [];
            this.vertices = {};
        }

        DAG.prototype.add = function(name) {
            if (!name) {
                return;
            }
            if (this.vertices.hasOwnProperty(name)) {
                return this.vertices[name];
            }
            var vertex = {
                name: name,
                incoming: {},
                incomingNames: [],
                hasOutgoing: false,
                value: null
            };
            this.vertices[name] = vertex;
            this.names.push(name);
            return vertex;
        };

        DAG.prototype.map = function(name, value) {
            this.add(name).value = value;
        };

        DAG.prototype.addEdge = function(fromName, toName) {
            if (!fromName || !toName || fromName === toName) {
                return;
            }
            var from = this.add(fromName), to = this.add(toName);
            if (to.incoming.hasOwnProperty(fromName)) {
                return;
            }
            function checkCycle(vertex, path) {
                if (vertex.name === toName) {
                    throw new EmberError("cycle detected: " + toName + " <- " + path.join(" <- "));
                }
            }
            visit(from, checkCycle);
            from.hasOutgoing = true;
            to.incoming[fromName] = from;
            to.incomingNames.push(fromName);
        };

        DAG.prototype.topsort = function(fn) {
            var visited = {};
            var vertices = this.vertices;
            var names = this.names;
            var len = names.length;
            var i, vertex;

            for (i = 0; i < len; i++) {
                vertex = vertices[names[i]];
                if (!vertex.hasOutgoing) {
                    visit(vertex, fn, visited);
                }
            }
        };

        DAG.prototype.addEdges = function(name, value, before, after) {
            var i;
            this.map(name, value);
            if (before) {
                if (typeof before === 'string') {
                    this.addEdge(name, before);
                } else {
                    for (i = 0; i < before.length; i++) {
                        this.addEdge(name, before[i]);
                    }
                }
            }
            if (after) {
                if (typeof after === 'string') {
                    this.addEdge(after, name);
                } else {
                    for (i = 0; i < after.length; i++) {
                        this.addEdge(after[i], name);
                    }
                }
            }
        };

        __exports__["default"] = DAG;
    });
    define("ember-application/system/deprecated-container",
    ["exports"],
    function(__exports__) {
        "use strict";
        function DeprecatedContainer(container) {
            this._container = container;
        }

        DeprecatedContainer.deprecate = function(method) {
            return function() {
                var container = this._container;

                Ember.deprecate('Using the defaultContainer is no longer supported. [defaultContainer#' + method + '] see: http://git.io/EKPpnA', false);
                return container[method].apply(container, arguments);
            };
        };

        DeprecatedContainer.prototype = {
            _container: null,
            lookup: DeprecatedContainer.deprecate('lookup'),
            resolve: DeprecatedContainer.deprecate('resolve'),
            register: DeprecatedContainer.deprecate('register')
        };

        __exports__["default"] = DeprecatedContainer;
    });
    define("ember-application/system/resolver",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/logger", "ember-runtime/system/string", "ember-runtime/system/object", "ember-runtime/system/namespace", "ember-handlebars", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-application
            */

        var Ember = __dependency1__["default"];
        // Ember.TEMPLATES, Ember.assert
        var get = __dependency2__.get;
        var Logger = __dependency3__["default"];
        var classify = __dependency4__.classify;
        var capitalize = __dependency4__.capitalize;
        var decamelize = __dependency4__.decamelize;
        var EmberObject = __dependency5__["default"];
        var Namespace = __dependency6__["default"];
        var EmberHandlebars = __dependency7__["default"];

        var Resolver = EmberObject.extend({
            /**
                    This will be set to the Application instance when it is
                    created.

                    @property namespace
                  */
            namespace: null,
            normalize: Ember.required(Function),
            resolve: Ember.required(Function),
            parseName: Ember.required(Function),
            lookupDescription: Ember.required(Function),
            makeToString: Ember.required(Function),
            resolveOther: Ember.required(Function),
            _logLookup: Ember.required(Function)
        });
        __exports__.Resolver = Resolver;
        /**
              The DefaultResolver defines the default lookup rules to resolve
              container lookups before consulting the container for registered
              items:

              * templates are looked up on `Ember.TEMPLATES`
              * other names are looked up on the application after converting
                the name. For example, `controller:post` looks up
                `App.PostController` by default.
              * there are some nuances (see examples below)

              ### How Resolving Works

              The container calls this object's `resolve` method with the
              `fullName` argument.

              It first parses the fullName into an object using `parseName`.

              Then it checks for the presence of a type-specific instance
              method of the form `resolve[Type]` and calls it if it exists.
              For example if it was resolving 'template:post', it would call
              the `resolveTemplate` method.

              Its last resort is to call the `resolveOther` method.

              The methods of this object are designed to be easy to override
              in a subclass. For example, you could enhance how a template
              is resolved like so:

              ```javascript
              App = Ember.Application.create({
                Resolver: Ember.DefaultResolver.extend({
                  resolveTemplate: function(parsedName) {
                    var resolvedTemplate = this._super(parsedName);
                    if (resolvedTemplate) { return resolvedTemplate; }
                    return Ember.TEMPLATES['not_found'];
                  }
                })
              });
              ```

              Some examples of how names are resolved:

              ```
              'template:post' //=> Ember.TEMPLATES['post']
              'template:posts/byline' //=> Ember.TEMPLATES['posts/byline']
              'template:posts.byline' //=> Ember.TEMPLATES['posts/byline']
              'template:blogPost' //=> Ember.TEMPLATES['blogPost']
                                  //   OR
                                  //   Ember.TEMPLATES['blog_post']
              'controller:post' //=> App.PostController
              'controller:posts.index' //=> App.PostsIndexController
              'controller:blog/post' //=> Blog.PostController
              'controller:basic' //=> Ember.Controller
              'route:post' //=> App.PostRoute
              'route:posts.index' //=> App.PostsIndexRoute
              'route:blog/post' //=> Blog.PostRoute
              'route:basic' //=> Ember.Route
              'view:post' //=> App.PostView
              'view:posts.index' //=> App.PostsIndexView
              'view:blog/post' //=> Blog.PostView
              'view:basic' //=> Ember.View
              'foo:post' //=> App.PostFoo
              'model:post' //=> App.Post
              ```

              @class DefaultResolver
              @namespace Ember
              @extends Ember.Object
            */

        __exports__["default"] = EmberObject.extend({
            /**
                    This will be set to the Application instance when it is
                    created.

                    @property namespace
                  */
            namespace: null,

            normalize: function(fullName) {
                var split = fullName.split(':', 2),
                type = split[0],
                name = split[1];

                Ember.assert("Tried to normalize a container name without a colon (:) in it. You probably tried to lookup a name that did not contain a type, a colon, and a name. A proper lookup name would be `view:post`.", split.length === 2);

                if (type !== 'template') {
                    var result = name;

                    if (result.indexOf('.') > -1) {
                        result = result.replace(/\.(.)/g, function(m) {
                            return m.charAt(1).toUpperCase();
                        });
                    }

                    if (name.indexOf('_') > -1) {
                        result = result.replace(/_(.)/g, function(m) {
                            return m.charAt(1).toUpperCase();
                        });
                    }

                    return type + ':' + result;
                } else {
                    return fullName;
                }
            },


            /**
                    This method is called via the container's resolver method.
                    It parses the provided `fullName` and then looks up and
                    returns the appropriate template or class.

                    @method resolve
                    @param {String} fullName the lookup string
                    @return {Object} the resolved factory
                  */
            resolve: function(fullName) {
                var parsedName = this.parseName(fullName),
                resolveMethodName = parsedName.resolveMethodName,
                resolved;

                if (!(parsedName.name && parsedName.type)) {
                    throw new TypeError('Invalid fullName: `' + fullName + '`, must be of the form `type:name` ');
                }

                if (this[resolveMethodName]) {
                    resolved = this[resolveMethodName](parsedName);
                }

                if (!resolved) {
                    resolved = this.resolveOther(parsedName);
                }

                if (parsedName.root && parsedName.root.LOG_RESOLVER) {
                    this._logLookup(resolved, parsedName);
                }

                return resolved;
            },
            /**
                    Convert the string name of the form 'type:name' to
                    a Javascript object with the parsed aspects of the name
                    broken out.

                    @protected
                    @param {String} fullName the lookup string
                    @method parseName
                  */
            parseName: function(fullName) {
                var nameParts = fullName.split(':'),
                type = nameParts[0], fullNameWithoutType = nameParts[1],
                name = fullNameWithoutType,
                namespace = get(this, 'namespace'),
                root = namespace;

                if (type !== 'template' && name.indexOf('/') !== -1) {
                    var parts = name.split('/');
                    name = parts[parts.length - 1];
                    var namespaceName = capitalize(parts.slice(0, -1).join('.'));
                    root = Namespace.byName(namespaceName);

                    Ember.assert('You are looking for a ' + name + ' ' + type + ' in the ' + namespaceName + ' namespace, but the namespace could not be found', root);
                }

                return {
                    fullName: fullName,
                    type: type,
                    fullNameWithoutType: fullNameWithoutType,
                    name: name,
                    root: root,
                    resolveMethodName: 'resolve' + classify(type)
                };
            },

            /**
                    Returns a human-readable description for a fullName. Used by the
                    Application namespace in assertions to describe the
                    precise name of the class that Ember is looking for, rather than
                    container keys.

                    @protected
                    @param {String} fullName the lookup string
                    @method lookupDescription
                  */
            lookupDescription: function(fullName) {
                var parsedName = this.parseName(fullName);

                if (parsedName.type === 'template') {
                    return 'template at ' + parsedName.fullNameWithoutType.replace(/\./g, '/');
                }

                var description = parsedName.root + '.' + classify(parsedName.name);
                if (parsedName.type !== 'model') {
                    description += classify(parsedName.type);
                }

                return description;
            },

            makeToString: function(factory, fullName) {
                return factory.toString();
            },
            /**
                    Given a parseName object (output from `parseName`), apply
                    the conventions expected by `Ember.Router`

                    @protected
                    @param {Object} parsedName a parseName object with the parsed
                      fullName lookup string
                    @method useRouterNaming
                  */
            useRouterNaming: function(parsedName) {
                parsedName.name = parsedName.name.replace(/\./g, '_');
                if (parsedName.name === 'basic') {
                    parsedName.name = '';
                }
            },
            /**
                    Look up the template in Ember.TEMPLATES

                    @protected
                    @param {Object} parsedName a parseName object with the parsed
                      fullName lookup string
                    @method resolveTemplate
                  */
            resolveTemplate: function(parsedName) {
                var templateName = parsedName.fullNameWithoutType.replace(/\./g, '/');

                if (Ember.TEMPLATES[templateName]) {
                    return Ember.TEMPLATES[templateName];
                }

                templateName = decamelize(templateName);
                if (Ember.TEMPLATES[templateName]) {
                    return Ember.TEMPLATES[templateName];
                }
            },
            /**
                    Lookup the view using `resolveOther`

                    @protected
                    @param {Object} parsedName a parseName object with the parsed
                      fullName lookup string
                    @method resolveView
                  */
            resolveView: function(parsedName) {
                this.useRouterNaming(parsedName);
                return this.resolveOther(parsedName);
            },
            /**
                    Lookup the controller using `resolveOther`

                    @protected
                    @param {Object} parsedName a parseName object with the parsed
                      fullName lookup string
                    @method resolveController
                  */
            resolveController: function(parsedName) {
                this.useRouterNaming(parsedName);
                return this.resolveOther(parsedName);
            },
            /**
                    Lookup the route using `resolveOther`

                    @protected
                    @param {Object} parsedName a parseName object with the parsed
                      fullName lookup string
                    @method resolveRoute
                  */
            resolveRoute: function(parsedName) {
                this.useRouterNaming(parsedName);
                return this.resolveOther(parsedName);
            },

            /**
                    Lookup the model on the Application namespace

                    @protected
                    @param {Object} parsedName a parseName object with the parsed
                      fullName lookup string
                    @method resolveModel
                  */
            resolveModel: function(parsedName) {
                var className = classify(parsedName.name);
                var factory = get(parsedName.root, className);

                if (factory) {
                    return factory;
                }
            },
            /**
                    Look up the specified object (from parsedName) on the appropriate
                    namespace (usually on the Application)

                    @protected
                    @param {Object} parsedName a parseName object with the parsed
                      fullName lookup string
                    @method resolveHelper
                  */
            resolveHelper: function(parsedName) {
                return this.resolveOther(parsedName) || EmberHandlebars.helpers[parsedName.fullNameWithoutType];
            },
            /**
                    Look up the specified object (from parsedName) on the appropriate
                    namespace (usually on the Application)

                    @protected
                    @param {Object} parsedName a parseName object with the parsed
                      fullName lookup string
                    @method resolveOther
                  */
            resolveOther: function(parsedName) {
                var className = classify(parsedName.name) + classify(parsedName.type);
                var factory = get(parsedName.root, className);
                if (factory) {
                    return factory;
                }
            },

            /**
                   @method _logLookup
                   @param {Boolean} found
                   @param {Object} parsedName
                   @private
                  */
            _logLookup: function(found, parsedName) {
                var symbol, padding;

                if (found) {
                    symbol = '[✓]';
                } else {
                    symbol = '[ ]';
                }

                if (parsedName.fullName.length > 60) {
                    padding = '.';
                } else {
                    padding = new Array(60 - parsedName.fullName.length).join('.');
                }

                Logger.info(symbol, parsedName.fullName, padding, this.lookupDescription(parsedName.fullName));
            }
        });
    });
    define("ember-debug",
    ["ember-metal/core", "ember-metal/error", "ember-metal/logger"],
    function(__dependency1__, __dependency2__, __dependency3__) {
        "use strict";
        /*global __fail__*/

        var Ember = __dependency1__["default"];
        var EmberError = __dependency2__["default"];
        var Logger = __dependency3__["default"];

        /**
            Ember Debug

            @module ember
            @submodule ember-debug
            */

        /**
            @class Ember
            */

        /**
              Define an assertion that will throw an exception if the condition is not
              met. Ember build tools will remove any calls to `Ember.assert()` when
              doing a production build. Example:

              ```javascript
              // Test for truthiness
              Ember.assert('Must pass a valid object', obj);

              // Fail unconditionally
              Ember.assert('This code path should never be run');
              ```

              @method assert
              @param {String} desc A description of the assertion. This will become
                the text of the Error thrown if the assertion fails.
              @param {Boolean} test Must be truthy for the assertion to pass. If
                falsy, an exception will be thrown.
            */
        Ember.assert = function(desc, test) {
            if (!test) {
                throw new EmberError("Assertion Failed: " + desc);
            }
        };


        /**
              Display a warning with the provided message. Ember build tools will
              remove any calls to `Ember.warn()` when doing a production build.

              @method warn
              @param {String} message A warning to display.
              @param {Boolean} test An optional boolean. If falsy, the warning
                will be displayed.
            */
        Ember.warn = function(message, test) {
            if (!test) {
                Logger.warn("WARNING: " + message);
                if ('trace' in Logger) 
                    Logger.trace();
            }
        };

        /**
              Display a debug notice. Ember build tools will remove any calls to
              `Ember.debug()` when doing a production build.

              ```javascript
              Ember.debug('I\'m a debug notice!');
              ```

              @method debug
              @param {String} message A debug message to display.
            */
        Ember.debug = function(message) {
            Logger.debug("DEBUG: " + message);
        };

        /**
              Display a deprecation warning with the provided message and a stack trace
              (Chrome and Firefox only). Ember build tools will remove any calls to
              `Ember.deprecate()` when doing a production build.

              @method deprecate
              @param {String} message A description of the deprecation.
              @param {Boolean} test An optional boolean. If falsy, the deprecation
                will be displayed.
            */
        Ember.deprecate = function(message, test) {
            if (test) {
                return;
            }

            if (Ember.ENV.RAISE_ON_DEPRECATION) {
                throw new EmberError(message);
            }

            var error;

            // When using new Error, we can't do the arguments check for Chrome. Alternatives are welcome
            try {
                __fail__.fail();
            } catch (e) {
                error = e;
            }

            if (Ember.LOG_STACKTRACE_ON_DEPRECATION && error.stack) {
                var stack, stackStr = '';
                if (error['arguments']) {
                    // Chrome
                    stack = error.stack.replace(/^\s+at\s+/gm, '').
                    replace(/^([^\(]+?)([\n$])/gm, '{anonymous}($1)$2').
                    replace(/^Object.<anonymous>\s*\(([^\)]+)\)/gm, '{anonymous}($1)').split('\n');
                    stack.shift();
                } else {
                    // Firefox
                    stack = error.stack.replace(/(?:\n@:0)?\s+$/m, '').
                    replace(/^\(/gm, '{anonymous}(').split('\n');
                }

                stackStr = "\n    " + stack.slice(2).join("\n    ");
                message = message + stackStr;
            }

            Logger.warn("DEPRECATION: " + message);
        };



        /**
              Alias an old, deprecated method with its new counterpart.

              Display a deprecation warning with the provided message and a stack trace
              (Chrome and Firefox only) when the assigned method is called.

              Ember build tools will not remove calls to `Ember.deprecateFunc()`, though
              no warnings will be shown in production.

              ```javascript
              Ember.oldMethod = Ember.deprecateFunc('Please use the new, updated method', Ember.newMethod);
              ```

              @method deprecateFunc
              @param {String} message A description of the deprecation.
              @param {Function} func The new function called to replace its deprecated counterpart.
              @return {Function} a new function that wrapped the original function with a deprecation warning
            */
        Ember.deprecateFunc = function(message, func) {
            return function() {
                Ember.deprecate(message);
                return func.apply(this, arguments);
            };
        };


        /**
              Run a function meant for debugging. Ember build tools will remove any calls to
              `Ember.runInDebug()` when doing a production build.

              ```javascript
              Ember.runInDebug(function() {
                Ember.Handlebars.EachView.reopen({
                  didInsertElement: function() {
                    console.log('I\'m happy');
                  }
                });
              });
              ```

              @method runInDebug
              @param {Function} func The function to be executed.
              @since 1.5.0
            */
        Ember.runInDebug = function(func) {
            func();
        };

        // Inform the developer about the Ember Inspector if not installed.
        if (!Ember.testing) {
            var isFirefox = typeof InstallTrigger !== 'undefined';
            var isChrome = !!window.chrome && !window.opera;

            if (typeof window !== 'undefined' && (isFirefox || isChrome) && window.addEventListener) {
                window.addEventListener("load", function() {
                    if (document.documentElement && document.documentElement.dataset && !document.documentElement.dataset.emberExtension) {
                        var downloadURL;

                        if (isChrome) {
                            downloadURL = 'https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi';
                        } else if (isFirefox) {
                            downloadURL = 'https://addons.mozilla.org/en-US/firefox/addon/ember-inspector/';
                        }

                        Ember.debug('For more advanced debugging, install the Ember Inspector from ' + downloadURL);
                    }
                }, false);
            }
        }
    });
    define("ember-extension-support",
    ["ember-metal/core", "ember-extension-support/data_adapter", "ember-extension-support/container_debug_adapter"],
    function(__dependency1__, __dependency2__, __dependency3__) {
        "use strict";
        /**
            Ember Extension Support

            @module ember
            @submodule ember-extension-support
            @requires ember-application
            */

        var Ember = __dependency1__["default"];
        var DataAdapter = __dependency2__["default"];
        var ContainerDebugAdapter = __dependency3__["default"];

        Ember.DataAdapter = DataAdapter;
        Ember.ContainerDebugAdapter = ContainerDebugAdapter;
    });
    define("ember-extension-support/container_debug_adapter",
    ["ember-metal/core", "ember-runtime/system/native_array", "ember-metal/utils", "ember-runtime/system/string", "ember-runtime/system/namespace", "ember-runtime/system/object", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        var emberA = __dependency2__.A;
        var typeOf = __dependency3__.typeOf;
        var dasherize = __dependency4__.dasherize;
        var classify = __dependency4__.classify;
        var Namespace = __dependency5__["default"];
        var EmberObject = __dependency6__["default"];

        /**
            @module ember
            @submodule ember-extension-support
            */

        /**
              The `ContainerDebugAdapter` helps the container and resolver interface
              with tools that debug Ember such as the
              [Ember Extension](https://github.com/tildeio/ember-extension)
              for Chrome and Firefox.

              This class can be extended by a custom resolver implementer
              to override some of the methods with library-specific code.

              The methods likely to be overridden are:

              * `canCatalogEntriesByType`
              * `catalogEntriesByType`

              The adapter will need to be registered
              in the application's container as `container-debug-adapter:main`

              Example:

              ```javascript
              Application.initializer({
                name: "containerDebugAdapter",

                initialize: function(container, application) {
                  application.register('container-debug-adapter:main', require('app/container-debug-adapter'));
                }
              });
              ```

              @class ContainerDebugAdapter
              @namespace Ember
              @extends EmberObject
              @since 1.5.0
            */
        __exports__["default"] = EmberObject.extend({
            /**
                    The container of the application being debugged.
                    This property will be injected
                    on creation.

                    @property container
                    @default null
                  */
            container: null,

            /**
                    The resolver instance of the application
                    being debugged. This property will be injected
                    on creation.

                    @property resolver
                    @default null
                  */
            resolver: null,

            /**
                    Returns true if it is possible to catalog a list of available
                    classes in the resolver for a given type.

                    @method canCatalogEntriesByType
                    @param {string} type The type. e.g. "model", "controller", "route"
                    @return {boolean} whether a list is available for this type.
                  */
            canCatalogEntriesByType: function(type) {
                if (type === 'model' || type === 'template') 
                    return false;
                return true;
            },

            /**
                    Returns the available classes a given type.

                    @method catalogEntriesByType
                    @param {string} type The type. e.g. "model", "controller", "route"
                    @return {Array} An array of strings.
                  */
            catalogEntriesByType: function(type) {
                var namespaces = emberA(Namespace.NAMESPACES), types = emberA(), self = this;
                var typeSuffixRegex = new RegExp(classify(type) + "$");

                namespaces.forEach(function(namespace) {
                    if (namespace !== Ember) {
                        for (var key in namespace) {
                            if (!namespace.hasOwnProperty(key)) {
                                continue;
                            }
                            if (typeSuffixRegex.test(key)) {
                                var klass = namespace[key];
                                if (typeOf(klass) === 'class') {
                                    types.push(dasherize(key.replace(typeSuffixRegex, '')));
                                }
                            }
                        }
                    }
                });
                return types;
            }
        });
    });
    define("ember-extension-support/data_adapter",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/run_loop", "ember-runtime/system/string", "ember-runtime/system/namespace", "ember-runtime/system/object", "ember-runtime/system/native_array", "ember-application/system/application", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        var get = __dependency2__.get;
        var run = __dependency3__["default"];
        var dasherize = __dependency4__.dasherize;
        var Namespace = __dependency5__["default"];
        var EmberObject = __dependency6__["default"];
        var emberA = __dependency7__.A;
        var Application = __dependency8__["default"];

        /**
            @module ember
            @submodule ember-extension-support
            */

        /**
              The `DataAdapter` helps a data persistence library
              interface with tools that debug Ember such
              as the [Ember Extension](https://github.com/tildeio/ember-extension)
              for Chrome and Firefox.

              This class will be extended by a persistence library
              which will override some of the methods with
              library-specific code.

              The methods likely to be overridden are:

              * `getFilters`
              * `detect`
              * `columnsForType`
              * `getRecords`
              * `getRecordColumnValues`
              * `getRecordKeywords`
              * `getRecordFilterValues`
              * `getRecordColor`
              * `observeRecord`

              The adapter will need to be registered
              in the application's container as `dataAdapter:main`

              Example:

              ```javascript
              Application.initializer({
                name: "data-adapter",

                initialize: function(container, application) {
                  application.register('data-adapter:main', DS.DataAdapter);
                }
              });
              ```

              @class DataAdapter
              @namespace Ember
              @extends EmberObject
            */
        __exports__["default"] = EmberObject.extend({
            init: function() {
                this._super();
                this.releaseMethods = emberA();
            },

            /**
                    The container of the application being debugged.
                    This property will be injected
                    on creation.

                    @property container
                    @default null
                    @since 1.3.0
                  */
            container: null,


            /**
                    The container-debug-adapter which is used
                    to list all models.

                    @property containerDebugAdapter
                    @default undefined
                    @since 1.5.0
                  **/
            containerDebugAdapter: undefined,

            /**
                    Number of attributes to send
                    as columns. (Enough to make the record
                    identifiable).

                    @private
                    @property attributeLimit
                    @default 3
                    @since 1.3.0
                  */
            attributeLimit: 3,

            /**
                    Stores all methods that clear observers.
                    These methods will be called on destruction.

                    @private
                    @property releaseMethods
                    @since 1.3.0
                  */
            releaseMethods: emberA(),

            /**
                    Specifies how records can be filtered.
                    Records returned will need to have a `filterValues`
                    property with a key for every name in the returned array.

                    @public
                    @method getFilters
                    @return {Array} List of objects defining filters.
                     The object should have a `name` and `desc` property.
                  */
            getFilters: function() {
                return emberA();
            },

            /**
                    Fetch the model types and observe them for changes.

                    @public
                    @method watchModelTypes

                    @param {Function} typesAdded Callback to call to add types.
                    Takes an array of objects containing wrapped types (returned from `wrapModelType`).

                    @param {Function} typesUpdated Callback to call when a type has changed.
                    Takes an array of objects containing wrapped types.

                    @return {Function} Method to call to remove all observers
                  */
            watchModelTypes: function(typesAdded, typesUpdated) {
                var modelTypes = this.getModelTypes(),
                self = this, typesToSend, releaseMethods = emberA();

                typesToSend = modelTypes.map(function(type) {
                    var klass = type.klass;
                    var wrapped = self.wrapModelType(klass, type.name);
                    releaseMethods.push(self.observeModelType(klass, typesUpdated));
                    return wrapped;
                });

                typesAdded(typesToSend);

                var release = function() {
                    releaseMethods.forEach(function(fn) {
                        fn();
                    });
                    self.releaseMethods.removeObject(release);
                };
                this.releaseMethods.pushObject(release);
                return release;
            },

            _nameToClass: function(type) {
                if (typeof type === 'string') {
                    type = this.container.lookupFactory('model:' + type);
                }
                return type;
            },

            /**
                    Fetch the records of a given type and observe them for changes.

                    @public
                    @method watchRecords

                    @param {Function} recordsAdded Callback to call to add records.
                    Takes an array of objects containing wrapped records.
                    The object should have the following properties:
                      columnValues: {Object} key and value of a table cell
                      object: {Object} the actual record object

                    @param {Function} recordsUpdated Callback to call when a record has changed.
                    Takes an array of objects containing wrapped records.

                    @param {Function} recordsRemoved Callback to call when a record has removed.
                    Takes the following parameters:
                      index: the array index where the records were removed
                      count: the number of records removed

                    @return {Function} Method to call to remove all observers
                  */
            watchRecords: function(type, recordsAdded, recordsUpdated, recordsRemoved) {
                var self = this, releaseMethods = emberA(), records = this.getRecords(type), release;

                var recordUpdated = function(updatedRecord) {
                    recordsUpdated([updatedRecord]);
                };

                var recordsToSend = records.map(function(record) {
                    releaseMethods.push(self.observeRecord(record, recordUpdated));
                    return self.wrapRecord(record);
                });


                var contentDidChange = function(array, idx, removedCount, addedCount) {
                    for (var i = idx; i < idx + addedCount; i++) {
                        var record = array.objectAt(i);
                        var wrapped = self.wrapRecord(record);
                        releaseMethods.push(self.observeRecord(record, recordUpdated));
                        recordsAdded([wrapped]);
                    }

                    if (removedCount) {
                        recordsRemoved(idx, removedCount);
                    }
                };

                var observer = {
                    didChange: contentDidChange,
                    willChange: Ember.K 
                };
                records.addArrayObserver(self, observer);

                release = function() {
                    releaseMethods.forEach(function(fn) {
                        fn();
                    });
                    records.removeArrayObserver(self, observer);
                    self.releaseMethods.removeObject(release);
                };

                recordsAdded(recordsToSend);

                this.releaseMethods.pushObject(release);
                return release;
            },

            /**
                    Clear all observers before destruction
                    @private
                    @method willDestroy
                  */
            willDestroy: function() {
                this._super();
                this.releaseMethods.forEach(function(fn) {
                    fn();
                });
            },

            /**
                    Detect whether a class is a model.

                    Test that against the model class
                    of your persistence library

                    @private
                    @method detect
                    @param {Class} klass The class to test
                    @return boolean Whether the class is a model class or not
                  */
            detect: function(klass) {
                return false;
            },

            /**
                    Get the columns for a given model type.

                    @private
                    @method columnsForType
                    @param {Class} type The model type
                    @return {Array} An array of columns of the following format:
                     name: {String} name of the column
                     desc: {String} Humanized description (what would show in a table column name)
                  */
            columnsForType: function(type) {
                return emberA();
            },

            /**
                    Adds observers to a model type class.

                    @private
                    @method observeModelType
                    @param {Class} type The model type class
                    @param {Function} typesUpdated Called when a type is modified.
                    @return {Function} The function to call to remove observers
                  */

            observeModelType: function(type, typesUpdated) {
                var self = this, records = this.getRecords(type);

                var onChange = function() {
                    typesUpdated([self.wrapModelType(type)]);
                };
                var observer = {
                    didChange: function() {
                        run.scheduleOnce('actions', this, onChange);
                    },
                    willChange: Ember.K
                };

                records.addArrayObserver(this, observer);

                var release = function() {
                    records.removeArrayObserver(self, observer);
                };

                return release;
            },


            /**
                    Wraps a given model type and observes changes to it.

                    @private
                    @method wrapModelType
                    @param {Class} type A model class
                    @param {String}  Optional name of the class
                    @return {Object} contains the wrapped type and the function to remove observers
                    Format:
                      type: {Object} the wrapped type
                        The wrapped type has the following format:
                          name: {String} name of the type
                          count: {Integer} number of records available
                          columns: {Columns} array of columns to describe the record
                          object: {Class} the actual Model type class
                      release: {Function} The function to remove observers
                  */
            wrapModelType: function(type, name) {
                var release, records = this.getRecords(type),
                typeToSend, self = this;

                typeToSend = {
                    name: name || type.toString(),
                    count: get(records, 'length'),
                    columns: this.columnsForType(type),
                    object: type
                };


                return typeToSend;
            },


            /**
                    Fetches all models defined in the application.

                    @private
                    @method getModelTypes
                    @return {Array} Array of model types
                  */
            getModelTypes: function() {
                var types, self = this,
                containerDebugAdapter = this.get('containerDebugAdapter');

                if (containerDebugAdapter.canCatalogEntriesByType('model')) {
                    types = containerDebugAdapter.catalogEntriesByType('model');
                } else {
                    types = this._getObjectsOnNamespaces();
                }

                // New adapters return strings instead of classes
                types = emberA(types).map(function(name) {
                    return {
                        klass: self._nameToClass(name),
                        name: name
                    };
                });
                types = emberA(types).filter(function(type) {
                    return self.detect(type.klass);
                });

                return emberA(types);
            },

            /**
                    Loops over all namespaces and all objects
                    attached to them

                    @private
                    @method _getObjectsOnNamespaces
                    @return {Array} Array of model type strings
                  */
            _getObjectsOnNamespaces: function() {
                var namespaces = emberA(Namespace.NAMESPACES),
                types = emberA(),
                self = this;

                namespaces.forEach(function(namespace) {
                    for (var key in namespace) {
                        if (!namespace.hasOwnProperty(key)) {
                            continue;
                        }
                        // Even though we will filter again in `getModelTypes`,
                        // we should not call `lookupContainer` on non-models
                        // (especially when `Ember.MODEL_FACTORY_INJECTIONS` is `true`)
                        if (!self.detect(namespace[key])) {
                            continue;
                        }
                        var name = dasherize(key);
                        if (!(namespace instanceof Application) && namespace.toString()) {
                            name = namespace + '/' + name;
                        }
                        types.push(name);
                    }
                });
                return types;
            },

            /**
                    Fetches all loaded records for a given type.

                    @private
                    @method getRecords
                    @return {Array} An array of records.
                     This array will be observed for changes,
                     so it should update when new records are added/removed.
                  */
            getRecords: function(type) {
                return emberA();
            },

            /**
                    Wraps a record and observers changes to it.

                    @private
                    @method wrapRecord
                    @param {Object} record The record instance.
                    @return {Object} The wrapped record. Format:
                    columnValues: {Array}
                    searchKeywords: {Array}
                  */
            wrapRecord: function(record) {
                var recordToSend = {
                    object: record 
                }, columnValues = {}, self = this;

                recordToSend.columnValues = this.getRecordColumnValues(record);
                recordToSend.searchKeywords = this.getRecordKeywords(record);
                recordToSend.filterValues = this.getRecordFilterValues(record);
                recordToSend.color = this.getRecordColor(record);

                return recordToSend;
            },

            /**
                    Gets the values for each column.

                    @private
                    @method getRecordColumnValues
                    @return {Object} Keys should match column names defined
                    by the model type.
                  */
            getRecordColumnValues: function(record) {
                return {};
            },

            /**
                    Returns keywords to match when searching records.

                    @private
                    @method getRecordKeywords
                    @return {Array} Relevant keywords for search.
                  */
            getRecordKeywords: function(record) {
                return emberA();
            },

            /**
                    Returns the values of filters defined by `getFilters`.

                    @private
                    @method getRecordFilterValues
                    @param {Object} record The record instance
                    @return {Object} The filter values
                  */
            getRecordFilterValues: function(record) {
                return {};
            },

            /**
                    Each record can have a color that represents its state.

                    @private
                    @method getRecordColor
                    @param {Object} record The record instance
                    @return {String} The record's color
                      Possible options: black, red, blue, green
                  */
            getRecordColor: function(record) {
                return null;
            },

            /**
                    Observes all relevant properties and re-sends the wrapped record
                    when a change occurs.

                    @private
                    @method observerRecord
                    @param {Object} record The record instance
                    @param {Function} recordUpdated The callback to call when a record is updated.
                    @return {Function} The function to call to remove all observers.
                  */
            observeRecord: function(record, recordUpdated) {
                return function() {};
            }
        });
    });
    define("ember-extension-support/initializers",
    [],
    function() {
        "use strict";

    });
    define("ember-handlebars-compiler",
    ["ember-metal/core", "exports"],
    function(__dependency1__, __exports__) {
        "use strict";
        /* global Handlebars:true */

        /**
            @module ember
            @submodule ember-handlebars-compiler
            */

        var Ember = __dependency1__["default"];

        // ES6Todo: you'll need to import debugger once debugger is es6'd.
        if (typeof Ember.assert === 'undefined') {
            Ember.assert = function() {};
        }
        if (typeof Ember.FEATURES === 'undefined') {
            Ember.FEATURES = {
                isEnabled: function() {}
            };
        }

        var objectCreate = Object.create || function(parent) {
            function F() {}
            F.prototype = parent;
            return new F();
        };

        // set up for circular references later
        var View, Component;

        // ES6Todo: when ember-debug is es6'ed import this.
        // var emberAssert = Ember.assert;
        var Handlebars = (Ember.imports && Ember.imports.Handlebars) || (this && this.Handlebars);
        if (!Handlebars && typeof require === 'function') {
            Handlebars = require('handlebars');
        }

        Ember.assert("Ember Handlebars requires Handlebars version 1.0 or 1.1. Include " +
        "a SCRIPT tag in the HTML HEAD linking to the Handlebars file " +
        "before you link to Ember.", Handlebars);

        Ember.assert("Ember Handlebars requires Handlebars version 1.0 or 1.1, " +
        "COMPILER_REVISION expected: 4, got: " + Handlebars.COMPILER_REVISION +
        " - Please note: Builds of master may have other COMPILER_REVISION values.",
        Handlebars.COMPILER_REVISION === 4);

        /**
              Prepares the Handlebars templating library for use inside Ember's view
              system.

              The `Ember.Handlebars` object is the standard Handlebars library, extended to
              use Ember's `get()` method instead of direct property access, which allows
              computed properties to be used inside templates.

              To create an `Ember.Handlebars` template, call `Ember.Handlebars.compile()`.
              This will return a function that can be used by `Ember.View` for rendering.

              @class Handlebars
              @namespace Ember
            */
        var EmberHandlebars = Ember.Handlebars = objectCreate(Handlebars);

        /**
              Register a bound helper or custom view helper.

              ## Simple bound helper example

              ```javascript
              Ember.Handlebars.helper('capitalize', function(value) {
                return value.toUpperCase();
              });
              ```

              The above bound helper can be used inside of templates as follows:

              ```handlebars
              {{capitalize name}}
              ```

              In this case, when the `name` property of the template's context changes,
              the rendered value of the helper will update to reflect this change.

              For more examples of bound helpers, see documentation for
              `Ember.Handlebars.registerBoundHelper`.

              ## Custom view helper example

              Assuming a view subclass named `App.CalendarView` were defined, a helper
              for rendering instances of this view could be registered as follows:

              ```javascript
              Ember.Handlebars.helper('calendar', App.CalendarView):
              ```

              The above bound helper can be used inside of templates as follows:

              ```handlebars
              {{calendar}}
              ```

              Which is functionally equivalent to:

              ```handlebars
              {{view App.CalendarView}}
              ```

              Options in the helper will be passed to the view in exactly the same
              manner as with the `view` helper.

              @method helper
              @for Ember.Handlebars
              @param {String} name
              @param {Function|Ember.View} function or view class constructor
              @param {String} dependentKeys*
            */
        EmberHandlebars.helper = function(name, value) {
            if (!View) {
                View = requireModule('ember-views/views/view')['default'];
            }
            // ES6TODO: stupid circular dep
            if (!Component) {
                Component = requireModule('ember-views/views/component')['default'];
            }
            // ES6TODO: stupid circular dep

            Ember.assert("You tried to register a component named '" + name + "', but component names must include a '-'", !Component.detect(value) || name.match(/-/));

            if (View.detect(value)) {
                EmberHandlebars.registerHelper(name, EmberHandlebars.makeViewHelper(value));
            } else {
                EmberHandlebars.registerBoundHelper.apply(null, arguments);
            }
        };

        /**
              Returns a helper function that renders the provided ViewClass.

              Used internally by Ember.Handlebars.helper and other methods
              involving helper/component registration.

              @private
              @method makeViewHelper
              @for Ember.Handlebars
              @param {Function} ViewClass view class constructor
              @since 1.2.0
            */
        EmberHandlebars.makeViewHelper = function(ViewClass) {
            return function(options) {
                Ember.assert("You can only pass attributes (such as name=value) not bare values to a helper for a View found in '" + ViewClass.toString() + "'", arguments.length < 2);
                return EmberHandlebars.helpers.view.call(this, ViewClass, options);
            };
        };

        /**
            @class helpers
            @namespace Ember.Handlebars
            */
        EmberHandlebars.helpers = objectCreate(Handlebars.helpers);

        /**
              Override the the opcode compiler and JavaScript compiler for Handlebars.

              @class Compiler
              @namespace Ember.Handlebars
              @private
              @constructor
            */
        EmberHandlebars.Compiler = function() {};

        // Handlebars.Compiler doesn't exist in runtime-only
        if (Handlebars.Compiler) {
            EmberHandlebars.Compiler.prototype = objectCreate(Handlebars.Compiler.prototype);
        }

        EmberHandlebars.Compiler.prototype.compiler = EmberHandlebars.Compiler;

        /**
              @class JavaScriptCompiler
              @namespace Ember.Handlebars
              @private
              @constructor
            */
        EmberHandlebars.JavaScriptCompiler = function() {};

        // Handlebars.JavaScriptCompiler doesn't exist in runtime-only
        if (Handlebars.JavaScriptCompiler) {
            EmberHandlebars.JavaScriptCompiler.prototype = objectCreate(Handlebars.JavaScriptCompiler.prototype);
            EmberHandlebars.JavaScriptCompiler.prototype.compiler = EmberHandlebars.JavaScriptCompiler;
        }


        EmberHandlebars.JavaScriptCompiler.prototype.namespace = "Ember.Handlebars";

        EmberHandlebars.JavaScriptCompiler.prototype.initializeBuffer = function() {
            return "''";
        };

        /**
              Override the default buffer for Ember Handlebars. By default, Handlebars
              creates an empty String at the beginning of each invocation and appends to
              it. Ember's Handlebars overrides this to append to a single shared buffer.

              @private
              @method appendToBuffer
              @param string {String}
            */
        EmberHandlebars.JavaScriptCompiler.prototype.appendToBuffer = function(string) {
            return "data.buffer.push(" + string + ");";
        };

        // Hacks ahead:
        // Handlebars presently has a bug where the `blockHelperMissing` hook
        // doesn't get passed the name of the missing helper name, but rather
        // gets passed the value of that missing helper evaluated on the current
        // context, which is most likely `undefined` and totally useless.
        //
        // So we alter the compiled template function to pass the name of the helper
        // instead, as expected.
        //
        // This can go away once the following is closed:
        // https://github.com/wycats/handlebars.js/issues/634

        var DOT_LOOKUP_REGEX = /helpers\.(.*?)\)/,
        BRACKET_STRING_LOOKUP_REGEX = /helpers\['(.*?)'/,
        INVOCATION_SPLITTING_REGEX = /(.*blockHelperMissing\.call\(.*)(stack[0-9]+)(,.*)/;

        EmberHandlebars.JavaScriptCompiler.stringifyLastBlockHelperMissingInvocation = function(source) {
            var helperInvocation = source[source.length - 1],
            helperName = (DOT_LOOKUP_REGEX.exec(helperInvocation) || BRACKET_STRING_LOOKUP_REGEX.exec(helperInvocation))[1],
            matches = INVOCATION_SPLITTING_REGEX.exec(helperInvocation);

            source[source.length - 1] = matches[1] + "'" + helperName + "'" + matches[3];
        };

        var stringifyBlockHelperMissing = EmberHandlebars.JavaScriptCompiler.stringifyLastBlockHelperMissingInvocation;

        var originalBlockValue = EmberHandlebars.JavaScriptCompiler.prototype.blockValue;
        EmberHandlebars.JavaScriptCompiler.prototype.blockValue = function() {
            originalBlockValue.apply(this, arguments);
            stringifyBlockHelperMissing(this.source);
        };

        var originalAmbiguousBlockValue = EmberHandlebars.JavaScriptCompiler.prototype.ambiguousBlockValue;
        EmberHandlebars.JavaScriptCompiler.prototype.ambiguousBlockValue = function() {
            originalAmbiguousBlockValue.apply(this, arguments);
            stringifyBlockHelperMissing(this.source);
        };

        /**
              Rewrite simple mustaches from `{{foo}}` to `{{bind "foo"}}`. This means that
              all simple mustaches in Ember's Handlebars will also set up an observer to
              keep the DOM up to date when the underlying property changes.

              @private
              @method mustache
              @for Ember.Handlebars.Compiler
              @param mustache
            */
        EmberHandlebars.Compiler.prototype.mustache = function(mustache) {
            if (!(mustache.params.length || mustache.hash)) {
                var id = new Handlebars.AST.IdNode([{
                    part: '_triageMustache' 
                }
                ]);

                // Update the mustache node to include a hash value indicating whether the original node
                // was escaped. This will allow us to properly escape values when the underlying value
                // changes and we need to re-render the value.
                if (!mustache.escaped) {
                    mustache.hash = mustache.hash || new Handlebars.AST.HashNode([]);
                    mustache.hash.pairs.push(["unescaped", new Handlebars.AST.StringNode("true")]);
                }
                mustache = new Handlebars.AST.MustacheNode([id].concat([mustache.id]), mustache.hash, !mustache.escaped);
            }

            return Handlebars.Compiler.prototype.mustache.call(this, mustache);
        };

        /**
              Used for precompilation of Ember Handlebars templates. This will not be used
              during normal app execution.

              @method precompile
              @for Ember.Handlebars
              @static
              @param {String} string The template to precompile
              @param {Boolean} asObject optional parameter, defaulting to true, of whether or not the
                                        compiled template should be returned as an Object or a String
            */
        EmberHandlebars.precompile = function(string, asObject) {
            var ast = Handlebars.parse(string);

            var options = {
                knownHelpers: {
                    action: true,
                    unbound: true,
                    'bind-attr': true,
                    template: true,
                    view: true,
                    _triageMustache: true
                },
                data: true,
                stringParams: true
            };

            asObject = asObject === undefined ? true : asObject;

            var environment = new EmberHandlebars.Compiler().compile(ast, options);
            return new EmberHandlebars.JavaScriptCompiler().compile(environment, options, undefined, asObject);
        };

        // We don't support this for Handlebars runtime-only
        if (Handlebars.compile) {
            /**
                    The entry point for Ember Handlebars. This replaces the default
                    `Handlebars.compile` and turns on template-local data and String
                    parameters.

                    @method compile
                    @for Ember.Handlebars
                    @static
                    @param {String} string The template to compile
                    @return {Function}
                  */
            EmberHandlebars.compile = function(string) {
                var ast = Handlebars.parse(string);
                var options = {
                    data: true,
                    stringParams: true 
                };
                var environment = new EmberHandlebars.Compiler().compile(ast, options);
                var templateSpec = new EmberHandlebars.JavaScriptCompiler().compile(environment, options, undefined, true);

                var template = EmberHandlebars.template(templateSpec);
                template.isMethod = false; //Make sure we don't wrap templates with ._super

                return template;
            };
        }

        __exports__["default"] = EmberHandlebars;
    });
    define("ember-handlebars",
    ["ember-handlebars-compiler", "ember-metal/core", "ember-runtime/system/lazy_load", "ember-handlebars/loader", "ember-handlebars/ext", "ember-handlebars/string", "ember-handlebars/helpers/shared", "ember-handlebars/helpers/binding", "ember-handlebars/helpers/collection", "ember-handlebars/helpers/view", "ember-handlebars/helpers/unbound", "ember-handlebars/helpers/debug", "ember-handlebars/helpers/each", "ember-handlebars/helpers/template", "ember-handlebars/helpers/partial", "ember-handlebars/helpers/yield", "ember-handlebars/helpers/loc", "ember-handlebars/controls/checkbox", "ember-handlebars/controls/select", "ember-handlebars/controls/text_area", "ember-handlebars/controls/text_field", "ember-handlebars/controls/text_support", "ember-handlebars/controls", "ember-handlebars/component_lookup", "ember-handlebars/views/handlebars_bound_view", "ember-handlebars/views/metamorph_view", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __dependency19__, __dependency20__, __dependency21__, __dependency22__, __dependency23__, __dependency24__, __dependency25__, __dependency26__, __exports__) {
        "use strict";
        var EmberHandlebars = __dependency1__["default"];
        var Ember = __dependency2__["default"];
        // to add to globals

        var runLoadHooks = __dependency3__.runLoadHooks;
        var bootstrap = __dependency4__["default"];

        var normalizePath = __dependency5__.normalizePath;
        var template = __dependency5__.template;
        var makeBoundHelper = __dependency5__.makeBoundHelper;
        var registerBoundHelper = __dependency5__.registerBoundHelper;
        var resolveHash = __dependency5__.resolveHash;
        var resolveParams = __dependency5__.resolveParams;
        var getEscaped = __dependency5__.getEscaped;
        var handlebarsGet = __dependency5__.handlebarsGet;
        var evaluateUnboundHelper = __dependency5__.evaluateUnboundHelper;
        var helperMissingHelper = __dependency5__.helperMissingHelper;
        var blockHelperMissingHelper = __dependency5__.blockHelperMissingHelper;


        // side effect of extending StringUtils of htmlSafe

        var resolvePaths = __dependency7__["default"];
        var bind = __dependency8__.bind;
        var _triageMustacheHelper = __dependency8__._triageMustacheHelper;
        var resolveHelper = __dependency8__.resolveHelper;
        var bindHelper = __dependency8__.bindHelper;
        var boundIfHelper = __dependency8__.boundIfHelper;
        var unboundIfHelper = __dependency8__.unboundIfHelper;
        var withHelper = __dependency8__.withHelper;
        var ifHelper = __dependency8__.ifHelper;
        var unlessHelper = __dependency8__.unlessHelper;
        var bindAttrHelper = __dependency8__.bindAttrHelper;
        var bindAttrHelperDeprecated = __dependency8__.bindAttrHelperDeprecated;
        var bindClasses = __dependency8__.bindClasses;

        var collectionHelper = __dependency9__["default"];
        var ViewHelper = __dependency10__.ViewHelper;
        var viewHelper = __dependency10__.viewHelper;
        var unboundHelper = __dependency11__["default"];
        var logHelper = __dependency12__.logHelper;
        var debuggerHelper = __dependency12__.debuggerHelper;
        var EachView = __dependency13__.EachView;
        var GroupedEach = __dependency13__.GroupedEach;
        var eachHelper = __dependency13__.eachHelper;
        var templateHelper = __dependency14__["default"];
        var partialHelper = __dependency15__["default"];
        var yieldHelper = __dependency16__["default"];
        var locHelper = __dependency17__["default"];


        var Checkbox = __dependency18__["default"];
        var Select = __dependency19__.Select;
        var SelectOption = __dependency19__.SelectOption;
        var SelectOptgroup = __dependency19__.SelectOptgroup;
        var TextArea = __dependency20__["default"];
        var TextField = __dependency21__["default"];
        var TextSupport = __dependency22__["default"];
        var inputHelper = __dependency23__.inputHelper;
        var textareaHelper = __dependency23__.textareaHelper;


        var ComponentLookup = __dependency24__["default"];
        var _HandlebarsBoundView = __dependency25__._HandlebarsBoundView;
        var SimpleHandlebarsView = __dependency25__.SimpleHandlebarsView;
        var _wrapMap = __dependency26__._wrapMap;
        var _SimpleMetamorphView = __dependency26__._SimpleMetamorphView;
        var _MetamorphView = __dependency26__._MetamorphView;
        var _Metamorph = __dependency26__._Metamorph;


        /**
            Ember Handlebars

            @module ember
            @submodule ember-handlebars
            @requires ember-views
            */

        // Ember.Handlebars.Globals
        EmberHandlebars.bootstrap = bootstrap;
        EmberHandlebars.template = template;
        EmberHandlebars.makeBoundHelper = makeBoundHelper;
        EmberHandlebars.registerBoundHelper = registerBoundHelper;
        EmberHandlebars.resolveHash = resolveHash;
        EmberHandlebars.resolveParams = resolveParams;
        EmberHandlebars.resolveHelper = resolveHelper;
        EmberHandlebars.get = handlebarsGet;
        EmberHandlebars.getEscaped = getEscaped;
        EmberHandlebars.evaluateUnboundHelper = evaluateUnboundHelper;
        EmberHandlebars.bind = bind;
        EmberHandlebars.bindClasses = bindClasses;
        EmberHandlebars.EachView = EachView;
        EmberHandlebars.GroupedEach = GroupedEach;
        EmberHandlebars.resolvePaths = resolvePaths;
        EmberHandlebars.ViewHelper = ViewHelper;
        EmberHandlebars.normalizePath = normalizePath;


        // Ember Globals
        Ember.Handlebars = EmberHandlebars;
        Ember.ComponentLookup = ComponentLookup;
        Ember._SimpleHandlebarsView = SimpleHandlebarsView;
        Ember._HandlebarsBoundView = _HandlebarsBoundView;
        Ember._SimpleMetamorphView = _SimpleMetamorphView;
        Ember._MetamorphView = _MetamorphView;
        Ember._Metamorph = _Metamorph;
        Ember._metamorphWrapMap = _wrapMap;
        Ember.TextSupport = TextSupport;
        Ember.Checkbox = Checkbox;
        Ember.Select = Select;
        Ember.SelectOption = SelectOption;
        Ember.SelectOptgroup = SelectOptgroup;
        Ember.TextArea = TextArea;
        Ember.TextField = TextField;
        Ember.TextSupport = TextSupport;

        // register helpers
        EmberHandlebars.registerHelper('helperMissing', helperMissingHelper);
        EmberHandlebars.registerHelper('blockHelperMissing', blockHelperMissingHelper);
        EmberHandlebars.registerHelper('bind', bindHelper);
        EmberHandlebars.registerHelper('boundIf', boundIfHelper);
        EmberHandlebars.registerHelper('_triageMustache', _triageMustacheHelper);
        EmberHandlebars.registerHelper('unboundIf', unboundIfHelper);
        EmberHandlebars.registerHelper('with', withHelper);
        EmberHandlebars.registerHelper('if', ifHelper);
        EmberHandlebars.registerHelper('unless', unlessHelper);
        EmberHandlebars.registerHelper('bind-attr', bindAttrHelper);
        EmberHandlebars.registerHelper('bindAttr', bindAttrHelperDeprecated);
        EmberHandlebars.registerHelper('collection', collectionHelper);
        EmberHandlebars.registerHelper("log", logHelper);
        EmberHandlebars.registerHelper("debugger", debuggerHelper);
        EmberHandlebars.registerHelper("each", eachHelper);
        EmberHandlebars.registerHelper("loc", locHelper);
        EmberHandlebars.registerHelper("partial", partialHelper);
        EmberHandlebars.registerHelper("template", templateHelper);
        EmberHandlebars.registerHelper("yield", yieldHelper);
        EmberHandlebars.registerHelper("view", viewHelper);
        EmberHandlebars.registerHelper("unbound", unboundHelper);
        EmberHandlebars.registerHelper("input", inputHelper);
        EmberHandlebars.registerHelper("textarea", textareaHelper);

        // run load hooks
        runLoadHooks('Ember.Handlebars', EmberHandlebars);

        __exports__["default"] = EmberHandlebars;
    });
    define("ember-handlebars/component_lookup",
    ["ember-runtime/system/object", "exports"],
    function(__dependency1__, __exports__) {
        "use strict";
        var EmberObject = __dependency1__["default"];

        var ComponentLookup = EmberObject.extend({
            lookupFactory: function(name, container) {

                container = container || this.container;

                var fullName = 'component:' + name,
                templateFullName = 'template:components/' + name,
                templateRegistered = container && container.has(templateFullName);

                if (templateRegistered) {
                    container.injection(fullName, 'layout', templateFullName);
                }

                var Component = container.lookupFactory(fullName);

                // Only treat as a component if either the component
                // or a template has been registered.
                if (templateRegistered || Component) {
                    if (!Component) {
                        container.register(fullName, Ember.Component);
                        Component = container.lookupFactory(fullName);
                    }
                    return Component;
                }
            }
        });

        __exports__["default"] = ComponentLookup;
    });
    define("ember-handlebars/controls",
    ["ember-handlebars/controls/checkbox", "ember-handlebars/controls/text_field", "ember-handlebars/controls/text_area", "ember-metal/core", "ember-handlebars-compiler", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
        "use strict";
        var Checkbox = __dependency1__["default"];
        var TextField = __dependency2__["default"];
        var TextArea = __dependency3__["default"];

        var Ember = __dependency4__["default"];
        // Ember.assert
        // var emberAssert = Ember.assert;

        var EmberHandlebars = __dependency5__["default"];
        var helpers = EmberHandlebars.helpers;
        /**
            @module ember
            @submodule ember-handlebars-compiler
            */

        /**

              The `{{input}}` helper inserts an HTML `<input>` tag into the template,
              with a `type` value of either `text` or `checkbox`. If no `type` is provided,
              `text` will be the default value applied. The attributes of `{{input}}`
              match those of the native HTML tag as closely as possible for these two types.

              ## Use as text field
              An `{{input}}` with no `type` or a `type` of `text` will render an HTML text input.
              The following HTML attributes can be set via the helper:

             <table>
              <tr><td>`readonly`</td><td>`required`</td><td>`autofocus`</td></tr>
              <tr><td>`value`</td><td>`placeholder`</td><td>`disabled`</td></tr>
              <tr><td>`size`</td><td>`tabindex`</td><td>`maxlength`</td></tr>
              <tr><td>`name`</td><td>`min`</td><td>`max`</td></tr>
              <tr><td>`pattern`</td><td>`accept`</td><td>`autocomplete`</td></tr>
              <tr><td>`autosave`</td><td>`formaction`</td><td>`formenctype`</td></tr>
              <tr><td>`formmethod`</td><td>`formnovalidate`</td><td>`formtarget`</td></tr>
              <tr><td>`height`</td><td>`inputmode`</td><td>`multiple`</td></tr>
              <tr><td>`step`</td><td>`width`</td><td>`form`</td></tr>
              <tr><td>`selectionDirection`</td><td>`spellcheck`</td><td>&nbsp;</td></tr>
             </table>


              When set to a quoted string, these values will be directly applied to the HTML
              element. When left unquoted, these values will be bound to a property on the
              template's current rendering context (most typically a controller instance).

              ## Unbound:

              ```handlebars
              {{input value="http://www.facebook.com"}}
              ```


              ```html
              <input type="text" value="http://www.facebook.com"/>
              ```

              ## Bound:

              ```javascript
              App.ApplicationController = Ember.Controller.extend({
                firstName: "Stanley",
                entryNotAllowed: true
              });
              ```


              ```handlebars
              {{input type="text" value=firstName disabled=entryNotAllowed size="50"}}
              ```


              ```html
              <input type="text" value="Stanley" disabled="disabled" size="50"/>
              ```

              ## Actions

              The helper can send multiple actions based on user events.

              The action property defines the action which is send when
              the user presses the return key.

              ```handlebars
              {{input action="submit"}}
              ```

              The helper allows some user events to send actions.

            * `enter`
            * `insert-newline`
            * `escape-press`
            * `focus-in`
            * `focus-out`
            * `key-press`

              For example, if you desire an action to be sent when the input is blurred,
              you only need to setup the action name to the event name property.

              ```handlebars
              {{input focus-in="alertMessage"}}
              ```

              See more about [Text Support Actions](api/classes/Ember.TextField.html)

              ## Extension

              Internally, `{{input type="text"}}` creates an instance of `Ember.TextField`, passing
              arguments from the helper to `Ember.TextField`'s `create` method. You can extend the
              capabilities of text inputs in your applications by reopening this class. For example,
              if you are building a Bootstrap project where `data-*` attributes are used, you
              can add one to the `TextField`'s `attributeBindings` property:


              ```javascript
              Ember.TextField.reopen({
                attributeBindings: ['data-error']
              });
              ```

              Keep in mind when writing `Ember.TextField` subclasses that `Ember.TextField`
              itself extends `Ember.Component`, meaning that it does NOT inherit
              the `controller` of the parent view.

              See more about [Ember components](api/classes/Ember.Component.html)


              ## Use as checkbox

              An `{{input}}` with a `type` of `checkbox` will render an HTML checkbox input.
              The following HTML attributes can be set via the helper:

            * `checked`
            * `disabled`
            * `tabindex`
            * `indeterminate`
            * `name`
            * `autofocus`
            * `form`


              When set to a quoted string, these values will be directly applied to the HTML
              element. When left unquoted, these values will be bound to a property on the
              template's current rendering context (most typically a controller instance).

              ## Unbound:

              ```handlebars
              {{input type="checkbox" name="isAdmin"}}
              ```

              ```html
              <input type="checkbox" name="isAdmin" />
              ```

              ## Bound:

              ```javascript
              App.ApplicationController = Ember.Controller.extend({
                isAdmin: true
              });
              ```


              ```handlebars
              {{input type="checkbox" checked=isAdmin }}
              ```


              ```html
              <input type="checkbox" checked="checked" />
              ```

              ## Extension

              Internally, `{{input type="checkbox"}}` creates an instance of `Ember.Checkbox`, passing
              arguments from the helper to `Ember.Checkbox`'s `create` method. You can extend the
              capablilties of checkbox inputs in your applications by reopening this class. For example,
              if you wanted to add a css class to all checkboxes in your application:


              ```javascript
              Ember.Checkbox.reopen({
                classNames: ['my-app-checkbox']
              });
              ```


              @method input
              @for Ember.Handlebars.helpers
              @param {Hash} options
            */
        function inputHelper(options) {
            Ember.assert('You can only pass attributes to the `input` helper, not arguments', arguments.length < 2);

            var hash = options.hash,
            types = options.hashTypes,
            inputType = hash.type,
            onEvent = hash.on;

            delete hash.type;
            delete hash.on;

            if (inputType === 'checkbox') {
                Ember.assert("{{input type='checkbox'}} does not support setting `value=someBooleanValue`; you must use `checked=someBooleanValue` instead.", options.hashTypes.value !== 'ID');
                return helpers.view.call(this, Checkbox, options);
            } else {
                if (inputType) {
                    hash.type = inputType;
                }
                hash.onEvent = onEvent || 'enter';
                return helpers.view.call(this, TextField, options);
            }
        }

        __exports__.inputHelper = inputHelper; /**
              `{{textarea}}` inserts a new instance of `<textarea>` tag into the template.
              The attributes of `{{textarea}}` match those of the native HTML tags as
              closely as possible.

              The following HTML attributes can be set:

                * `value`
                * `name`
                * `rows`
                * `cols`
                * `placeholder`
                * `disabled`
                * `maxlength`
                * `tabindex`
                * `selectionEnd`
                * `selectionStart`
                * `selectionDirection`
                * `wrap`
                * `readonly`
                * `autofocus`
                * `form`
                * `spellcheck`
                * `required`

              When set to a quoted string, these value will be directly applied to the HTML
              element. When left unquoted, these values will be bound to a property on the
              template's current rendering context (most typically a controller instance).

              Unbound:

              ```handlebars
              {{textarea value="Lots of static text that ISN'T bound"}}
              ```

              Would result in the following HTML:

              ```html
              <textarea class="ember-text-area">
                Lots of static text that ISN'T bound
              </textarea>
              ```

              Bound:

              In the following example, the `writtenWords` property on `App.ApplicationController`
              will be updated live as the user types 'Lots of text that IS bound' into
              the text area of their browser's window.

              ```javascript
              App.ApplicationController = Ember.Controller.extend({
                writtenWords: "Lots of text that IS bound"
              });
              ```

              ```handlebars
              {{textarea value=writtenWords}}
              ```

               Would result in the following HTML:

              ```html
              <textarea class="ember-text-area">
                Lots of text that IS bound
              </textarea>
              ```

              If you wanted a one way binding between the text area and a div tag
              somewhere else on your screen, you could use `Ember.computed.oneWay`:

              ```javascript
              App.ApplicationController = Ember.Controller.extend({
                writtenWords: "Lots of text that IS bound",
                outputWrittenWords: Ember.computed.oneWay("writtenWords")
              });
              ```

              ```handlebars
              {{textarea value=writtenWords}}

              <div>
                {{outputWrittenWords}}
              </div>
              ```

              Would result in the following HTML:

              ```html
              <textarea class="ember-text-area">
                Lots of text that IS bound
              </textarea>

              <-- the following div will be updated in real time as you type -->

              <div>
                Lots of text that IS bound
              </div>
              ```

              Finally, this example really shows the power and ease of Ember when two
              properties are bound to eachother via `Ember.computed.alias`. Type into
              either text area box and they'll both stay in sync. Note that
              `Ember.computed.alias` costs more in terms of performance, so only use it when
              your really binding in both directions:

              ```javascript
              App.ApplicationController = Ember.Controller.extend({
                writtenWords: "Lots of text that IS bound",
                twoWayWrittenWords: Ember.computed.alias("writtenWords")
              });
              ```

              ```handlebars
              {{textarea value=writtenWords}}
              {{textarea value=twoWayWrittenWords}}
              ```

              ```html
              <textarea id="ember1" class="ember-text-area">
                Lots of text that IS bound
              </textarea>

              <-- both updated in real time -->

              <textarea id="ember2" class="ember-text-area">
                Lots of text that IS bound
              </textarea>
              ```

              ## Actions

              The helper can send multiple actions based on user events.

              The action property defines the action which is send when
              the user presses the return key.

              ```handlebars
              {{input action="submit"}}
              ```

              The helper allows some user events to send actions.

            * `enter`
            * `insert-newline`
            * `escape-press`
            * `focus-in`
            * `focus-out`
            * `key-press`

              For example, if you desire an action to be sent when the input is blurred,
              you only need to setup the action name to the event name property.

              ```handlebars
              {{textarea focus-in="alertMessage"}}
              ```

              See more about [Text Support Actions](api/classes/Ember.TextArea.html)

              ## Extension

              Internally, `{{textarea}}` creates an instance of `Ember.TextArea`, passing
              arguments from the helper to `Ember.TextArea`'s `create` method. You can
              extend the capabilities of text areas in your application by reopening this
              class. For example, if you are building a Bootstrap project where `data-*` 
              attributes are used, you can globally add support for a `data-*` attribute
              on all `{{textarea}}`s' in your app by reopening `Ember.TextArea` or
              `Ember.TextSupport` and adding it to the `attributeBindings` concatenated
              property:

              ```javascript
              Ember.TextArea.reopen({
                attributeBindings: ['data-error']
              });
              ```

              Keep in mind when writing `Ember.TextArea` subclasses that `Ember.TextArea`
              itself extends `Ember.Component`, meaning that it does NOT inherit
              the `controller` of the parent view.

              See more about [Ember components](api/classes/Ember.Component.html)

              @method textarea
              @for Ember.Handlebars.helpers
              @param {Hash} options
            */
        function textareaHelper(options) {
            Ember.assert('You can only pass attributes to the `textarea` helper, not arguments', arguments.length < 2);

            var hash = options.hash,
            types = options.hashTypes;

            return helpers.view.call(this, TextArea, options);
        }

        __exports__.textareaHelper = textareaHelper;
    });
    define("ember-handlebars/controls/checkbox",
    ["ember-metal/property_get", "ember-metal/property_set", "ember-views/views/view", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        var get = __dependency1__.get;
        var set = __dependency2__.set;
        var View = __dependency3__["default"];

        /**
            @module ember
            @submodule ember-handlebars
            */

        /**
              The internal class used to create text inputs when the `{{input}}`
              helper is used with `type` of `checkbox`.

              See [handlebars.helpers.input](/api/classes/Ember.Handlebars.helpers.html#method_input)  for usage details.

              ## Direct manipulation of `checked`

              The `checked` attribute of an `Ember.Checkbox` object should always be set
              through the Ember object or by interacting with its rendered element
              representation via the mouse, keyboard, or touch. Updating the value of the
              checkbox via jQuery will result in the checked value of the object and its
              element losing synchronization.

              ## Layout and LayoutName properties

              Because HTML `input` elements are self closing `layout` and `layoutName`
              properties will not be applied. See [Ember.View](/api/classes/Ember.View.html)'s
              layout section for more information.

              @class Checkbox
              @namespace Ember
              @extends Ember.View
            */
        __exports__["default"] = View.extend({
            instrumentDisplay: '{{input type="checkbox"}}',

            classNames: ['ember-checkbox'],

            tagName: 'input',

            attributeBindings: [
            'type',
            'checked',
            'indeterminate',
            'disabled',
            'tabindex',
            'name',
            'autofocus',
            'required',
            'form'
            ],

            type: 'checkbox',
            checked: false,
            disabled: false,
            indeterminate: false,

            init: function() {
                this._super();
                this.on('change', this, this._updateElementValue);
            },

            didInsertElement: function() {
                this._super();
                get(this, 'element').indeterminate = !!get(this, 'indeterminate');
            },

            _updateElementValue: function() {
                set(this, 'checked', this.$().prop('checked'));
            }
        });
    });
    define("ember-handlebars/controls/select",
    ["ember-handlebars-compiler", "ember-metal/enumerable_utils", "ember-metal/property_get", "ember-metal/property_set", "ember-views/views/view", "ember-views/views/collection_view", "ember-metal/utils", "ember-metal/is_none", "ember-metal/computed", "ember-runtime/system/native_array", "ember-metal/mixin", "ember-metal/properties", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-handlebars
            */

        var EmberHandlebars = __dependency1__["default"];

        var forEach = __dependency2__.forEach;
        var indexOf = __dependency2__.indexOf;
        var indexesOf = __dependency2__.indexesOf;
        var replace = __dependency2__.replace;

        var get = __dependency3__.get;
        var set = __dependency4__.set;
        var View = __dependency5__["default"];
        var CollectionView = __dependency6__["default"];
        var isArray = __dependency7__.isArray;
        var isNone = __dependency8__["default"];
        var computed = __dependency9__.computed;
        var emberA = __dependency10__.A;
        var observer = __dependency11__.observer;
        var defineProperty = __dependency12__.defineProperty;

        var precompileTemplate = EmberHandlebars.compile;

        var SelectOption = View.extend({
            instrumentDisplay: 'Ember.SelectOption',

            tagName: 'option',
            attributeBindings: ['value', 'selected'],

            defaultTemplate: function(context, options) {
                options = {
                    data: options.data,
                    hash: {}
                };
                EmberHandlebars.helpers.bind.call(context, "view.label", options);
            },

            init: function() {
                this.labelPathDidChange();
                this.valuePathDidChange();

                this._super();
            },

            selected: computed(function() {
                var content = get(this, 'content'),
                selection = get(this, 'parentView.selection');
                if (get(this, 'parentView.multiple')) {
                    return selection && indexOf(selection, content.valueOf()) > -1;
                } else {
                    // Primitives get passed through bindings as objects... since
                    // `new Number(4) !== 4`, we use `==` below
                    return content == selection; // jshint ignore:line
                }
            }).property('content', 'parentView.selection'),

            labelPathDidChange: observer('parentView.optionLabelPath', function() {
                var labelPath = get(this, 'parentView.optionLabelPath');

                if (!labelPath) {
                    return;
                }

                defineProperty(this, 'label', computed(function() {
                    return get(this, labelPath);
                }).property(labelPath));
            }),

            valuePathDidChange: observer('parentView.optionValuePath', function() {
                var valuePath = get(this, 'parentView.optionValuePath');

                if (!valuePath) {
                    return;
                }

                defineProperty(this, 'value', computed(function() {
                    return get(this, valuePath);
                }).property(valuePath));
            })
        });

        var SelectOptgroup = CollectionView.extend({
            instrumentDisplay: 'Ember.SelectOptgroup',

            tagName: 'optgroup',
            attributeBindings: ['label'],

            selectionBinding: 'parentView.selection',
            multipleBinding: 'parentView.multiple',
            optionLabelPathBinding: 'parentView.optionLabelPath',
            optionValuePathBinding: 'parentView.optionValuePath',

            itemViewClassBinding: 'parentView.optionView'
        });

        /**
              The `Ember.Select` view class renders a
              [select](https://developer.mozilla.org/en/HTML/Element/select) HTML element,
              allowing the user to choose from a list of options.

              The text and `value` property of each `<option>` element within the
              `<select>` element are populated from the objects in the `Element.Select`'s
              `content` property. The underlying data object of the selected `<option>` is
              stored in the `Element.Select`'s `value` property.

              ## The Content Property (array of strings)

              The simplest version of an `Ember.Select` takes an array of strings as its
              `content` property. The string will be used as both the `value` property and
              the inner text of each `<option>` element inside the rendered `<select>`.

              Example:

              ```javascript
              App.ApplicationController = Ember.ObjectController.extend({
                names: ["Yehuda", "Tom"]
              });
              ```

              ```handlebars
              {{view Ember.Select content=names}}
              ```

              Would result in the following HTML:

              ```html
              <select class="ember-select">
                <option value="Yehuda">Yehuda</option>
                <option value="Tom">Tom</option>
              </select>
              ```

              You can control which `<option>` is selected through the `Ember.Select`'s
              `value` property:

              ```javascript
              App.ApplicationController = Ember.ObjectController.extend({
                selectedName: 'Tom',
                names: ["Yehuda", "Tom"]
              });
              ```

              ```handlebars
              {{view Ember.Select
                     content=names
                     value=selectedName
              }}
              ```

              Would result in the following HTML with the `<option>` for 'Tom' selected:

              ```html
              <select class="ember-select">
                <option value="Yehuda">Yehuda</option>
                <option value="Tom" selected="selected">Tom</option>
              </select>
              ```

              A user interacting with the rendered `<select>` to choose "Yehuda" would
              update the value of `selectedName` to "Yehuda".

              ## The Content Property (array of Objects)

              An `Ember.Select` can also take an array of JavaScript or Ember objects as
              its `content` property.

              When using objects you need to tell the `Ember.Select` which property should
              be accessed on each object to supply the `value` attribute of the `<option>`
              and which property should be used to supply the element text.

              The `optionValuePath` option is used to specify the path on each object to
              the desired property for the `value` attribute. The `optionLabelPath`
              specifies the path on each object to the desired property for the
              element's text. Both paths must reference each object itself as `content`:

              ```javascript
              App.ApplicationController = Ember.ObjectController.extend({
                programmers: [
                  {firstName: "Yehuda", id: 1},
                  {firstName: "Tom",    id: 2}
                ]
              });
              ```

              ```handlebars
              {{view Ember.Select
                     content=programmers
                     optionValuePath="content.id"
                     optionLabelPath="content.firstName"}}
              ```

              Would result in the following HTML:

              ```html
              <select class="ember-select">
                <option value="1">Yehuda</option>
                <option value="2">Tom</option>
              </select>
              ```

              The `value` attribute of the selected `<option>` within an `Ember.Select`
              can be bound to a property on another object:

              ```javascript
              App.ApplicationController = Ember.ObjectController.extend({
                programmers: [
                  {firstName: "Yehuda", id: 1},
                  {firstName: "Tom",    id: 2}
                ],
                currentProgrammer: {
                  id: 2
                }
              });
              ```

              ```handlebars
              {{view Ember.Select
                     content=programmers
                     optionValuePath="content.id"
                     optionLabelPath="content.firstName"
                     value=currentProgrammer.id}}
              ```

              Would result in the following HTML with a selected option:

              ```html
              <select class="ember-select">
                <option value="1">Yehuda</option>
                <option value="2" selected="selected">Tom</option>
              </select>
              ```

              Interacting with the rendered element by selecting the first option
              ('Yehuda') will update the `id` of `currentProgrammer`
              to match the `value` property of the newly selected `<option>`.

              Alternatively, you can control selection through the underlying objects
              used to render each object by binding the `selection` option. When the selected
              `<option>` is changed, the property path provided to `selection`
              will be updated to match the content object of the rendered `<option>`
              element:

              ```javascript

              var yehuda = {firstName: "Yehuda", id: 1, bff4eva: 'tom'}
              var tom = {firstName: "Tom", id: 2, bff4eva: 'yehuda'};

              App.ApplicationController = Ember.ObjectController.extend({
                selectedPerson: tom,
                programmers: [
                  yehuda,
                  tom
                ]
              });
              ```

              ```handlebars
              {{view Ember.Select
                     content=programmers
                     optionValuePath="content.id"
                     optionLabelPath="content.firstName"
                     selection=selectedPerson}}
              ```

              Would result in the following HTML with a selected option:

              ```html
              <select class="ember-select">
                <option value="1">Yehuda</option>
                <option value="2" selected="selected">Tom</option>
              </select>
              ```

              Interacting with the rendered element by selecting the first option
              ('Yehuda') will update the `selectedPerson` to match the object of
              the newly selected `<option>`. In this case it is the first object
              in the `programmers`

              ## Supplying a Prompt

              A `null` value for the `Ember.Select`'s `value` or `selection` property
              results in there being no `<option>` with a `selected` attribute:

              ```javascript
              App.ApplicationController = Ember.ObjectController.extend({
                selectedProgrammer: null,
                programmers: [
                  "Yehuda",
                  "Tom"
                ]
              });
              ```

              ``` handlebars
              {{view Ember.Select
                     content=programmers
                     value=selectedProgrammer
              }}
              ```

              Would result in the following HTML:

              ```html
              <select class="ember-select">
                <option value="Yehuda">Yehuda</option>
                <option value="Tom">Tom</option>
              </select>
              ```

              Although `selectedProgrammer` is `null` and no `<option>`
              has a `selected` attribute the rendered HTML will display the
              first item as though it were selected. You can supply a string
              value for the `Ember.Select` to display when there is no selection
              with the `prompt` option:

              ```javascript
              App.ApplicationController = Ember.ObjectController.extend({
                selectedProgrammer: null,
                programmers: [
                  "Yehuda",
                  "Tom"
                ]
              });
              ```

              ```handlebars
              {{view Ember.Select
                     content=programmers
                     value=selectedProgrammer
                     prompt="Please select a name"
              }}
              ```

              Would result in the following HTML:

              ```html
              <select class="ember-select">
                <option>Please select a name</option>
                <option value="Yehuda">Yehuda</option>
                <option value="Tom">Tom</option>
              </select>
              ```

              @class Select
              @namespace Ember
              @extends Ember.View
            */
        var Select = View.extend({
            instrumentDisplay: 'Ember.Select',

            tagName: 'select',
            classNames: ['ember-select'],
            defaultTemplate: Ember.Handlebars.template(function anonymous(Handlebars, depth0, helpers, partials, data) {
                this.compilerInfo = [4, '>= 1.0.0'];
                helpers = this.merge(helpers, Ember.Handlebars.helpers);
                data = data || {};
                var buffer = '', stack1, escapeExpression = this.escapeExpression, self = this;

                function program1(depth0, data) {

                    var buffer = '', stack1;
                    data.buffer.push("<option value=\"\">");
                    stack1 = helpers._triageMustache.call(depth0, "view.prompt", {
                        hash: {},
                        hashTypes: {},
                        hashContexts: {},
                        contexts: [depth0],
                        types: ["ID"],
                        data: data
                    });
                    if (stack1 || stack1 === 0) {
                        data.buffer.push(stack1);
                    }
                    data.buffer.push("</option>");
                    return buffer;
                }

                function program3(depth0, data) {

                    var stack1;
                    stack1 = helpers.each.call(depth0, "view.groupedContent", {
                        hash: {},
                        hashTypes: {},
                        hashContexts: {},
                        inverse: self.noop,
                        fn: self.program(4, program4, data),
                        contexts: [depth0],
                        types: ["ID"],
                        data: data
                    });
                    if (stack1 || stack1 === 0) {
                        data.buffer.push(stack1);
                    } else {
                        data.buffer.push('');
                    }
                }
                function program4(depth0, data) {


                    data.buffer.push(escapeExpression(helpers.view.call(depth0, "view.groupView", {
                        hash: {
                            'content': ("content"),
                            'label': ("label")
                        },
                        hashTypes: {
                            'content': "ID",
                            'label': "ID"
                        },
                        hashContexts: {
                            'content': depth0,
                            'label': depth0
                        },
                        contexts: [depth0],
                        types: ["ID"],
                        data: data
                    })));
                }

                function program6(depth0, data) {

                    var stack1;
                    stack1 = helpers.each.call(depth0, "view.content", {
                        hash: {},
                        hashTypes: {},
                        hashContexts: {},
                        inverse: self.noop,
                        fn: self.program(7, program7, data),
                        contexts: [depth0],
                        types: ["ID"],
                        data: data
                    });
                    if (stack1 || stack1 === 0) {
                        data.buffer.push(stack1);
                    } else {
                        data.buffer.push('');
                    }
                }
                function program7(depth0, data) {


                    data.buffer.push(escapeExpression(helpers.view.call(depth0, "view.optionView", {
                        hash: {
                            'content': ("")
                        },
                        hashTypes: {
                            'content': "ID"
                        },
                        hashContexts: {
                            'content': depth0
                        },
                        contexts: [depth0],
                        types: ["ID"],
                        data: data
                    })));
                }

                stack1 = helpers['if'].call(depth0, "view.prompt", {
                    hash: {},
                    hashTypes: {},
                    hashContexts: {},
                    inverse: self.noop,
                    fn: self.program(1, program1, data),
                    contexts: [depth0],
                    types: ["ID"],
                    data: data
                });
                if (stack1 || stack1 === 0) {
                    data.buffer.push(stack1);
                }
                stack1 = helpers['if'].call(depth0, "view.optionGroupPath", {
                    hash: {},
                    hashTypes: {},
                    hashContexts: {},
                    inverse: self.program(6, program6, data),
                    fn: self.program(3, program3, data),
                    contexts: [depth0],
                    types: ["ID"],
                    data: data
                });
                if (stack1 || stack1 === 0) {
                    data.buffer.push(stack1);
                }
                return buffer;

            }),
            attributeBindings: ['multiple', 'disabled', 'tabindex', 'name', 'required', 'autofocus',
            'form', 'size'],

            /**
                    The `multiple` attribute of the select element. Indicates whether multiple
                    options can be selected.

                    @property multiple
                    @type Boolean
                    @default false
                  */
            multiple: false,

            /**
                    The `disabled` attribute of the select element. Indicates whether
                    the element is disabled from interactions.

                    @property disabled
                    @type Boolean
                    @default false
                  */
            disabled: false,

            /**
                    The `required` attribute of the select element. Indicates whether
                    a selected option is required for form validation.

                    @property required
                    @type Boolean
                    @default false
                    @since 1.5.0
                  */
            required: false,

            /**
                    The list of options.

                    If `optionLabelPath` and `optionValuePath` are not overridden, this should
                    be a list of strings, which will serve simultaneously as labels and values.

                    Otherwise, this should be a list of objects. For instance:

                    ```javascript
                    Ember.Select.create({
                      content: Ember.A([
                          { id: 1, firstName: 'Yehuda' },
                          { id: 2, firstName: 'Tom' }
                        ]),
                      optionLabelPath: 'content.firstName',
                      optionValuePath: 'content.id'
                    });
                    ```

                    @property content
                    @type Array
                    @default null
                  */
            content: null,

            /**
                    When `multiple` is `false`, the element of `content` that is currently
                    selected, if any.

                    When `multiple` is `true`, an array of such elements.

                    @property selection
                    @type Object or Array
                    @default null
                  */
            selection: null,

            /**
                    In single selection mode (when `multiple` is `false`), value can be used to
                    get the current selection's value or set the selection by it's value.

                    It is not currently supported in multiple selection mode.

                    @property value
                    @type String
                    @default null
                  */
            value: computed(function(key, value) {
                if (arguments.length === 2) {
                    return value;
                }
                var valuePath = get(this, 'optionValuePath').replace(/^content\.?/, '');
                return valuePath ? get(this, 'selection.' + valuePath) : get(this, 'selection');
            }).property('selection'),

            /**
                    If given, a top-most dummy option will be rendered to serve as a user
                    prompt.

                    @property prompt
                    @type String
                    @default null
                  */
            prompt: null,

            /**
                    The path of the option labels. See [content](/api/classes/Ember.Select.html#property_content).

                    @property optionLabelPath
                    @type String
                    @default 'content'
                  */
            optionLabelPath: 'content',

            /**
                    The path of the option values. See [content](/api/classes/Ember.Select.html#property_content).

                    @property optionValuePath
                    @type String
                    @default 'content'
                  */
            optionValuePath: 'content',

            /**
                    The path of the option group.
                    When this property is used, `content` should be sorted by `optionGroupPath`.

                    @property optionGroupPath
                    @type String
                    @default null
                  */
            optionGroupPath: null,

            /**
                    The view class for optgroup.

                    @property groupView
                    @type Ember.View
                    @default Ember.SelectOptgroup
                  */
            groupView: SelectOptgroup,

            groupedContent: computed(function() {
                var groupPath = get(this, 'optionGroupPath');
                var groupedContent = emberA();
                var content = get(this, 'content') || [];

                forEach(content, function(item) {
                    var label = get(item, groupPath);

                    if (get(groupedContent, 'lastObject.label') !== label) {
                        groupedContent.pushObject({
                            label: label,
                            content: emberA()
                        });
                    }

                    get(groupedContent, 'lastObject.content').push(item);
                });

                return groupedContent;
            }).property('optionGroupPath', 'content.@each'),

            /**
                    The view class for option.

                    @property optionView
                    @type Ember.View
                    @default Ember.SelectOption
                  */
            optionView: SelectOption,

            _change: function() {
                if (get(this, 'multiple')) {
                    this._changeMultiple();
                } else {
                    this._changeSingle();
                }
            },

            selectionDidChange: observer('selection.@each', function() {
                var selection = get(this, 'selection');
                if (get(this, 'multiple')) {
                    if (!isArray(selection)) {
                        set(this, 'selection', emberA([selection]));
                        return;
                    }
                    this._selectionDidChangeMultiple();
                } else {
                    this._selectionDidChangeSingle();
                }
            }),

            valueDidChange: observer('value', function() {
                var content = get(this, 'content'),
                value = get(this, 'value'),
                valuePath = get(this, 'optionValuePath').replace(/^content\.?/, ''),
                selectedValue = (valuePath ? get(this, 'selection.' + valuePath) : get(this, 'selection')),
                selection;

                if (value !== selectedValue) {
                    selection = content ? content.find(function(obj) {
                        return value === (valuePath ? get(obj, valuePath) : obj);
                    }) : null;

                    this.set('selection', selection);
                }
            }),


            _triggerChange: function() {
                var selection = get(this, 'selection');
                var value = get(this, 'value');

                if (!isNone(selection)) {
                    this.selectionDidChange();
                }
                if (!isNone(value)) {
                    this.valueDidChange();
                }

                this._change();
            },

            _changeSingle: function() {
                var selectedIndex = this.$()[0].selectedIndex,
                content = get(this, 'content'),
                prompt = get(this, 'prompt');

                if (!content || !get(content, 'length')) {
                    return;
                }
                if (prompt && selectedIndex === 0) {
                    set(this, 'selection', null);
                    return;
                }

                if (prompt) {
                    selectedIndex -= 1;
                }
                set(this, 'selection', content.objectAt(selectedIndex));
            },


            _changeMultiple: function() {
                var options = this.$('option:selected'),
                prompt = get(this, 'prompt'),
                offset = prompt ? 1 : 0,
                content = get(this, 'content'),
                selection = get(this, 'selection');

                if (!content) {
                    return;
                }
                if (options) {
                    var selectedIndexes = options.map(function() {
                        return this.index - offset;
                    }).toArray();
                    var newSelection = content.objectsAt(selectedIndexes);

                    if (isArray(selection)) {
                        replace(selection, 0, get(selection, 'length'), newSelection);
                    } else {
                        set(this, 'selection', newSelection);
                    }
                }
            },

            _selectionDidChangeSingle: function() {
                var el = this.get('element');
                if (!el) {
                    return;
                }

                var content = get(this, 'content'),
                selection = get(this, 'selection'),
                selectionIndex = content ? indexOf(content, selection) : -1,
                prompt = get(this, 'prompt');

                if (prompt) {
                    selectionIndex += 1;
                }
                if (el) {
                    el.selectedIndex = selectionIndex;
                }
            },

            _selectionDidChangeMultiple: function() {
                var content = get(this, 'content'),
                selection = get(this, 'selection'),
                selectedIndexes = content ? indexesOf(content, selection) : [-1],
                prompt = get(this, 'prompt'),
                offset = prompt ? 1 : 0,
                options = this.$('option'),
                adjusted;

                if (options) {
                    options.each(function() {
                        adjusted = this.index > -1 ? this.index - offset : -1;
                        this.selected = indexOf(selectedIndexes, adjusted) > -1;
                    });
                }
            },

            init: function() {
                this._super();
                this.on("didInsertElement", this, this._triggerChange);
                this.on("change", this, this._change);
            }
        });

        __exports__["default"] = Select;
        __exports__.Select = Select;
        __exports__.SelectOption = SelectOption;
        __exports__.SelectOptgroup = SelectOptgroup;
    });
    define("ember-handlebars/controls/text_area",
    ["ember-metal/property_get", "ember-views/views/component", "ember-handlebars/controls/text_support", "ember-metal/mixin", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
        "use strict";

        /**
            @module ember
            @submodule ember-handlebars
            */
        var get = __dependency1__.get;
        var Component = __dependency2__["default"];
        var TextSupport = __dependency3__["default"];
        var observer = __dependency4__.observer;

        /**
              The internal class used to create textarea element when the `{{textarea}}`
              helper is used.

              See [handlebars.helpers.textarea](/api/classes/Ember.Handlebars.helpers.html#method_textarea)  for usage details.

              ## Layout and LayoutName properties

              Because HTML `textarea` elements do not contain inner HTML the `layout` and
              `layoutName` properties will not be applied. See [Ember.View](/api/classes/Ember.View.html)'s
              layout section for more information.

              @class TextArea
              @namespace Ember
              @extends Ember.Component
              @uses Ember.TextSupport
            */
        __exports__["default"] = Component.extend(TextSupport, {
            instrumentDisplay: '{{textarea}}',

            classNames: ['ember-text-area'],

            tagName: "textarea",
            attributeBindings: ['rows', 'cols', 'name', 'selectionEnd', 'selectionStart', 'wrap'],
            rows: null,
            cols: null,

            _updateElementValue: observer('value', function() {
                // We do this check so cursor position doesn't get affected in IE
                var value = get(this, 'value'),
                $el = this.$();
                if ($el && value !== $el.val()) {
                    $el.val(value);
                }
            }),

            init: function() {
                this._super();
                this.on("didInsertElement", this, this._updateElementValue);
            }
        });
    });
    define("ember-handlebars/controls/text_field",
    ["ember-metal/property_get", "ember-metal/property_set", "ember-views/views/component", "ember-handlebars/controls/text_support", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-handlebars
            */

        var get = __dependency1__.get;
        var set = __dependency2__.set;
        var Component = __dependency3__["default"];
        var TextSupport = __dependency4__["default"];

        /**

              The internal class used to create text inputs when the `{{input}}`
              helper is used with `type` of `text`.

              See [Handlebars.helpers.input](/api/classes/Ember.Handlebars.helpers.html#method_input)  for usage details.

              ## Layout and LayoutName properties

              Because HTML `input` elements are self closing `layout` and `layoutName`
              properties will not be applied. See [Ember.View](/api/classes/Ember.View.html)'s
              layout section for more information.

              @class TextField
              @namespace Ember
              @extends Ember.Component
              @uses Ember.TextSupport
            */
        __exports__["default"] = Component.extend(TextSupport, {
            instrumentDisplay: '{{input type="text"}}',

            classNames: ['ember-text-field'],
            tagName: "input",
            attributeBindings: ['type', 'value', 'size', 'pattern', 'name', 'min', 'max',
            'accept', 'autocomplete', 'autosave', 'formaction',
            'formenctype', 'formmethod', 'formnovalidate', 'formtarget',
            'height', 'inputmode', 'list', 'multiple', 'step',
            'width'],

            /**
                    The `value` attribute of the input element. As the user inputs text, this
                    property is updated live.

                    @property value
                    @type String
                    @default ""
                  */
            value: "",

            /**
                    The `type` attribute of the input element.

                    @property type
                    @type String
                    @default "text"
                  */
            type: "text",

            /**
                    The `size` of the text field in characters.

                    @property size
                    @type String
                    @default null
                  */
            size: null,

            /**
                    The `pattern` attribute of input element.

                    @property pattern
                    @type String
                    @default null
                  */
            pattern: null,

            /**
                    The `min` attribute of input element used with `type="number"` or `type="range"`.

                    @property min
                    @type String
                    @default null
                    @since 1.4.0
                  */
            min: null,

            /**
                    The `max` attribute of input element used with `type="number"` or `type="range"`.

                    @property max
                    @type String
                    @default null
                    @since 1.4.0
                  */
            max: null
        });
    });
    define("ember-handlebars/controls/text_support",
    ["ember-metal/property_get", "ember-metal/property_set", "ember-metal/mixin", "ember-runtime/mixins/target_action_support", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-handlebars
            */

        var get = __dependency1__.get;
        var set = __dependency2__.set;
        var Mixin = __dependency3__.Mixin;
        var TargetActionSupport = __dependency4__["default"];

        /**
              Shared mixin used by `Ember.TextField` and `Ember.TextArea`.

              @class TextSupport
              @namespace Ember
              @uses Ember.TargetActionSupport
              @extends Ember.Mixin
              @private
            */
        var TextSupport = Mixin.create(TargetActionSupport, {
            value: "",

            attributeBindings: ['placeholder', 'disabled', 'maxlength', 'tabindex', 'readonly',
            'autofocus', 'form', 'selectionDirection', 'spellcheck', 'required',
            'title', 'autocapitalize', 'autocorrect'],
            placeholder: null,
            disabled: false,
            maxlength: null,

            init: function() {
                this._super();
                this.on("focusOut", this, this._elementValueDidChange);
                this.on("change", this, this._elementValueDidChange);
                this.on("paste", this, this._elementValueDidChange);
                this.on("cut", this, this._elementValueDidChange);
                this.on("input", this, this._elementValueDidChange);
                this.on("keyUp", this, this.interpretKeyEvents);
            },

            /**
                    The action to be sent when the user presses the return key.

                    This is similar to the `{{action}}` helper, but is fired when
                    the user presses the return key when editing a text field, and sends
                    the value of the field as the context.

                    @property action
                    @type String
                    @default null
                  */
            action: null,

            /**
                    The event that should send the action.

                    Options are:

                    * `enter`: the user pressed enter
                    * `keyPress`: the user pressed a key

                    @property onEvent
                    @type String
                    @default enter
                  */
            onEvent: 'enter',

            /**
                    Whether they `keyUp` event that triggers an `action` to be sent continues
                    propagating to other views.

                    By default, when the user presses the return key on their keyboard and
                    the text field has an `action` set, the action will be sent to the view's
                    controller and the key event will stop propagating.

                    If you would like parent views to receive the `keyUp` event even after an
                    action has been dispatched, set `bubbles` to true.

                    @property bubbles
                    @type Boolean
                    @default false
                  */
            bubbles: false,

            interpretKeyEvents: function(event) {
                var map = TextSupport.KEY_EVENTS;
                var method = map[event.keyCode];

                this._elementValueDidChange();
                if (method) {
                    return this[method](event);
                }
            },

            _elementValueDidChange: function() {
                set(this, 'value', this.$().val());
            },

            /**
                    Called when the user inserts a new line.

                    Called by the `Ember.TextSupport` mixin on keyUp if keycode matches 13.
                    Uses sendAction to send the `enter` action.

                    @method insertNewline
                    @param {Event} event
                  */
            insertNewline: function(event) {
                sendAction('enter', this, event);
                sendAction('insert-newline', this, event);
            },

            /**
                    Called when the user hits escape.

                    Called by the `Ember.TextSupport` mixin on keyUp if keycode matches 27.
                    Uses sendAction to send the `escape-press` action.

                    @method cancel
                    @param {Event} event
                  */
            cancel: function(event) {
                sendAction('escape-press', this, event);
            },

            /**
                    Called when the text area is focused.

                    Uses sendAction to send the `focus-in` action.

                    @method focusIn
                    @param {Event} event
                  */
            focusIn: function(event) {
                sendAction('focus-in', this, event);
            },

            /**
                    Called when the text area is blurred. 

                    Uses sendAction to send the `focus-out` action.

                    @method focusOut
                    @param {Event} event
                  */
            focusOut: function(event) {
                sendAction('focus-out', this, event);
            },

            /**
                    Called when the user presses a key. Enabled by setting
                    the `onEvent` property to `keyPress`.

                    Uses sendAction to send the `key-press` action.

                    @method keyPress
                    @param {Event} event
                  */
            keyPress: function(event) {
                sendAction('key-press', this, event);
            }

        });

        TextSupport.KEY_EVENTS = {
            13: 'insertNewline',
            27: 'cancel'
        };

        // In principle, this shouldn't be necessary, but the legacy
        // sendAction semantics for TextField are different from
        // the component semantics so this method normalizes them.
        function sendAction(eventName, view, event) {
            var action = get(view, eventName),
            on = get(view, 'onEvent'),
            value = get(view, 'value');

            // back-compat support for keyPress as an event name even though
            // it's also a method name that consumes the event (and therefore
            // incompatible with sendAction semantics).
            if (on === eventName || (on === 'keyPress' && eventName === 'key-press')) {
                view.sendAction('action', value);
            }

            view.sendAction(eventName, value);

            if (action || on === eventName) {
                if (!get(view, 'bubbles')) {
                    event.stopPropagation();
                }
            }
        }

        __exports__["default"] = TextSupport;
    });
    define("ember-handlebars/ext",
    ["ember-metal/core", "ember-runtime/system/string", "ember-handlebars-compiler", "ember-metal/property_get", "ember-metal/binding", "ember-metal/error", "ember-metal/mixin", "ember-metal/is_empty", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // Ember.FEATURES, Ember.assert, Ember.Handlebars, Ember.lookup
        // var emberAssert = Ember.assert;

        var fmt = __dependency2__.fmt;

        var EmberHandlebars = __dependency3__["default"];
        var helpers = EmberHandlebars.helpers;

        var get = __dependency4__.get;
        var isGlobalPath = __dependency5__.isGlobalPath;
        var EmberError = __dependency6__["default"];
        var IS_BINDING = __dependency7__.IS_BINDING;

        // late bound via requireModule because of circular dependencies.
        var resolveHelper,
        SimpleHandlebarsView;

        var isEmpty = __dependency8__["default"];

        var slice = [].slice, originalTemplate = EmberHandlebars.template;

        /**
              If a path starts with a reserved keyword, returns the root
              that should be used.

              @private
              @method normalizePath
              @for Ember
              @param root {Object}
              @param path {String}
              @param data {Hash}
            */
        function normalizePath(root, path, data) {
            var keywords = (data && data.keywords) || {},
            keyword, isKeyword;

            // Get the first segment of the path. For example, if the
            // path is "foo.bar.baz", returns "foo".
            keyword = path.split('.', 1)[0];

            // Test to see if the first path is a keyword that has been
            // passed along in the view's data hash. If so, we will treat
            // that object as the new root.
            if (keywords.hasOwnProperty(keyword)) {
                // Look up the value in the template's data hash.
                root = keywords[keyword];
                isKeyword = true;

                // Handle cases where the entire path is the reserved
                // word. In that case, return the object itself.
                if (path === keyword) {
                    path = '';
                } else {
                    // Strip the keyword from the path and look up
                    // the remainder from the newly found root.
                    path = path.substr(keyword.length + 1);
                }
            }

            return {
                root: root,
                path: path,
                isKeyword: isKeyword 
            };
        }


        /**
              Lookup both on root and on window. If the path starts with
              a keyword, the corresponding object will be looked up in the
              template's data hash and used to resolve the path.

              @method get
              @for Ember.Handlebars
              @param {Object} root The object to look up the property on
              @param {String} path The path to be lookedup
              @param {Object} options The template's option hash
            */
        function handlebarsGet(root, path, options) {
            var data = options && options.data,
            normalizedPath = normalizePath(root, path, data),
            value;


            root = normalizedPath.root;
            path = normalizedPath.path;

            value = get(root, path);

            if (value === undefined && root !== Ember.lookup && isGlobalPath(path)) {
                value = get(Ember.lookup, path);
            }


            return value;
        }

        /**
              This method uses `Ember.Handlebars.get` to lookup a value, then ensures
              that the value is escaped properly.

              If `unescaped` is a truthy value then the escaping will not be performed.

              @method getEscaped
              @for Ember.Handlebars
              @param {Object} root The object to look up the property on
              @param {String} path The path to be lookedup
              @param {Object} options The template's option hash
              @since 1.4.0
            */
        function getEscaped(root, path, options) {
            var result = handlebarsGet(root, path, options);

            if (result === null || result === undefined) {
                result = "";
            } else if (!(result instanceof Handlebars.SafeString)) {
                result = String(result);
            }
            if (!options.hash.unescaped) {
                result = Handlebars.Utils.escapeExpression(result);
            }

            return result;
        }

        __exports__.getEscaped = getEscaped;
        function resolveParams(context, params, options) {
            var resolvedParams = [], types = options.types, param, type;

            for (var i = 0, l = params.length; i < l; i++) {
                param = params[i];
                type = types[i];

                if (type === 'ID') {
                    resolvedParams.push(handlebarsGet(context, param, options));
                } else {
                    resolvedParams.push(param);
                }
            }

            return resolvedParams;
        }

        __exports__.resolveParams = resolveParams;
        function resolveHash(context, hash, options) {
            var resolvedHash = {}, types = options.hashTypes, type;

            for (var key in hash) {
                if (!hash.hasOwnProperty(key)) {
                    continue;
                }

                type = types[key];

                if (type === 'ID') {
                    resolvedHash[key] = handlebarsGet(context, hash[key], options);
                } else {
                    resolvedHash[key] = hash[key];
                }
            }

            return resolvedHash;
        }

        __exports__.resolveHash = resolveHash; /**
              Registers a helper in Handlebars that will be called if no property with the
              given name can be found on the current context object, and no helper with
              that name is registered.

              This throws an exception with a more helpful error message so the user can
              track down where the problem is happening.

              @private
              @method helperMissing
              @for Ember.Handlebars.helpers
              @param {String} path
              @param {Hash} options
            */
        function helperMissingHelper(path) {
            if (!resolveHelper) {
                resolveHelper = requireModule('ember-handlebars/helpers/binding')['resolveHelper'];
            }
            // ES6TODO: stupid circular dep

            var error, view = "";

            var options = arguments[arguments.length - 1];

            var helper = resolveHelper(options.data.view.container, path);

            if (helper) {
                return helper.apply(this, slice.call(arguments, 1));
            }

            error = "%@ Handlebars error: Could not find property '%@' on object %@.";
            if (options.data) {
                view = options.data.view;
            }
            throw new EmberError(fmt(error, [view, path, this]));
        }

        __exports__.helperMissingHelper = helperMissingHelper; /**
              Registers a helper in Handlebars that will be called if no property with the
              given name can be found on the current context object, and no helper with
              that name is registered.

              This throws an exception with a more helpful error message so the user can
              track down where the problem is happening.

              @private
              @method helperMissing
              @for Ember.Handlebars.helpers
              @param {String} path
              @param {Hash} options
            */
        function blockHelperMissingHelper(path) {
            if (!resolveHelper) {
                resolveHelper = requireModule('ember-handlebars/helpers/binding')['resolveHelper'];
            }
            // ES6TODO: stupid circular dep

            var options = arguments[arguments.length - 1];

            Ember.assert("`blockHelperMissing` was invoked without a helper name, which " +
            "is most likely due to a mismatch between the version of " +
            "Ember.js you're running now and the one used to precompile your " +
            "templates. Please make sure the version of " +
            "`ember-handlebars-compiler` you're using is up to date.", path);

            var helper = resolveHelper(options.data.view.container, path);

            if (helper) {
                return helper.apply(this, slice.call(arguments, 1));
            } else {
                return helpers.helperMissing.call(this, path);
            }
        }

        __exports__.blockHelperMissingHelper = blockHelperMissingHelper; /**
              Register a bound handlebars helper. Bound helpers behave similarly to regular
              handlebars helpers, with the added ability to re-render when the underlying data
              changes.

              ## Simple example

              ```javascript
              Ember.Handlebars.registerBoundHelper('capitalize', function(value) {
                return Ember.String.capitalize(value);
              });
              ```

              The above bound helper can be used inside of templates as follows:

              ```handlebars
              {{capitalize name}}
              ```

              In this case, when the `name` property of the template's context changes,
              the rendered value of the helper will update to reflect this change.

              ## Example with options

              Like normal handlebars helpers, bound helpers have access to the options
              passed into the helper call.

              ```javascript
              Ember.Handlebars.registerBoundHelper('repeat', function(value, options) {
                var count = options.hash.count;
                var a = [];
                while(a.length < count) {
                    a.push(value);
                }
                return a.join('');
              });
              ```

              This helper could be used in a template as follows:

              ```handlebars
              {{repeat text count=3}}
              ```

              ## Example with bound options

              Bound hash options are also supported. Example:

              ```handlebars
              {{repeat text count=numRepeats}}
              ```

              In this example, count will be bound to the value of
              the `numRepeats` property on the context. If that property
              changes, the helper will be re-rendered.

              ## Example with extra dependencies

              The `Ember.Handlebars.registerBoundHelper` method takes a variable length
              third parameter which indicates extra dependencies on the passed in value.
              This allows the handlebars helper to update when these dependencies change.

              ```javascript
              Ember.Handlebars.registerBoundHelper('capitalizeName', function(value) {
                return value.get('name').toUpperCase();
              }, 'name');
              ```

              ## Example with multiple bound properties

              `Ember.Handlebars.registerBoundHelper` supports binding to
              multiple properties, e.g.:

              ```javascript
              Ember.Handlebars.registerBoundHelper('concatenate', function() {
                var values = Array.prototype.slice.call(arguments, 0, -1);
                return values.join('||');
              });
              ```

              Which allows for template syntax such as `{{concatenate prop1 prop2}}` or
              `{{concatenate prop1 prop2 prop3}}`. If any of the properties change,
              the helper will re-render.  Note that dependency keys cannot be
              using in conjunction with multi-property helpers, since it is ambiguous
              which property the dependent keys would belong to.

              ## Use with unbound helper

              The `{{unbound}}` helper can be used with bound helper invocations
              to render them in their unbound form, e.g.

              ```handlebars
              {{unbound capitalize name}}
              ```

              In this example, if the name property changes, the helper
              will not re-render.

              ## Use with blocks not supported

              Bound helpers do not support use with Handlebars blocks or
              the addition of child views of any kind.

              @method registerBoundHelper
              @for Ember.Handlebars
              @param {String} name
              @param {Function} function
              @param {String} dependentKeys*
            */
        function registerBoundHelper(name, fn) {
            var boundHelperArgs = slice.call(arguments, 1),
            boundFn = makeBoundHelper.apply(this, boundHelperArgs);
            EmberHandlebars.registerHelper(name, boundFn);
        }

        __exports__.registerBoundHelper = registerBoundHelper; /**
              A helper function used by `registerBoundHelper`. Takes the
              provided Handlebars helper function fn and returns it in wrapped
              bound helper form.

              The main use case for using this outside of `registerBoundHelper`
              is for registering helpers on the container:

              ```js
              var boundHelperFn = Ember.Handlebars.makeBoundHelper(function(word) {
                return word.toUpperCase();
              });

              container.register('helper:my-bound-helper', boundHelperFn);
              ```

              In the above example, if the helper function hadn't been wrapped in
              `makeBoundHelper`, the registered helper would be unbound.

              @method makeBoundHelper
              @for Ember.Handlebars
              @param {Function} function
              @param {String} dependentKeys*
              @since 1.2.0
            */
        function makeBoundHelper(fn) {
            if (!SimpleHandlebarsView) {
                SimpleHandlebarsView = requireModule('ember-handlebars/views/handlebars_bound_view')['SimpleHandlebarsView'];
            }
            // ES6TODO: stupid circular dep

            var dependentKeys = slice.call(arguments, 1);

            function helper() {
                var properties = slice.call(arguments, 0, -1),
                numProperties = properties.length,
                options = arguments[arguments.length - 1],
                normalizedProperties = [],
                data = options.data,
                types = data.isUnbound ? slice.call(options.types, 1) : options.types,
                hash = options.hash,
                view = data.view,
                contexts = options.contexts,
                currentContext = (contexts && contexts.length) ? contexts[0] : this,
                prefixPathForDependentKeys = '',
                loc, len, hashOption,
                boundOption, property,
                normalizedValue = SimpleHandlebarsView.prototype.normalizedValue;

                Ember.assert("registerBoundHelper-generated helpers do not support use with Handlebars blocks.", !options.fn);

                // Detect bound options (e.g. countBinding="otherCount")
                var boundOptions = hash.boundOptions = {};
                for (hashOption in hash) {
                    if (IS_BINDING.test(hashOption)) {
                        // Lop off 'Binding' suffix.
                        boundOptions[hashOption.slice(0, -7)] = hash[hashOption];
                    }
                }

                // Expose property names on data.properties object.
                var watchedProperties = [];
                data.properties = [];
                for (loc = 0; loc < numProperties; ++loc) {
                    data.properties.push(properties[loc]);
                    if (types[loc] === 'ID') {
                        var normalizedProp = normalizePath(currentContext, properties[loc], data);
                        normalizedProperties.push(normalizedProp);
                        watchedProperties.push(normalizedProp);
                    } else {
                        if (data.isUnbound) {
                            normalizedProperties.push({
                                path: properties[loc]
                            });
                        } else {
                            normalizedProperties.push(null);
                        }
                    }
                }

                // Handle case when helper invocation is preceded by `unbound`, e.g.
                // {{unbound myHelper foo}}
                if (data.isUnbound) {
                    return evaluateUnboundHelper(this, fn, normalizedProperties, options);
                }

                var bindView = new SimpleHandlebarsView(null, null, !options.hash.unescaped, options.data);

                // Override SimpleHandlebarsView's method for generating the view's content.
                bindView.normalizedValue = function() {
                    var args = [], boundOption;

                    // Copy over bound hash options.
                    for (boundOption in boundOptions) {
                        if (!boundOptions.hasOwnProperty(boundOption)) {
                            continue;
                        }
                        property = normalizePath(currentContext, boundOptions[boundOption], data);
                        bindView.path = property.path;
                        bindView.pathRoot = property.root;
                        hash[boundOption] = normalizedValue.call(bindView);
                    }

                    for (loc = 0; loc < numProperties; ++loc) {
                        property = normalizedProperties[loc];
                        if (property) {
                            bindView.path = property.path;
                            bindView.pathRoot = property.root;
                            args.push(normalizedValue.call(bindView));
                        } else {
                            args.push(properties[loc]);
                        }
                    }
                    args.push(options);

                    // Run the supplied helper function.
                    return fn.apply(currentContext, args);
                };

                view.appendChild(bindView);

                // Assemble list of watched properties that'll re-render this helper.
                for (boundOption in boundOptions) {
                    if (boundOptions.hasOwnProperty(boundOption)) {
                        watchedProperties.push(normalizePath(currentContext, boundOptions[boundOption], data));
                    }
                }

                // Observe each property.
                for (loc = 0, len = watchedProperties.length; loc < len; ++loc) {
                    property = watchedProperties[loc];
                    view.registerObserver(property.root, property.path, bindView, bindView.rerender);
                }

                if (types[0] !== 'ID' || normalizedProperties.length === 0) {
                    return;
                }

                // Add dependent key observers to the first param
                var normalized = normalizedProperties[0],
                pathRoot = normalized.root,
                path = normalized.path;

                if (!isEmpty(path)) {
                    prefixPathForDependentKeys = path + '.';
                }
                for (var i = 0, l = dependentKeys.length; i < l; i++) {
                    view.registerObserver(pathRoot, prefixPathForDependentKeys + dependentKeys[i], bindView, bindView.rerender);
                }
            }

            helper._rawFunction = fn;
            return helper;
        }

        /**
              Renders the unbound form of an otherwise bound helper function.

              @private
              @method evaluateUnboundHelper
              @param {Function} fn
              @param {Object} context
              @param {Array} normalizedProperties
              @param {String} options
            */
        function evaluateUnboundHelper(context, fn, normalizedProperties, options) {
            var args = [],
            hash = options.hash,
            boundOptions = hash.boundOptions,
            types = slice.call(options.types, 1),
            loc,
            len,
            property,
            propertyType,
            boundOption;

            for (boundOption in boundOptions) {
                if (!boundOptions.hasOwnProperty(boundOption)) {
                    continue;
                }
                hash[boundOption] = handlebarsGet(context, boundOptions[boundOption], options);
            }

            for (loc = 0, len = normalizedProperties.length; loc < len; ++loc) {
                property = normalizedProperties[loc];
                propertyType = types[loc];
                if (propertyType === "ID") {
                    args.push(handlebarsGet(property.root, property.path, options));
                } else {
                    args.push(property.path);
                }
            }
            args.push(options);
            return fn.apply(context, args);
        }

        /**
              Overrides Handlebars.template so that we can distinguish
              user-created, top-level templates from inner contexts.

              @private
              @method template
              @for Ember.Handlebars
              @param {String} spec
            */
        function template(spec) {
            var t = originalTemplate(spec);
            t.isTop = true;
            return t;
        }

        __exports__.template = template;
        __exports__.normalizePath = normalizePath;
        __exports__.makeBoundHelper = makeBoundHelper;
        __exports__.handlebarsGet = handlebarsGet;
        __exports__.evaluateUnboundHelper = evaluateUnboundHelper;
    });
    define("ember-handlebars/helpers/binding",
    ["ember-metal/core", "ember-handlebars-compiler", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/utils", "ember-runtime/system/string", "ember-metal/platform", "ember-metal/is_none", "ember-metal/enumerable_utils", "ember-metal/array", "ember-views/views/view", "ember-metal/run_loop", "ember-metal/observer", "ember-metal/binding", "ember-views/system/jquery", "ember-handlebars/ext", "ember-runtime/keys", "ember-handlebars/views/handlebars_bound_view", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-handlebars
            */

        var Ember = __dependency1__["default"];
        // Ember.assert, Ember.warn, uuid
        // var emberAssert = Ember.assert, Ember.warn = Ember.warn;

        var EmberHandlebars = __dependency2__["default"];
        var get = __dependency3__.get;
        var set = __dependency4__.set;
        var apply = __dependency5__.apply;
        var uuid = __dependency5__.uuid;
        var fmt = __dependency6__.fmt;
        var o_create = __dependency7__.create;
        var isNone = __dependency8__["default"];
        var EnumerableUtils = __dependency9__["default"];
        var forEach = __dependency10__.forEach;
        var View = __dependency11__["default"];
        var run = __dependency12__["default"];
        var removeObserver = __dependency13__.removeObserver;
        var isGlobalPath = __dependency14__.isGlobalPath;
        var emberBind = __dependency14__.bind;
        var jQuery = __dependency15__["default"];
        var isArray = __dependency5__.isArray;
        var handlebarsGetEscaped = __dependency16__.getEscaped;
        var keys = __dependency17__["default"];

        var _HandlebarsBoundView = __dependency18__._HandlebarsBoundView;
        var SimpleHandlebarsView = __dependency18__.SimpleHandlebarsView;

        var normalizePath = __dependency16__.normalizePath;
        var handlebarsGet = __dependency16__.handlebarsGet;
        var getEscaped = __dependency16__.getEscaped;

        var guidFor = __dependency5__.guidFor;
        var typeOf = __dependency5__.typeOf;

        var helpers = EmberHandlebars.helpers;
        var SafeString = EmberHandlebars.SafeString;

        function exists(value) {
            return !isNone(value);
        }

        var WithView = _HandlebarsBoundView.extend({
            init: function() {
                var controller;

                apply(this, this._super, arguments);

                var keywords = this.templateData.keywords;
                var keywordName = this.templateHash.keywordName;
                var keywordPath = this.templateHash.keywordPath;
                var controllerName = this.templateHash.controller;
                var preserveContext = this.preserveContext;

                if (controllerName) {
                    var previousContext = this.previousContext;
                    controller = this.container.lookupFactory('controller:' + controllerName).create({
                        parentController: previousContext,
                        target: previousContext
                    });

                    this._generatedController = controller;

                    if (!preserveContext) {
                        this.set('controller', controller);

                        this.valueNormalizerFunc = function(result) {
                            controller.set('model', result);
                            return controller;
                        };
                    } else {
                        var controllerPath = jQuery.expando + guidFor(controller);
                        keywords[controllerPath] = controller;
                        emberBind(keywords, controllerPath + '.model', keywordPath);
                        keywordPath = controllerPath;
                    }
                }

                if (preserveContext) {
                    emberBind(keywords, keywordName, keywordPath);
                }

            },
            willDestroy: function() {
                this._super();

                if (this._generatedController) {
                    this._generatedController.destroy();
                }
            }
        });

        // Binds a property into the DOM. This will create a hook in DOM that the
        // KVO system will look for and update if the property changes.
        function bind(property, options, preserveContext, shouldDisplay, valueNormalizer, childProperties) {
            var data = options.data,
            fn = options.fn,
            inverse = options.inverse,
            view = data.view,
            normalized, observer, i;

            // we relied on the behavior of calling without
            // context to mean this === window, but when running
            // "use strict", it's possible for this to === undefined;
            var currentContext = this || window;

            normalized = normalizePath(currentContext, property, data);

            // Set up observers for observable objects
            if ('object' === typeof this) {
                if (data.insideGroup) {
                    observer = function() {
                        while (view._contextView) {
                            view = view._contextView;
                        }
                        run.once(view, 'rerender');
                    };

                    var template, context, result = handlebarsGet(currentContext, property, options);

                    result = valueNormalizer ? valueNormalizer(result) : result;

                    context = preserveContext ? currentContext : result;
                    if (shouldDisplay(result)) {
                        template = fn;
                    } else if (inverse) {
                        template = inverse;
                    }

                    template(context, {
                        data: options.data 
                    });
                } else {
                    var viewClass = _HandlebarsBoundView;
                    var viewOptions = {
                        preserveContext: preserveContext,
                        shouldDisplayFunc: shouldDisplay,
                        valueNormalizerFunc: valueNormalizer,
                        displayTemplate: fn,
                        inverseTemplate: inverse,
                        path: property,
                        pathRoot: currentContext,
                        previousContext: currentContext,
                        isEscaped: !options.hash.unescaped,
                        templateData: options.data,
                        templateHash: options.hash,
                        helperName: options.helperName
                    };

                    if (options.isWithHelper) {
                        viewClass = WithView;
                    }

                    // Create the view that will wrap the output of this template/property
                    // and add it to the nearest view's childViews array.
                    // See the documentation of Ember._HandlebarsBoundView for more.
                    var bindView = view.createChildView(viewClass, viewOptions);

                    view.appendChild(bindView);

                    observer = function() {
                        run.scheduleOnce('render', bindView, 'rerenderIfNeeded');
                    };
                }

                // Observes the given property on the context and
                // tells the Ember._HandlebarsBoundView to re-render. If property
                // is an empty string, we are printing the current context
                // object ({{this}}) so updating it is not our responsibility.
                if (normalized.path !== '') {
                    view.registerObserver(normalized.root, normalized.path, observer);
                    if (childProperties) {
                        for (i = 0; i < childProperties.length; i++) {
                            view.registerObserver(normalized.root, normalized.path + '.' + childProperties[i], observer);
                        }
                    }
                }
            } else {
                // The object is not observable, so just render it out and
                // be done with it.
                data.buffer.push(handlebarsGetEscaped(currentContext, property, options));
            }
        }

        function simpleBind(currentContext, property, options) {
            var data = options.data,
            view = data.view,
            normalized, observer, pathRoot, output;

            normalized = normalizePath(currentContext, property, data);
            pathRoot = normalized.root;

            // Set up observers for observable objects
            if (pathRoot && ('object' === typeof pathRoot)) {
                if (data.insideGroup) {
                    observer = function() {
                        while (view._contextView) {
                            view = view._contextView;
                        }
                        run.once(view, 'rerender');
                    };

                    output = handlebarsGetEscaped(currentContext, property, options);

                    data.buffer.push(output);
                } else {
                    var bindView = new SimpleHandlebarsView(
                    property, currentContext, !options.hash.unescaped, options.data
                    );

                    bindView._parentView = view;
                    view.appendChild(bindView);

                    observer = function() {
                        run.scheduleOnce('render', bindView, 'rerender');
                    };
                }

                // Observes the given property on the context and
                // tells the Ember._HandlebarsBoundView to re-render. If property
                // is an empty string, we are printing the current context
                // object ({{this}}) so updating it is not our responsibility.
                if (normalized.path !== '') {
                    view.registerObserver(normalized.root, normalized.path, observer);
                }
            } else {
                // The object is not observable, so just render it out and
                // be done with it.
                output = handlebarsGetEscaped(currentContext, property, options);
                data.buffer.push(output);
            }
        }

        function shouldDisplayIfHelperContent(result) {
            var truthy = result && get(result, 'isTruthy');
            if (typeof truthy === 'boolean') {
                return truthy;
            }

            if (isArray(result)) {
                return get(result, 'length') !== 0;
            } else {
                return !!result;
            }
        }

        /**
              '_triageMustache' is used internally select between a binding, helper, or component for
              the given context. Until this point, it would be hard to determine if the
              mustache is a property reference or a regular helper reference. This triage
              helper resolves that.

              This would not be typically invoked by directly.

              @private
              @method _triageMustache
              @for Ember.Handlebars.helpers
              @param {String} property Property/helperID to triage
              @param {Object} options hash of template/rendering options
              @return {String} HTML string
            */
        function _triageMustacheHelper(property, options) {
            Ember.assert("You cannot pass more than one argument to the _triageMustache helper", arguments.length <= 2);

            var helper = EmberHandlebars.resolveHelper(options.data.view.container, property);
            if (helper) {
                return helper.call(this, options);
            }

            return helpers.bind.call(this, property, options);
        }

        /**
              Used to lookup/resolve handlebars helpers. The lookup order is:

              * Look for a registered helper
              * If a dash exists in the name:
                * Look for a helper registed in the container
                * Use Ember.ComponentLookup to find an Ember.Component that resolves
                  to the given name

              @private
              @method resolveHelper
              @param {Container} container
              @param {String} name the name of the helper to lookup
              @return {Handlebars Helper}
            */
        function resolveHelper(container, name) {
            if (helpers[name]) {
                return helpers[name];
            }

            if (!container || name.indexOf('-') === -1) {
                return;
            }

            var helper = container.lookup('helper:' + name);
            if (!helper) {
                var componentLookup = container.lookup('component-lookup:main');
                Ember.assert("Could not find 'component-lookup:main' on the provided container, which is necessary for performing component lookups", componentLookup);

                var Component = componentLookup.lookupFactory(name, container);
                if (Component) {
                    helper = EmberHandlebars.makeViewHelper(Component);
                    container.register('helper:' + name, helper);
                }
            }
            return helper;
        }


        /**
              `bind` can be used to display a value, then update that value if it
              changes. For example, if you wanted to print the `title` property of
              `content`:

              ```handlebars
              {{bind "content.title"}}
              ```

              This will return the `title` property as a string, then create a new observer
              at the specified path. If it changes, it will update the value in DOM. Note
              that if you need to support IE7 and IE8 you must modify the model objects
              properties using `Ember.get()` and `Ember.set()` for this to work as it
              relies on Ember's KVO system. For all other browsers this will be handled for
              you automatically.

              @private
              @method bind
              @for Ember.Handlebars.helpers
              @param {String} property Property to bind
              @param {Function} fn Context to provide for rendering
              @return {String} HTML string
            */
        function bindHelper(property, options) {
            Ember.assert("You cannot pass more than one argument to the bind helper", arguments.length <= 2);

            var context = (options.contexts && options.contexts.length) ? options.contexts[0] : this;

            if (!options.fn) {
                return simpleBind(context, property, options);
            }

            options.helperName = 'bind';

            return bind.call(context, property, options, false, exists);
        }

        /**
              Use the `boundIf` helper to create a conditional that re-evaluates
              whenever the truthiness of the bound value changes.

              ```handlebars
              {{#boundIf "content.shouldDisplayTitle"}}
                {{content.title}}
              {{/boundIf}}
              ```

              @private
              @method boundIf
              @for Ember.Handlebars.helpers
              @param {String} property Property to bind
              @param {Function} fn Context to provide for rendering
              @return {String} HTML string
            */
        function boundIfHelper(property, fn) {
            var context = (fn.contexts && fn.contexts.length) ? fn.contexts[0] : this;

            fn.helperName = fn.helperName || 'boundIf';

            return bind.call(context, property, fn, true, shouldDisplayIfHelperContent, shouldDisplayIfHelperContent, ['isTruthy', 'length']);
        }


        /**
              @private

              Use the `unboundIf` helper to create a conditional that evaluates once.

              ```handlebars
              {{#unboundIf "content.shouldDisplayTitle"}}
                {{content.title}}
              {{/unboundIf}}
              ```

              @method unboundIf
              @for Ember.Handlebars.helpers
              @param {String} property Property to bind
              @param {Function} fn Context to provide for rendering
              @return {String} HTML string
              @since 1.4.0
            */
        function unboundIfHelper(property, fn) {
            var context = (fn.contexts && fn.contexts.length) ? fn.contexts[0] : this,
            data = fn.data,
            template = fn.fn,
            inverse = fn.inverse,
            normalized, propertyValue, result;

            normalized = normalizePath(context, property, data);
            propertyValue = handlebarsGet(context, property, fn);

            if (!shouldDisplayIfHelperContent(propertyValue)) {
                template = inverse;
            }

            template(context, {
                data: data 
            });
        }

        /**
              Use the `{{with}}` helper when you want to scope context. Take the following code as an example:

              ```handlebars
              <h5>{{user.name}}</h5>

              <div class="role">
                <h6>{{user.role.label}}</h6>
                <span class="role-id">{{user.role.id}}</span>

                <p class="role-desc">{{user.role.description}}</p>
              </div>
              ```

              `{{with}}` can be our best friend in these cases,
              instead of writing `user.role.*` over and over, we use `{{#with user.role}}`.
              Now the context within the `{{#with}} .. {{/with}}` block is `user.role` so you can do the following:

              ```handlebars
              <h5>{{user.name}}</h5>

              <div class="role">
                {{#with user.role}}
                  <h6>{{label}}</h6>
                  <span class="role-id">{{id}}</span>

                  <p class="role-desc">{{description}}</p>
                {{/with}}
              </div>
              ```

              ### `as` operator

              This operator aliases the scope to a new name. It's helpful for semantic clarity and to retain
              default scope or to reference from another `{{with}}` block.

              ```handlebars
              // posts might not be
              {{#with user.posts as blogPosts}}
                <div class="notice">
                  There are {{blogPosts.length}} blog posts written by {{user.name}}.
                </div>

                {{#each post in blogPosts}}
                  <li>{{post.title}}</li>
                {{/each}}
              {{/with}}
              ```

              Without the `as` operator, it would be impossible to reference `user.name` in the example above.

              NOTE: The alias should not reuse a name from the bound property path.
              For example: `{{#with foo.bar as foo}}` is not supported because it attempts to alias using
              the first part of the property path, `foo`. Instead, use `{{#with foo.bar as baz}}`.

              ### `controller` option

              Adding `controller='something'` instructs the `{{with}}` helper to create and use an instance of
              the specified controller with the new context as its content.

              This is very similar to using an `itemController` option with the `{{each}}` helper.

              ```handlebars
              {{#with users.posts controller='userBlogPosts'}}
                {{!- The current context is wrapped in our controller instance }}
              {{/with}}
              ```

              In the above example, the template provided to the `{{with}}` block is now wrapped in the
              `userBlogPost` controller, which provides a very elegant way to decorate the context with custom
              functions/properties.

              @method with
              @for Ember.Handlebars.helpers
              @param {Function} context
              @param {Hash} options
              @return {String} HTML string
            */
        function withHelper(context, options) {
            var bindContext, preserveContext, controller, helperName = 'with';

            if (arguments.length === 4) {
                var keywordName, path, rootPath, normalized, contextPath;

                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");
                options = arguments[3];
                keywordName = arguments[2];
                path = arguments[0];

                if (path) {
                    helperName += ' ' + path + ' as ' + keywordName;
                }

                Ember.assert("You must pass a block to the with helper", options.fn && options.fn !== Handlebars.VM.noop);

                var localizedOptions = o_create(options);
                localizedOptions.data = o_create(options.data);
                localizedOptions.data.keywords = o_create(options.data.keywords || {});

                if (isGlobalPath(path)) {
                    contextPath = path;
                } else {
                    normalized = normalizePath(this, path, options.data);
                    path = normalized.path;
                    rootPath = normalized.root;

                    // This is a workaround for the fact that you cannot bind separate objects
                    // together. When we implement that functionality, we should use it here.
                    var contextKey = jQuery.expando + guidFor(rootPath);
                    localizedOptions.data.keywords[contextKey] = rootPath;
                    // if the path is '' ("this"), just bind directly to the current context
                    contextPath = path ? contextKey + '.' + path : contextKey;
                }

                localizedOptions.hash.keywordName = keywordName;
                localizedOptions.hash.keywordPath = contextPath;

                bindContext = this;
                context = contextPath;
                options = localizedOptions;
                preserveContext = true;
            } else {
                Ember.assert("You must pass exactly one argument to the with helper", arguments.length === 2);
                Ember.assert("You must pass a block to the with helper", options.fn && options.fn !== Handlebars.VM.noop);

                helperName += ' ' + context;
                bindContext = options.contexts[0];
                preserveContext = false;
            }

            options.helperName = helperName;
            options.isWithHelper = true;

            return bind.call(bindContext, context, options, preserveContext, exists);
        }
        /**
              See [boundIf](/api/classes/Ember.Handlebars.helpers.html#method_boundIf)
              and [unboundIf](/api/classes/Ember.Handlebars.helpers.html#method_unboundIf)

              @method if
              @for Ember.Handlebars.helpers
              @param {Function} context
              @param {Hash} options
              @return {String} HTML string
            */
        function ifHelper(context, options) {
            Ember.assert("You must pass exactly one argument to the if helper", arguments.length === 2);
            Ember.assert("You must pass a block to the if helper", options.fn && options.fn !== Handlebars.VM.noop);

            options.helperName = options.helperName || ('if ' + context);

            if (options.data.isUnbound) {
                return helpers.unboundIf.call(options.contexts[0], context, options);
            } else {
                return helpers.boundIf.call(options.contexts[0], context, options);
            }
        }

        /**
              @method unless
              @for Ember.Handlebars.helpers
              @param {Function} context
              @param {Hash} options
              @return {String} HTML string
            */
        function unlessHelper(context, options) {
            Ember.assert("You must pass exactly one argument to the unless helper", arguments.length === 2);
            Ember.assert("You must pass a block to the unless helper", options.fn && options.fn !== Handlebars.VM.noop);

            var fn = options.fn, inverse = options.inverse, helperName = 'unless';

            if (context) {
                helperName += ' ' + context;
            }

            options.fn = inverse;
            options.inverse = fn;

            options.helperName = options.helperName || helperName;

            if (options.data.isUnbound) {
                return helpers.unboundIf.call(options.contexts[0], context, options);
            } else {
                return helpers.boundIf.call(options.contexts[0], context, options);
            }
        }

        /**
              `bind-attr` allows you to create a binding between DOM element attributes and
              Ember objects. For example:

              ```handlebars
              <img {{bind-attr src="imageUrl" alt="imageTitle"}}>
              ```

              The above handlebars template will fill the `<img>`'s `src` attribute will
              the value of the property referenced with `"imageUrl"` and its `alt`
              attribute with the value of the property referenced with `"imageTitle"`.

              If the rendering context of this template is the following object:

              ```javascript
              {
                imageUrl: 'http://lolcats.info/haz-a-funny',
                imageTitle: 'A humorous image of a cat'
              }
              ```

              The resulting HTML output will be:

              ```html
              <img src="http://lolcats.info/haz-a-funny" alt="A humorous image of a cat">
              ```

              `bind-attr` cannot redeclare existing DOM element attributes. The use of `src`
              in the following `bind-attr` example will be ignored and the hard coded value
              of `src="/failwhale.gif"` will take precedence:

              ```handlebars
              <img src="/failwhale.gif" {{bind-attr src="imageUrl" alt="imageTitle"}}>
              ```

              ### `bind-attr` and the `class` attribute

              `bind-attr` supports a special syntax for handling a number of cases unique
              to the `class` DOM element attribute. The `class` attribute combines
              multiple discrete values into a single attribute as a space-delimited
              list of strings. Each string can be:

              * a string return value of an object's property.
              * a boolean return value of an object's property
              * a hard-coded value

              A string return value works identically to other uses of `bind-attr`. The
              return value of the property will become the value of the attribute. For
              example, the following view and template:

              ```javascript
                AView = View.extend({
                  someProperty: function() {
                    return "aValue";
                  }.property()
                })
              ```

              ```handlebars
              <img {{bind-attr class="view.someProperty}}>
              ```

              Result in the following rendered output:

              ```html
              <img class="aValue">
              ```

              A boolean return value will insert a specified class name if the property
              returns `true` and remove the class name if the property returns `false`.

              A class name is provided via the syntax
              `somePropertyName:class-name-if-true`.

              ```javascript
              AView = View.extend({
                someBool: true
              })
              ```

              ```handlebars
              <img {{bind-attr class="view.someBool:class-name-if-true"}}>
              ```

              Result in the following rendered output:

              ```html
              <img class="class-name-if-true">
              ```

              An additional section of the binding can be provided if you want to
              replace the existing class instead of removing it when the boolean
              value changes:

              ```handlebars
              <img {{bind-attr class="view.someBool:class-name-if-true:class-name-if-false"}}>
              ```

              A hard-coded value can be used by prepending `:` to the desired
              class name: `:class-name-to-always-apply`.

              ```handlebars
              <img {{bind-attr class=":class-name-to-always-apply"}}>
              ```

              Results in the following rendered output:

              ```html
              <img class="class-name-to-always-apply">
              ```

              All three strategies - string return value, boolean return value, and
              hard-coded value – can be combined in a single declaration:

              ```handlebars
              <img {{bind-attr class=":class-name-to-always-apply view.someBool:class-name-if-true view.someProperty"}}>
              ```

              @method bind-attr
              @for Ember.Handlebars.helpers
              @param {Hash} options
              @return {String} HTML string
            */
        function bindAttrHelper(options) {
            var attrs = options.hash;

            Ember.assert("You must specify at least one hash argument to bind-attr", !!keys(attrs).length);

            var view = options.data.view;
            var ret = [];

            // we relied on the behavior of calling without
            // context to mean this === window, but when running
            // "use strict", it's possible for this to === undefined;
            var ctx = this || window;

            // Generate a unique id for this element. This will be added as a
            // data attribute to the element so it can be looked up when
            // the bound property changes.
            var dataId = uuid();

            // Handle classes differently, as we can bind multiple classes
            var classBindings = attrs['class'];
            if (classBindings != null) {
                var classResults = bindClasses(ctx, classBindings, view, dataId, options);

                ret.push('class="' + Handlebars.Utils.escapeExpression(classResults.join(' ')) + '"');
                delete attrs['class'];
            }

            var attrKeys = keys(attrs);

            // For each attribute passed, create an observer and emit the
            // current value of the property as an attribute.
            forEach.call(attrKeys, function(attr) {
                var path = attrs[attr],
                normalized;

                Ember.assert(fmt("You must provide an expression as the value of bound attribute. You specified: %@=%@", [attr, path]), typeof path === 'string');

                normalized = normalizePath(ctx, path, options.data);

                var value = (path === 'this') ? normalized.root : handlebarsGet(ctx, path, options),
                type = typeOf(value);

                Ember.assert(fmt("Attributes must be numbers, strings or booleans, not %@", [value]), value === null || value === undefined || type === 'number' || type === 'string' || type === 'boolean');

                var observer;

                observer = function observer() {
                    var result = handlebarsGet(ctx, path, options);

                    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');

                    var elem = view.$("[data-bindattr-" + dataId + "='" + dataId + "']");

                    // If we aren't able to find the element, it means the element
                    // to which we were bound has been removed from the view.
                    // In that case, we can assume the template has been re-rendered
                    // and we need to clean up the observer.
                    if (!elem || elem.length === 0) {
                        removeObserver(normalized.root, normalized.path, observer);
                        return;
                    }

                    View.applyAttributeBindings(elem, attr, result);
                };

                // Add an observer to the view for when the property changes.
                // When the observer fires, find the element using the
                // unique data id and update the attribute to the new value.
                // Note: don't add observer when path is 'this' or path
                // is whole keyword e.g. {{#each x in list}} ... {{bind-attr attr="x"}}
                if (path !== 'this' && !(normalized.isKeyword && normalized.path === '' )) {
                    view.registerObserver(normalized.root, normalized.path, observer);
                }

                // if this changes, also change the logic in ember-views/lib/views/view.js
                if ((type === 'string' || (type === 'number' && !isNaN(value)))) {
                    ret.push(attr + '="' + Handlebars.Utils.escapeExpression(value) + '"');
                } else if (value && type === 'boolean') {
                    // The developer controls the attr name, so it should always be safe
                    ret.push(attr + '="' + attr + '"');
                }
            }, this);

            // Add the unique identifier
            // NOTE: We use all lower-case since Firefox has problems with mixed case in SVG
            ret.push('data-bindattr-' + dataId + '="' + dataId + '"');
            return new SafeString(ret.join(' '));
        }

        /**
              See `bind-attr`

              @method bindAttr
              @for Ember.Handlebars.helpers
              @deprecated
              @param {Function} context
              @param {Hash} options
              @return {String} HTML string
            */
        function bindAttrHelperDeprecated() {
            Ember.warn("The 'bindAttr' view helper is deprecated in favor of 'bind-attr'");
            return helpers['bind-attr'].apply(this, arguments);
        }

        /**
              Helper that, given a space-separated string of property paths and a context,
              returns an array of class names. Calling this method also has the side
              effect of setting up observers at those property paths, such that if they
              change, the correct class name will be reapplied to the DOM element.

              For example, if you pass the string "fooBar", it will first look up the
              "fooBar" value of the context. If that value is true, it will add the
              "foo-bar" class to the current element (i.e., the dasherized form of
              "fooBar"). If the value is a string, it will add that string as the class.
              Otherwise, it will not add any new class name.

              @private
              @method bindClasses
              @for Ember.Handlebars
              @param {Ember.Object} context The context from which to lookup properties
              @param {String} classBindings A string, space-separated, of class bindings
                to use
              @param {View} view The view in which observers should look for the
                element to update
              @param {Srting} bindAttrId Optional bindAttr id used to lookup elements
              @return {Array} An array of class names to add
            */
        function bindClasses(context, classBindings, view, bindAttrId, options) {
            var ret = [], newClass, value, elem;

            // Helper method to retrieve the property from the context and
            // determine which class string to return, based on whether it is
            // a Boolean or not.
            var classStringForPath = function(root, parsedPath, options) {
                var val,
                path = parsedPath.path;

                if (path === 'this') {
                    val = root;
                } else if (path === '') {
                    val = true;
                } else {
                    val = handlebarsGet(root, path, options);
                }

                return View._classStringForValue(path, val, parsedPath.className, parsedPath.falsyClassName);
            };

            // For each property passed, loop through and setup
            // an observer.
            forEach.call(classBindings.split(' '), function(binding) {

                // Variable in which the old class value is saved. The observer function
                // closes over this variable, so it knows which string to remove when
                // the property changes.
                var oldClass;

                var observer;

                var parsedPath = View._parsePropertyPath(binding),
                path = parsedPath.path,
                pathRoot = context,
                normalized;

                if (path !== '' && path !== 'this') {
                    normalized = normalizePath(context, path, options.data);

                    pathRoot = normalized.root;
                    path = normalized.path;
                }

                // Set up an observer on the context. If the property changes, toggle the
                // class name.
                observer = function() {
                    // Get the current value of the property
                    newClass = classStringForPath(context, parsedPath, options);
                    elem = bindAttrId ? view.$("[data-bindattr-" + bindAttrId + "='" + bindAttrId + "']") : view.$();

                    // If we can't find the element anymore, a parent template has been
                    // re-rendered and we've been nuked. Remove the observer.
                    if (!elem || elem.length === 0) {
                        removeObserver(pathRoot, path, observer);
                    } else {
                        // If we had previously added a class to the element, remove it.
                        if (oldClass) {
                            elem.removeClass(oldClass);
                        }

                        // If necessary, add a new class. Make sure we keep track of it so
                        // it can be removed in the future.
                        if (newClass) {
                            elem.addClass(newClass);
                            oldClass = newClass;
                        } else {
                            oldClass = null;
                        }
                    }
                };

                if (path !== '' && path !== 'this') {
                    view.registerObserver(pathRoot, path, observer);
                }

                // We've already setup the observer; now we just need to figure out the
                // correct behavior right now on the first pass through.
                value = classStringForPath(context, parsedPath, options);

                if (value) {
                    ret.push(value);

                    // Make sure we save the current value so that it can be removed if the
                    // observer fires.
                    oldClass = value;
                }
            });

            return ret;
        }

        __exports__.bind = bind;
        __exports__._triageMustacheHelper = _triageMustacheHelper;
        __exports__.resolveHelper = resolveHelper;
        __exports__.bindHelper = bindHelper;
        __exports__.boundIfHelper = boundIfHelper;
        __exports__.unboundIfHelper = unboundIfHelper;
        __exports__.withHelper = withHelper;
        __exports__.ifHelper = ifHelper;
        __exports__.unlessHelper = unlessHelper;
        __exports__.bindAttrHelper = bindAttrHelper;
        __exports__.bindAttrHelperDeprecated = bindAttrHelperDeprecated;
        __exports__.bindClasses = bindClasses;
    });
    define("ember-handlebars/helpers/collection",
    ["ember-metal/core", "ember-metal/utils", "ember-handlebars-compiler", "ember-runtime/system/string", "ember-metal/property_get", "ember-handlebars/ext", "ember-handlebars/helpers/view", "ember-metal/computed", "ember-views/views/collection_view", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-handlebars
            */

        var Ember = __dependency1__["default"];
        // Ember.assert, Ember.deprecate
        var inspect = __dependency2__.inspect;

        // var emberAssert = Ember.assert;
        // emberDeprecate = Ember.deprecate;

        var EmberHandlebars = __dependency3__["default"];
        var helpers = EmberHandlebars.helpers;

        var fmt = __dependency4__.fmt;
        var get = __dependency5__.get;
        var handlebarsGet = __dependency6__.handlebarsGet;
        var ViewHelper = __dependency7__.ViewHelper;
        var computed = __dependency8__.computed;
        var CollectionView = __dependency9__["default"];

        var alias = computed.alias;
        /**
              `{{collection}}` is a `Ember.Handlebars` helper for adding instances of
              `Ember.CollectionView` to a template. See [Ember.CollectionView](/api/classes/Ember.CollectionView.html)
               for additional information on how a `CollectionView` functions.

              `{{collection}}`'s primary use is as a block helper with a `contentBinding`
              option pointing towards an `Ember.Array`-compatible object. An `Ember.View`
              instance will be created for each item in its `content` property. Each view
              will have its own `content` property set to the appropriate item in the
              collection.

              The provided block will be applied as the template for each item's view.

              Given an empty `<body>` the following template:

              ```handlebars
              {{#collection contentBinding="App.items"}}
                Hi {{view.content.name}}
              {{/collection}}
              ```

              And the following application code

              ```javascript
              App = Ember.Application.create()
              App.items = [
                Ember.Object.create({name: 'Dave'}),
                Ember.Object.create({name: 'Mary'}),
                Ember.Object.create({name: 'Sara'})
              ]
              ```

              Will result in the HTML structure below

              ```html
              <div class="ember-view">
                <div class="ember-view">Hi Dave</div>
                <div class="ember-view">Hi Mary</div>
                <div class="ember-view">Hi Sara</div>
              </div>
              ```

              ### Blockless use in a collection

              If you provide an `itemViewClass` option that has its own `template` you can
              omit the block.

              The following template:

              ```handlebars
              {{collection contentBinding="App.items" itemViewClass="App.AnItemView"}}
              ```

              And application code

              ```javascript
              App = Ember.Application.create();
              App.items = [
                Ember.Object.create({name: 'Dave'}),
                Ember.Object.create({name: 'Mary'}),
                Ember.Object.create({name: 'Sara'})
              ];

              App.AnItemView = Ember.View.extend({
                template: Ember.Handlebars.compile("Greetings {{view.content.name}}")
              });
              ```

              Will result in the HTML structure below

              ```html
              <div class="ember-view">
                <div class="ember-view">Greetings Dave</div>
                <div class="ember-view">Greetings Mary</div>
                <div class="ember-view">Greetings Sara</div>
              </div>
              ```

              ### Specifying a CollectionView subclass

              By default the `{{collection}}` helper will create an instance of
              `Ember.CollectionView`. You can supply a `Ember.CollectionView` subclass to
              the helper by passing it as the first argument:

              ```handlebars
              {{#collection App.MyCustomCollectionClass contentBinding="App.items"}}
                Hi {{view.content.name}}
              {{/collection}}
              ```

              ### Forwarded `item.*`-named Options

              As with the `{{view}}`, helper options passed to the `{{collection}}` will be
              set on the resulting `Ember.CollectionView` as properties. Additionally,
              options prefixed with `item` will be applied to the views rendered for each
              item (note the camelcasing):

              ```handlebars
              {{#collection contentBinding="App.items"
                            itemTagName="p"
                            itemClassNames="greeting"}}
                Howdy {{view.content.name}}
              {{/collection}}
              ```

              Will result in the following HTML structure:

              ```html
              <div class="ember-view">
                <p class="ember-view greeting">Howdy Dave</p>
                <p class="ember-view greeting">Howdy Mary</p>
                <p class="ember-view greeting">Howdy Sara</p>
              </div>
              ```

              @method collection
              @for Ember.Handlebars.helpers
              @param {String} path
              @param {Hash} options
              @return {String} HTML string
              @deprecated Use `{{each}}` helper instead.
            */
        function collectionHelper(path, options) {
            Ember.deprecate("Using the {{collection}} helper without specifying a class has been deprecated as the {{each}} helper now supports the same functionality.", path !== 'collection');

            // If no path is provided, treat path param as options.
            if (path && path.data && path.data.isRenderData) {
                options = path;
                path = undefined;
                Ember.assert("You cannot pass more than one argument to the collection helper", arguments.length === 1);
            } else {
                Ember.assert("You cannot pass more than one argument to the collection helper", arguments.length === 2);
            }

            var fn = options.fn;
            var data = options.data;
            var inverse = options.inverse;
            var view = options.data.view;


            var controller, container;
            // If passed a path string, convert that into an object.
            // Otherwise, just default to the standard class.
            var collectionClass;
            if (path) {
                controller = data.keywords.controller;
                container = controller && controller.container;
                collectionClass = handlebarsGet(this, path, options) || container.lookupFactory('view:' + path);
                Ember.assert(fmt("%@ #collection: Could not find collection class %@", [data.view, path]), !!collectionClass);
            } else {
                collectionClass = CollectionView;
            }

            var hash = options.hash, itemHash = {}, match;

            // Extract item view class if provided else default to the standard class
            var collectionPrototype = collectionClass.proto(), itemViewClass;

            if (hash.itemView) {
                controller = data.keywords.controller;
                Ember.assert('You specified an itemView, but the current context has no ' +
                'container to look the itemView up in. This probably means ' +
                'that you created a view manually, instead of through the ' +
                'container. Instead, use container.lookup("view:viewName"), ' +
                'which will properly instantiate your view.',
                controller && controller.container);
                container = controller.container;
                itemViewClass = container.lookupFactory('view:' + hash.itemView);
                Ember.assert('You specified the itemView ' + hash.itemView + ", but it was " +
                "not found at " + container.describe("view:" + hash.itemView) +
                " (and it was not registered in the container)", !!itemViewClass);
            } else if (hash.itemViewClass) {
                itemViewClass = handlebarsGet(collectionPrototype, hash.itemViewClass, options);
            } else {
                itemViewClass = collectionPrototype.itemViewClass;
            }

            Ember.assert(fmt("%@ #collection: Could not find itemViewClass %@", [data.view, itemViewClass]), !!itemViewClass);

            delete hash.itemViewClass;
            delete hash.itemView;

            // Go through options passed to the {{collection}} helper and extract options
            // that configure item views instead of the collection itself.
            for (var prop in hash) {
                if (hash.hasOwnProperty(prop)) {
                    match = prop.match(/^item(.)(.*)$/);

                    if (match && prop !== 'itemController') {
                        // Convert itemShouldFoo -> shouldFoo
                        itemHash[match[1].toLowerCase() + match[2]] = hash[prop];
                        // Delete from hash as this will end up getting passed to the
                        // {{view}} helper method.
                        delete hash[prop];
                    }
                }
            }

            if (fn) {
                itemHash.template = fn;
                delete options.fn;
            }

            var emptyViewClass;
            if (inverse && inverse !== EmberHandlebars.VM.noop) {
                emptyViewClass = get(collectionPrototype, 'emptyViewClass');
                emptyViewClass = emptyViewClass.extend({
                    template: inverse,
                    tagName: itemHash.tagName
                });
            } else if (hash.emptyViewClass) {
                emptyViewClass = handlebarsGet(this, hash.emptyViewClass, options);
            }
            if (emptyViewClass) {
                hash.emptyView = emptyViewClass;
            }

            if (hash.keyword) {
                itemHash._context = this;
            } else {
                itemHash._context = alias('content');
            }

            var viewOptions = ViewHelper.propertiesFromHTMLOptions({
                data: data,
                hash: itemHash 
            }, this);
            hash.itemViewClass = itemViewClass.extend(viewOptions);

            options.helperName = options.helperName || 'collection';

            return helpers.view.call(this, collectionClass, options);
        }

        __exports__["default"] = collectionHelper;
    });
    define("ember-handlebars/helpers/debug",
    ["ember-metal/core", "ember-metal/utils", "ember-metal/logger", "ember-metal/property_get", "ember-handlebars/ext", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
        "use strict";
        /*jshint debug:true*/

        /**
            @module ember
            @submodule ember-handlebars
            */
        var Ember = __dependency1__["default"];
        // Ember.FEATURES,
        var inspect = __dependency2__.inspect;
        var Logger = __dependency3__["default"];

        var get = __dependency4__.get;
        var normalizePath = __dependency5__.normalizePath;
        var handlebarsGet = __dependency5__.handlebarsGet;

        var a_slice = [].slice;

        /**
              `log` allows you to output the value of variables in the current rendering
              context. `log` also accepts primitive types such as strings or numbers.

              ```handlebars
              {{log "myVariable:" myVariable }}
              ```

              @method log
              @for Ember.Handlebars.helpers
              @param {String} property
            */
        function logHelper() {
            var params = a_slice.call(arguments, 0, -1),
            options = arguments[arguments.length - 1],
            logger = Logger.log,
            values = [],
            allowPrimitives = true;

            for (var i = 0; i < params.length; i++) {
                var type = options.types[i];

                if (type === 'ID' || !allowPrimitives) {
                    var context = (options.contexts && options.contexts[i]) || this,
                    normalized = normalizePath(context, params[i], options.data);

                    if (normalized.path === 'this') {
                        values.push(normalized.root);
                    } else {
                        values.push(handlebarsGet(normalized.root, normalized.path, options));
                    }
                } else {
                    values.push(params[i]);
                }
            }

            logger.apply(logger, values);
        }

        /**
              Execute the `debugger` statement in the current context.

              ```handlebars
              {{debugger}}
              ```

              Before invoking the `debugger` statement, there
              are a few helpful variables defined in the
              body of this helper that you can inspect while
              debugging that describe how and where this
              helper was invoked:

              - templateContext: this is most likely a controller
                from which this template looks up / displays properties
              - typeOfTemplateContext: a string description of
                what the templateContext is

              For example, if you're wondering why a value `{{foo}}`
              isn't rendering as expected within a template, you
              could place a `{{debugger}}` statement, and when
              the `debugger;` breakpoint is hit, you can inspect
              `templateContext`, determine if it's the object you
              expect, and/or evaluate expressions in the console
              to perform property lookups on the `templateContext`:

              ```
                > templateContext.get('foo') // -> "<value of {{foo}}>"
              ```

              @method debugger
              @for Ember.Handlebars.helpers
              @param {String} property
            */
        function debuggerHelper(options) {

            // These are helpful values you can inspect while debugging.
            var templateContext = this;
            var typeOfTemplateContext = inspect(templateContext);
            Ember.Logger.info('Use `this` to access the context of the calling template.');

            debugger;
        }

        __exports__.logHelper = logHelper;
        __exports__.debuggerHelper = debuggerHelper;
    });
    define("ember-handlebars/helpers/each",
    ["ember-metal/core", "ember-handlebars-compiler", "ember-runtime/system/string", "ember-metal/property_get", "ember-metal/property_set", "ember-views/views/collection_view", "ember-metal/binding", "ember-runtime/mixins/controller", "ember-runtime/controllers/array_controller", "ember-runtime/mixins/array", "ember-runtime/copy", "ember-metal/run_loop", "ember-metal/events", "ember-handlebars/ext", "ember-metal/computed", "ember-metal/observer", "ember-handlebars/views/metamorph_view", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __exports__) {
        "use strict";

        /**
            @module ember
            @submodule ember-handlebars
            */
        var Ember = __dependency1__["default"];
        // Ember.assert;, Ember.K
        // var emberAssert = Ember.assert,
        var K = Ember.K;

        var EmberHandlebars = __dependency2__["default"];
        var helpers = EmberHandlebars.helpers;

        var fmt = __dependency3__.fmt;
        var get = __dependency4__.get;
        var set = __dependency5__.set;
        var CollectionView = __dependency6__["default"];
        var Binding = __dependency7__.Binding;
        var ControllerMixin = __dependency8__["default"];
        var ArrayController = __dependency9__["default"];
        var EmberArray = __dependency10__["default"];
        var copy = __dependency11__["default"];
        var run = __dependency12__["default"];
        var on = __dependency13__.on;
        var handlebarsGet = __dependency14__.handlebarsGet;
        var computed = __dependency15__.computed;

        var addObserver = __dependency16__.addObserver;
        var removeObserver = __dependency16__.removeObserver;
        var addBeforeObserver = __dependency16__.addBeforeObserver;
        var removeBeforeObserver = __dependency16__.removeBeforeObserver;

        var _Metamorph = __dependency17__._Metamorph;
        var _MetamorphView = __dependency17__._MetamorphView;

        var EachView = CollectionView.extend(_Metamorph, {

            init: function() {
                var itemController = get(this, 'itemController');
                var binding;

                if (itemController) {
                    var controller = get(this, 'controller.container').lookupFactory('controller:array').create({
                        _isVirtual: true,
                        parentController: get(this, 'controller'),
                        itemController: itemController,
                        target: get(this, 'controller'),
                        _eachView: this
                    });

                    this.disableContentObservers(function() {
                        set(this, 'content', controller);
                        binding = new Binding('content', '_eachView.dataSource').oneWay();
                        binding.connect(controller);
                    });

                    set(this, '_arrayController', controller);
                } else {
                    this.disableContentObservers(function() {
                        binding = new Binding('content', 'dataSource').oneWay();
                        binding.connect(this);
                    });
                }

                return this._super();
            },

            _assertArrayLike: function(content) {
                Ember.assert(fmt("The value that #each loops over must be an Array. You " +
                "passed %@, but it should have been an ArrayController",
                [content.constructor]),
                !ControllerMixin.detect(content) ||
                (content && content.isGenerated) ||
                content instanceof ArrayController);
                Ember.assert(fmt("The value that #each loops over must be an Array. You passed %@", [(ControllerMixin.detect(content) && content.get('model') !== undefined) ? fmt("'%@' (wrapped in %@)", [content.get('model'), content]) : content]), EmberArray.detect(content));
            },

            disableContentObservers: function(callback) {
                removeBeforeObserver(this, 'content', null, '_contentWillChange');
                removeObserver(this, 'content', null, '_contentDidChange');

                callback.call(this);

                addBeforeObserver(this, 'content', null, '_contentWillChange');
                addObserver(this, 'content', null, '_contentDidChange');
            },

            itemViewClass: _MetamorphView,
            emptyViewClass: _MetamorphView,

            createChildView: function(view, attrs) {
                view = this._super(view, attrs);

                // At the moment, if a container view subclass wants
                // to insert keywords, it is responsible for cloning
                // the keywords hash. This will be fixed momentarily.
                var keyword = get(this, 'keyword');
                var content = get(view, 'content');

                if (keyword) {
                    var data = get(view, 'templateData');

                    data = copy(data);
                    data.keywords = view.cloneKeywords();
                    set(view, 'templateData', data);

                    // In this case, we do not bind, because the `content` of
                    // a #each item cannot change.
                    data.keywords[keyword] = content;
                }

                // If {{#each}} is looping over an array of controllers,
                // point each child view at their respective controller.
                if (content && content.isController) {
                    set(view, 'controller', content);
                }

                return view;
            },

            destroy: function() {
                if (!this._super()) {
                    return;
                }

                var arrayController = get(this, '_arrayController');

                if (arrayController) {
                    arrayController.destroy();
                }

                return this;
            }
        });

        // Defeatureify doesn't seem to like nested functions that need to be removed
        function _addMetamorphCheck() {
            EachView.reopen({
                _checkMetamorph: on('didInsertElement', function() {
                    Ember.assert("The metamorph tags, " +
                    this.morph.start + " and " + this.morph.end +
                    ", have different parents.\nThe browser has fixed your template to output valid HTML (for example, check that you have properly closed all tags and have used a TBODY tag when creating a table with '{{#each}}')",
                    document.getElementById( this.morph.start ).parentNode ===
                    document.getElementById( this.morph.end ).parentNode
                    );
                })
            });
        }

        // until ember-debug is es6ed
        var runInDebug = function(f) {
            f();
        };
        runInDebug( function() {
            _addMetamorphCheck();
        });

        var GroupedEach = EmberHandlebars.GroupedEach = function(context, path, options) {
            var self = this,
            normalized = EmberHandlebars.normalizePath(context, path, options.data);

            this.context = context;
            this.path = path;
            this.options = options;
            this.template = options.fn;
            this.containingView = options.data.view;
            this.normalizedRoot = normalized.root;
            this.normalizedPath = normalized.path;
            this.content = this.lookupContent();

            this.addContentObservers();
            this.addArrayObservers();

            this.containingView.on('willClearRender', function() {
                self.destroy();
            });
        };

        GroupedEach.prototype = {
            contentWillChange: function() {
                this.removeArrayObservers();
            },

            contentDidChange: function() {
                this.content = this.lookupContent();
                this.addArrayObservers();
                this.rerenderContainingView();
            },

            contentArrayWillChange: K,

            contentArrayDidChange: function() {
                this.rerenderContainingView();
            },

            lookupContent: function() {
                return handlebarsGet(this.normalizedRoot, this.normalizedPath, this.options);
            },

            addArrayObservers: function() {
                if (!this.content) {
                    return;
                }

                this.content.addArrayObserver(this, {
                    willChange: 'contentArrayWillChange',
                    didChange: 'contentArrayDidChange'
                });
            },

            removeArrayObservers: function() {
                if (!this.content) {
                    return;
                }

                this.content.removeArrayObserver(this, {
                    willChange: 'contentArrayWillChange',
                    didChange: 'contentArrayDidChange'
                });
            },

            addContentObservers: function() {
                addBeforeObserver(this.normalizedRoot, this.normalizedPath, this, this.contentWillChange);
                addObserver(this.normalizedRoot, this.normalizedPath, this, this.contentDidChange);
            },

            removeContentObservers: function() {
                removeBeforeObserver(this.normalizedRoot, this.normalizedPath, this.contentWillChange);
                removeObserver(this.normalizedRoot, this.normalizedPath, this.contentDidChange);
            },

            render: function() {
                if (!this.content) {
                    return;
                }

                var content = this.content,
                contentLength = get(content, 'length'),
                options = this.options,
                data = options.data,
                template = this.template;

                data.insideEach = true;
                for (var i = 0; i < contentLength; i++) {
                    var context = content.objectAt(i);
                    options.data.keywords[options.hash.keyword] = context;
                    template(context, {
                        data: data 
                    });
                }
            },

            rerenderContainingView: function() {
                var self = this;
                run.scheduleOnce('render', this, function() {
                    // It's possible it's been destroyed after we enqueued a re-render call.
                    if (!self.destroyed) {
                        self.containingView.rerender();
                    }
                });
            },

            destroy: function() {
                this.removeContentObservers();
                if (this.content) {
                    this.removeArrayObservers();
                }
                this.destroyed = true;
            }
        };

        /**
              The `{{#each}}` helper loops over elements in a collection, rendering its
              block once for each item. It is an extension of the base Handlebars `{{#each}}`
              helper:

              ```javascript
              Developers = [{name: 'Yehuda'},{name: 'Tom'}, {name: 'Paul'}];
              ```

              ```handlebars
              {{#each Developers}}
                {{name}}
              {{/each}}
              ```

              `{{each}}` supports an alternative syntax with element naming:

              ```handlebars
              {{#each person in Developers}}
                {{person.name}}
              {{/each}}
              ```

              When looping over objects that do not have properties, `{{this}}` can be used
              to render the object:

              ```javascript
              DeveloperNames = ['Yehuda', 'Tom', 'Paul']
              ```

              ```handlebars
              {{#each DeveloperNames}}
                {{this}}
              {{/each}}
              ```
              ### {{else}} condition
              `{{#each}}` can have a matching `{{else}}`. The contents of this block will render
              if the collection is empty.

              ```
              {{#each person in Developers}}
                {{person.name}}
              {{else}}
                <p>Sorry, nobody is available for this task.</p>
              {{/each}}
              ```
              ### Specifying a View class for items
              If you provide an `itemViewClass` option that references a view class
              with its own `template` you can omit the block.

              The following template:

              ```handlebars
              {{#view App.MyView }}
                {{each view.items itemViewClass="App.AnItemView"}}
              {{/view}}
              ```

              And application code

              ```javascript
              App = Ember.Application.create({
                MyView: Ember.View.extend({
                  items: [
                    Ember.Object.create({name: 'Dave'}),
                    Ember.Object.create({name: 'Mary'}),
                    Ember.Object.create({name: 'Sara'})
                  ]
                })
              });

              App.AnItemView = Ember.View.extend({
                template: Ember.Handlebars.compile("Greetings {{name}}")
              });
              ```

              Will result in the HTML structure below

              ```html
              <div class="ember-view">
                <div class="ember-view">Greetings Dave</div>
                <div class="ember-view">Greetings Mary</div>
                <div class="ember-view">Greetings Sara</div>
              </div>
              ```

              If an `itemViewClass` is defined on the helper, and therefore the helper is not
              being used as a block, an `emptyViewClass` can also be provided optionally.
              The `emptyViewClass` will match the behavior of the `{{else}}` condition
              described above. That is, the `emptyViewClass` will render if the collection
              is empty.

              ### Representing each item with a Controller.
              By default the controller lookup within an `{{#each}}` block will be
              the controller of the template where the `{{#each}}` was used. If each
              item needs to be presented by a custom controller you can provide a
              `itemController` option which references a controller by lookup name.
              Each item in the loop will be wrapped in an instance of this controller
              and the item itself will be set to the `model` property of that controller.

              This is useful in cases where properties of model objects need transformation
              or synthesis for display:

              ```javascript
              App.DeveloperController = Ember.ObjectController.extend({
                isAvailableForHire: function() {
                  return !this.get('model.isEmployed') && this.get('model.isSeekingWork');
                }.property('isEmployed', 'isSeekingWork')
              })
              ```

              ```handlebars
              {{#each person in developers itemController="developer"}}
                {{person.name}} {{#if person.isAvailableForHire}}Hire me!{{/if}}
              {{/each}}
              ```

              Each itemController will receive a reference to the current controller as
              a `parentController` property.

              ### (Experimental) Grouped Each

              When used in conjunction with the experimental [group helper](https://github.com/emberjs/group-helper),
              you can inform Handlebars to re-render an entire group of items instead of
              re-rendering them one at a time (in the event that they are changed en masse
              or an item is added/removed).

              ```handlebars
              {{#group}}
                {{#each people}}
                  {{firstName}} {{lastName}}
                {{/each}}
              {{/group}}
              ```

              This can be faster than the normal way that Handlebars re-renders items
              in some cases.

              If for some reason you have a group with more than one `#each`, you can make
              one of the collections be updated in normal (non-grouped) fashion by setting
              the option `groupedRows=true` (counter-intuitive, I know).

              For example,

              ```handlebars
              {{dealershipName}}

              {{#group}}
                {{#each dealers}}
                  {{firstName}} {{lastName}}
                {{/each}}

                {{#each car in cars groupedRows=true}}
                  {{car.make}} {{car.model}} {{car.color}}
                {{/each}}
              {{/group}}
              ```
              Any change to `dealershipName` or the `dealers` collection will cause the
              entire group to be re-rendered. However, changes to the `cars` collection
              will be re-rendered individually (as normal).

              Note that `group` behavior is also disabled by specifying an `itemViewClass`.

              @method each
              @for Ember.Handlebars.helpers
              @param [name] {String} name for item (used with `in`)
              @param [path] {String} path
              @param [options] {Object} Handlebars key/value pairs of options
              @param [options.itemViewClass] {String} a path to a view class used for each item
              @param [options.itemController] {String} name of a controller to be created for each item
              @param [options.groupedRows] {boolean} enable normal item-by-item rendering when inside a `#group` helper
            */
        function eachHelper(path, options) {
            var ctx, helperName = 'each';

            if (arguments.length === 4) {
                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");

                var keywordName = arguments[0];


                options = arguments[3];
                path = arguments[2];

                helperName += ' ' + keywordName + ' in ' + path;

                if (path === '') {
                    path = "this";
                }

                options.hash.keyword = keywordName;

            } else if (arguments.length === 1) {
                options = path;
                path = 'this';
            } else {
                helperName += ' ' + path;
            }

            options.hash.dataSourceBinding = path;
            // Set up emptyView as a metamorph with no tag
            //options.hash.emptyViewClass = Ember._MetamorphView;

            // can't rely on this default behavior when use strict
            ctx = this || window;

            options.helperName = options.helperName || helperName;

            if (options.data.insideGroup && !options.hash.groupedRows && !options.hash.itemViewClass) {
                new GroupedEach(ctx, path, options).render();
            } else {
                // ES6TODO: figure out how to do this without global lookup.
                return helpers.collection.call(ctx, 'Ember.Handlebars.EachView', options);
            }
        }

        __exports__.EachView = EachView;
        __exports__.GroupedEach = GroupedEach;
        __exports__.eachHelper = eachHelper;
    });
    define("ember-handlebars/helpers/loc",
    ["ember-runtime/system/string", "exports"],
    function(__dependency1__, __exports__) {
        "use strict";
        var loc = __dependency1__.loc;

        /**
            @module ember
            @submodule ember-handlebars
            */

        // ES6TODO:
        // Pretty sure this can be expressed as
        // var locHelper EmberStringUtils.loc ?

        /**
              Calls [Ember.String.loc](/api/classes/Ember.String.html#method_loc) with the
              provided string.

              This is a convenient way to localize text. For example:

              ```html
              <script type="text/x-handlebars" data-template-name="home">
                {{loc "welcome"}}
              </script>
              ```

              Take note that `"welcome"` is a string and not an object
              reference.

              See [Ember.String.loc](/api/classes/Ember.String.html#method_loc) for how to 
              set up localized string references.

              @method loc
              @for Ember.Handlebars.helpers
              @param {String} str The string to format
              @see {Ember.String#loc}
            */
        __exports__["default"] = function locHelper(str) {
            return loc(str);
        }
    });
    define("ember-handlebars/helpers/partial",
    ["ember-metal/core", "ember-metal/is_none", "ember-handlebars/ext", "ember-handlebars/helpers/binding", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // Ember.assert
        // var emberAssert = Ember.assert;

        var isNone = __dependency2__.isNone;
        var handlebarsGet = __dependency3__.handlebarsGet;
        var bind = __dependency4__.bind;

        /**
            @module ember
            @submodule ember-handlebars
            */

        /**
              The `partial` helper renders another template without
              changing the template context:

              ```handlebars
              {{foo}}
              {{partial "nav"}}
              ```

              The above example template will render a template named
              "_nav", which has the same context as the parent template
              it's rendered into, so if the "_nav" template also referenced
              `{{foo}}`, it would print the same thing as the `{{foo}}`
              in the above example.

              If a "_nav" template isn't found, the `partial` helper will
              fall back to a template named "nav".

              ## Bound template names

              The parameter supplied to `partial` can also be a path
              to a property containing a template name, e.g.:

              ```handlebars
              {{partial someTemplateName}}
              ```

              The above example will look up the value of `someTemplateName`
              on the template context (e.g. a controller) and use that
              value as the name of the template to render. If the resolved
              value is falsy, nothing will be rendered. If `someTemplateName`
              changes, the partial will be re-rendered using the new template
              name.

              ## Setting the partial's context with `with`

              The `partial` helper can be used in conjunction with the `with`
              helper to set a context that will be used by the partial:

              ```handlebars
              {{#with currentUser}}
                {{partial "user_info"}}
              {{/with}}
              ```

              @method partial
              @for Ember.Handlebars.helpers
              @param {String} partialName the name of the template to render minus the leading underscore
            */

        __exports__["default"] = function partialHelper(name, options) {

            var context = (options.contexts && options.contexts.length) ? options.contexts[0] : this;

            options.helperName = options.helperName || 'partial';

            if (options.types[0] === "ID") {
                // Helper was passed a property path; we need to
                // create a binding that will re-render whenever
                // this property changes.
                options.fn = function(context, fnOptions) {
                    var partialName = handlebarsGet(context, name, fnOptions);
                    renderPartial(context, partialName, fnOptions);
                };

                return bind.call(context, name, options, true, exists);
            } else {
                // Render the partial right into parent template.
                renderPartial(context, name, options);
            }
        }

        function exists(value) {
            return !isNone(value);
        }

        function renderPartial(context, name, options) {
            var nameParts = name.split("/");
            var lastPart = nameParts[nameParts.length - 1];

            nameParts[nameParts.length - 1] = "_" + lastPart;

            var view = options.data.view;
            var underscoredName = nameParts.join("/");
            var template = view.templateForName(underscoredName);
            var deprecatedTemplate = !template && view.templateForName(name);

            Ember.assert("Unable to find partial with name '" + name + "'.", template || deprecatedTemplate);

            template = template || deprecatedTemplate;

            template(context, {
                data: options.data 
            });
        }
    });
    define("ember-handlebars/helpers/shared",
    ["ember-handlebars/ext", "exports"],
    function(__dependency1__, __exports__) {
        "use strict";
        var handlebarsGet = __dependency1__.handlebarsGet;

        __exports__["default"] = function resolvePaths(options) {
            var ret = [],
            contexts = options.contexts,
            roots = options.roots,
            data = options.data;

            for (var i = 0, l = contexts.length; i < l; i++) {
                ret.push(handlebarsGet(roots[i], contexts[i], {
                    data: data 
                }));
            }

            return ret;
        }
    });
    define("ember-handlebars/helpers/template",
    ["ember-metal/core", "ember-handlebars-compiler", "exports"],
    function(__dependency1__, __dependency2__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // var emberDeprecate = Ember.deprecate;

        var EmberHandlebars = __dependency2__["default"];
        var helpers = EmberHandlebars.helpers;
        /**
            @module ember
            @submodule ember-handlebars
            */

        /**
              `template` allows you to render a template from inside another template.
              This allows you to re-use the same template in multiple places. For example:

              ```html
              <script type="text/x-handlebars" data-template-name="logged_in_user">
                {{#with loggedInUser}}
                  Last Login: {{lastLogin}}
                  User Info: {{template "user_info"}}
                {{/with}}
              </script>
              ```

              ```html
              <script type="text/x-handlebars" data-template-name="user_info">
                Name: <em>{{name}}</em>
                Karma: <em>{{karma}}</em>
              </script>
              ```

              ```handlebars
              {{#if isUser}}
                {{template "user_info"}}
              {{else}}
                {{template "unlogged_user_info"}}
              {{/if}}
              ```

              This helper looks for templates in the global `Ember.TEMPLATES` hash. If you
              add `<script>` tags to your page with the `data-template-name` attribute set,
              they will be compiled and placed in this hash automatically.

              You can also manually register templates by adding them to the hash:

              ```javascript
              Ember.TEMPLATES["my_cool_template"] = Ember.Handlebars.compile('<b>{{user}}</b>');
              ```

              @deprecated
              @method template
              @for Ember.Handlebars.helpers
              @param {String} templateName the template to render
            */
        __exports__["default"] = function templateHelper(name, options) {
            Ember.deprecate("The `template` helper has been deprecated in favor of the `partial` helper. Please use `partial` instead, which will work the same way.");

            options.helperName = options.helperName || 'template';

            return helpers.partial.apply(this, arguments);
        }
    });
    define("ember-handlebars/helpers/unbound",
    ["ember-handlebars-compiler", "ember-handlebars/helpers/binding", "ember-handlebars/ext", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        /*globals Handlebars */

        /**
            @module ember
            @submodule ember-handlebars
            */

        var EmberHandlebars = __dependency1__["default"];
        var helpers = EmberHandlebars.helpers;

        var resolveHelper = __dependency2__.resolveHelper;
        var handlebarsGet = __dependency3__.handlebarsGet;

        var slice = [].slice;

        /**
              `unbound` allows you to output a property without binding. *Important:* The
              output will not be updated if the property changes. Use with caution.

              ```handlebars
              <div>{{unbound somePropertyThatDoesntChange}}</div>
              ```

              `unbound` can also be used in conjunction with a bound helper to
              render it in its unbound form:

              ```handlebars
              <div>{{unbound helperName somePropertyThatDoesntChange}}</div>
              ```

              @method unbound
              @for Ember.Handlebars.helpers
              @param {String} property
              @return {String} HTML string
            */
        __exports__["default"] = function unboundHelper(property, fn) {
            var options = arguments[arguments.length - 1],
            container = options.data.view.container,
            helper, context, out, ctx;

            ctx = this;
            if (arguments.length > 2) {
                // Unbound helper call.
                options.data.isUnbound = true;
                helper = resolveHelper(container, property) || helpers.helperMissing;
                out = helper.apply(ctx, slice.call(arguments, 1));
                delete options.data.isUnbound;
                return out;
            }

            context = (fn.contexts && fn.contexts.length) ? fn.contexts[0] : ctx;
            return handlebarsGet(context, property, fn);
        }
    });
    define("ember-handlebars/helpers/view",
    ["ember-metal/core", "ember-runtime/system/object", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/mixin", "ember-views/system/jquery", "ember-views/views/view", "ember-metal/binding", "ember-handlebars/ext", "ember-runtime/system/string", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __exports__) {
        "use strict";
        /*globals Handlebars */

        /**
            @module ember
            @submodule ember-handlebars
            */

        var Ember = __dependency1__["default"];
        // Ember.warn, Ember.assert
        // var emberWarn = Ember.warn, emberAssert = Ember.assert;

        var EmberObject = __dependency2__["default"];
        var get = __dependency3__.get;
        var set = __dependency4__.set;
        var IS_BINDING = __dependency5__.IS_BINDING;
        var jQuery = __dependency6__["default"];
        var View = __dependency7__["default"];
        var isGlobalPath = __dependency8__.isGlobalPath;
        var normalizePath = __dependency9__.normalizePath;
        var handlebarsGet = __dependency9__.handlebarsGet;
        var EmberString = __dependency10__["default"];


        var LOWERCASE_A_Z = /^[a-z]/,
        VIEW_PREFIX = /^view\./;

        function makeBindings(thisContext, options) {
            var hash = options.hash,
            hashType = options.hashTypes;

            for (var prop in hash) {
                if (hashType[prop] === 'ID') {

                    var value = hash[prop];

                    if (IS_BINDING.test(prop)) {
                        Ember.warn("You're attempting to render a view by passing " + prop + "=" + value + " to a view helper, but this syntax is ambiguous. You should either surround " + value + " in quotes or remove `Binding` from " + prop + ".");
                    } else {
                        hash[prop + 'Binding'] = value;
                        hashType[prop + 'Binding'] = 'STRING';
                        delete hash[prop];
                        delete hashType[prop];
                    }
                }
            }

            if (hash.hasOwnProperty('idBinding')) {
                // id can't be bound, so just perform one-time lookup.
                hash.id = handlebarsGet(thisContext, hash.idBinding, options);
                hashType.id = 'STRING';
                delete hash.idBinding;
                delete hashType.idBinding;
            }
        }

        var ViewHelper = EmberObject.create({

            propertiesFromHTMLOptions: function(options) {
                var hash = options.hash, data = options.data;
                var extensions = {},
                classes = hash['class'],
                dup = false;

                if (hash.id) {
                    extensions.elementId = hash.id;
                    dup = true;
                }

                if (hash.tag) {
                    extensions.tagName = hash.tag;
                    dup = true;
                }

                if (classes) {
                    classes = classes.split(' ');
                    extensions.classNames = classes;
                    dup = true;
                }

                if (hash.classBinding) {
                    extensions.classNameBindings = hash.classBinding.split(' ');
                    dup = true;
                }

                if (hash.classNameBindings) {
                    if (extensions.classNameBindings === undefined) 
                        extensions.classNameBindings = [];
                    extensions.classNameBindings = extensions.classNameBindings.concat(hash.classNameBindings.split(' '));
                    dup = true;
                }

                if (hash.attributeBindings) {
                    Ember.assert("Setting 'attributeBindings' via Handlebars is not allowed. Please subclass Ember.View and set it there instead.");
                    extensions.attributeBindings = null;
                    dup = true;
                }

                if (dup) {
                    hash = jQuery.extend({}, hash);
                    delete hash.id;
                    delete hash.tag;
                    delete hash['class'];
                    delete hash.classBinding;
                }

                // Set the proper context for all bindings passed to the helper. This applies to regular attribute bindings
                // as well as class name bindings. If the bindings are local, make them relative to the current context
                // instead of the view.
                var path;

                // Evaluate the context of regular attribute bindings:
                for (var prop in hash) {
                    if (!hash.hasOwnProperty(prop)) {
                        continue;
                    }

                    // Test if the property ends in "Binding"
                    if (IS_BINDING.test(prop) && typeof hash[prop] === 'string') {
                        path = this.contextualizeBindingPath(hash[prop], data);
                        if (path) {
                            hash[prop] = path;
                        }
                    }
                }

                // Evaluate the context of class name bindings:
                if (extensions.classNameBindings) {
                    for (var b in extensions.classNameBindings) {
                        var full = extensions.classNameBindings[b];
                        if (typeof full === 'string') {
                            // Contextualize the path of classNameBinding so this:
                            //
                            //     classNameBinding="isGreen:green"
                            //
                            // is converted to this:
                            //
                            //     classNameBinding="_parentView.context.isGreen:green"
                            var parsedPath = View._parsePropertyPath(full);
                            path = this.contextualizeBindingPath(parsedPath.path, data);
                            if (path) {
                                extensions.classNameBindings[b] = path + parsedPath.classNames;
                            }
                        }
                    }
                }

                return jQuery.extend(hash, extensions);
            },

            // Transform bindings from the current context to a context that can be evaluated within the view.
            // Returns null if the path shouldn't be changed.
            //
            // TODO: consider the addition of a prefix that would allow this method to return `path`.
            contextualizeBindingPath: function(path, data) {
                var normalized = normalizePath(null, path, data);
                if (normalized.isKeyword) {
                    return 'templateData.keywords.' + path;
                } else if (isGlobalPath(path)) {
                    return null;
                } else if (path === 'this' || path === '') {
                    return '_parentView.context';
                } else {
                    return '_parentView.context.' + path;
                }
            },

            helper: function(thisContext, path, options) {
                var data = options.data,
                fn = options.fn,
                newView;

                makeBindings(thisContext, options);

                if ('string' === typeof path) {
                    var lookup;
                    // TODO: this is a lame conditional, this should likely change
                    // but something along these lines will likely need to be added
                    // as deprecation warnings
                    //
                    if (options.types[0] === 'STRING' && LOWERCASE_A_Z.test(path) && !VIEW_PREFIX.test(path)) {
                        lookup = path;
                    } else {
                        newView = handlebarsGet(thisContext, path, options);
                        if (typeof newView === 'string') {
                            lookup = newView;
                        }
                    }

                    if (lookup) {
                        Ember.assert("View requires a container", !!data.view.container);
                        newView = data.view.container.lookupFactory('view:' + lookup);
                    }

                    Ember.assert("Unable to find view at path '" + path + "'", !!newView);
                } else {
                    newView = path;
                }

                Ember.assert(EmberString.fmt('You must pass a view to the #view helper, not %@ (%@)', [path, newView]), View.detect(newView) || View.detectInstance(newView));

                var viewOptions = this.propertiesFromHTMLOptions(options, thisContext);
                var currentView = data.view;
                viewOptions.templateData = data;
                var newViewProto = newView.proto ? newView.proto() : newView;

                if (fn) {
                    Ember.assert("You cannot provide a template block if you also specified a templateName", !get(viewOptions, 'templateName') && !get(newViewProto, 'templateName'));
                    viewOptions.template = fn;
                }

                // We only want to override the `_context` computed property if there is
                // no specified controller. See View#_context for more information.
                if (!newViewProto.controller && !newViewProto.controllerBinding && !viewOptions.controller && !viewOptions.controllerBinding) {
                    viewOptions._context = thisContext;
                }

                // for instrumentation
                if (options.helperName) {
                    viewOptions.helperName = options.helperName;
                }

                currentView.appendChild(newView, viewOptions);
            }
        });
        __exports__.ViewHelper = ViewHelper;
        /**
              `{{view}}` inserts a new instance of an `Ember.View` into a template passing its
              options to the `Ember.View`'s `create` method and using the supplied block as
              the view's own template.

              An empty `<body>` and the following template:

              ```handlebars
              A span:
              {{#view tagName="span"}}
                hello.
              {{/view}}
              ```

              Will result in HTML structure:

              ```html
              <body>
                <!-- Note: the handlebars template script
                     also results in a rendered Ember.View
                     which is the outer <div> here -->

                <div class="ember-view">
                  A span:
                  <span id="ember1" class="ember-view">
                    Hello.
                  </span>
                </div>
              </body>
              ```

              ### `parentView` setting

              The `parentView` property of the new `Ember.View` instance created through
              `{{view}}` will be set to the `Ember.View` instance of the template where
              `{{view}}` was called.

              ```javascript
              aView = Ember.View.create({
                template: Ember.Handlebars.compile("{{#view}} my parent: {{parentView.elementId}} {{/view}}")
              });

              aView.appendTo('body');
              ```

              Will result in HTML structure:

              ```html
              <div id="ember1" class="ember-view">
                <div id="ember2" class="ember-view">
                  my parent: ember1
                </div>
              </div>
              ```

              ### Setting CSS id and class attributes

              The HTML `id` attribute can be set on the `{{view}}`'s resulting element with
              the `id` option. This option will _not_ be passed to `Ember.View.create`.

              ```handlebars
              {{#view tagName="span" id="a-custom-id"}}
                hello.
              {{/view}}
              ```

              Results in the following HTML structure:

              ```html
              <div class="ember-view">
                <span id="a-custom-id" class="ember-view">
                  hello.
                </span>
              </div>
              ```

              The HTML `class` attribute can be set on the `{{view}}`'s resulting element
              with the `class` or `classNameBindings` options. The `class` option will
              directly set the CSS `class` attribute and will not be passed to
              `Ember.View.create`. `classNameBindings` will be passed to `create` and use
              `Ember.View`'s class name binding functionality:

              ```handlebars
              {{#view tagName="span" class="a-custom-class"}}
                hello.
              {{/view}}
              ```

              Results in the following HTML structure:

              ```html
              <div class="ember-view">
                <span id="ember2" class="ember-view a-custom-class">
                  hello.
                </span>
              </div>
              ```

              ### Supplying a different view class

              `{{view}}` can take an optional first argument before its supplied options to
              specify a path to a custom view class.

              ```handlebars
              {{#view "MyApp.CustomView"}}
                hello.
              {{/view}}
              ```

              The first argument can also be a relative path accessible from the current
              context.

              ```javascript
              MyApp = Ember.Application.create({});
              MyApp.OuterView = Ember.View.extend({
                innerViewClass: Ember.View.extend({
                  classNames: ['a-custom-view-class-as-property']
                }),
                template: Ember.Handlebars.compile('{{#view "view.innerViewClass"}} hi {{/view}}')
              });

              MyApp.OuterView.create().appendTo('body');
              ```

              Will result in the following HTML:

              ```html
              <div id="ember1" class="ember-view">
                <div id="ember2" class="ember-view a-custom-view-class-as-property">
                  hi
                </div>
              </div>
              ```

              ### Blockless use

              If you supply a custom `Ember.View` subclass that specifies its own template
              or provide a `templateName` option to `{{view}}` it can be used without
              supplying a block. Attempts to use both a `templateName` option and supply a
              block will throw an error.

              ```handlebars
              {{view "MyApp.ViewWithATemplateDefined"}}
              ```

              ### `viewName` property

              You can supply a `viewName` option to `{{view}}`. The `Ember.View` instance
              will be referenced as a property of its parent view by this name.

              ```javascript
              aView = Ember.View.create({
                template: Ember.Handlebars.compile('{{#view viewName="aChildByName"}} hi {{/view}}')
              });

              aView.appendTo('body');
              aView.get('aChildByName') // the instance of Ember.View created by {{view}} helper
              ```

              @method view
              @for Ember.Handlebars.helpers
              @param {String} path
              @param {Hash} options
              @return {String} HTML string
            */
        function viewHelper(path, options) {
            Ember.assert("The view helper only takes a single argument", arguments.length <= 2);

            // If no path is provided, treat path param as options
            // and get an instance of the registered `view:toplevel`
            if (path && path.data && path.data.isRenderData) {
                options = path;
                Ember.assert('{{view}} helper requires parent view to have a container but none was found. This usually happens when you are manually-managing views.', !!options.data.view.container);
                path = options.data.view.container.lookupFactory('view:toplevel');
            }

            options.helperName = options.helperName || 'view';

            return ViewHelper.helper(this, path, options);
        }

        __exports__.viewHelper = viewHelper;
    });
    define("ember-handlebars/helpers/yield",
    ["ember-metal/core", "ember-metal/property_get", "exports"],
    function(__dependency1__, __dependency2__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-handlebars
            */

        var Ember = __dependency1__["default"];
        // var emberAssert = Ember.assert;

        var get = __dependency2__.get;

        /**
              `{{yield}}` denotes an area of a template that will be rendered inside
              of another template. It has two main uses:

              ### Use with `layout`
              When used in a Handlebars template that is assigned to an `Ember.View`
              instance's `layout` property Ember will render the layout template first,
              inserting the view's own rendered output at the `{{yield}}` location.

              An empty `<body>` and the following application code:

              ```javascript
              AView = Ember.View.extend({
                classNames: ['a-view-with-layout'],
                layout: Ember.Handlebars.compile('<div class="wrapper">{{yield}}</div>'),
                template: Ember.Handlebars.compile('<span>I am wrapped</span>')
              });

              aView = AView.create();
              aView.appendTo('body');
              ```

              Will result in the following HTML output:

              ```html
              <body>
                <div class='ember-view a-view-with-layout'>
                  <div class="wrapper">
                    <span>I am wrapped</span>
                  </div>
                </div>
              </body>
              ```

              The `yield` helper cannot be used outside of a template assigned to an
              `Ember.View`'s `layout` property and will throw an error if attempted.

              ```javascript
              BView = Ember.View.extend({
                classNames: ['a-view-with-layout'],
                template: Ember.Handlebars.compile('{{yield}}')
              });

              bView = BView.create();
              bView.appendTo('body');

              // throws
              // Uncaught Error: assertion failed:
              // You called yield in a template that was not a layout
              ```

              ### Use with Ember.Component
              When designing components `{{yield}}` is used to denote where, inside the component's
              template, an optional block passed to the component should render:

              ```handlebars
              <!-- application.hbs -->
              {{#labeled-textfield value=someProperty}}
                First name:
              {{/labeled-textfield}}
              ```

              ```handlebars
              <!-- components/labeled-textfield.hbs -->
              <label>
                {{yield}} {{input value=value}}
              </label>
              ```

              Result:

              ```html
              <label>
                First name: <input type="text" />
              </label>
              ```

              @method yield
              @for Ember.Handlebars.helpers
              @param {Hash} options
              @return {String} HTML string
            */
        __exports__["default"] = function yieldHelper(options) {
            var view = options.data.view;

            while (view && !get(view, 'layout')) {
                if (view._contextView) {
                    view = view._contextView;
                } else {
                    view = get(view, '_parentView');
                }
            }

            Ember.assert("You called yield in a template that was not a layout", !!view);

            view._yield(this, options);
        }
    });
    define("ember-handlebars/loader",
    ["ember-handlebars/component_lookup", "ember-views/system/jquery", "ember-metal/error", "ember-runtime/system/lazy_load", "ember-handlebars-compiler", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
        "use strict";
        /*globals Handlebars */

        var ComponentLookup = __dependency1__["default"];
        var jQuery = __dependency2__["default"];
        var EmberError = __dependency3__["default"];
        var onLoad = __dependency4__.onLoad;

        var EmberHandlebars = __dependency5__["default"];

        /**
            @module ember
            @submodule ember-handlebars
            */

        /**
              Find templates stored in the head tag as script tags and make them available
              to `Ember.CoreView` in the global `Ember.TEMPLATES` object. This will be run
              as as jQuery DOM-ready callback.

              Script tags with `text/x-handlebars` will be compiled
              with Ember's Handlebars and are suitable for use as a view's template.
              Those with type `text/x-raw-handlebars` will be compiled with regular
              Handlebars and are suitable for use in views' computed properties.

              @private
              @method bootstrap
              @for Ember.Handlebars
              @static
              @param ctx
            */
        function bootstrap(ctx) {
            var selectors = 'script[type="text/x-handlebars"], script[type="text/x-raw-handlebars"]';

            jQuery(selectors, ctx)
            .each(function() {
                // Get a reference to the script tag
                var script = jQuery(this);

                var compile = (script.attr('type') === 'text/x-raw-handlebars') ?
                jQuery.proxy(Handlebars.compile, Handlebars) :
                jQuery.proxy(EmberHandlebars.compile, EmberHandlebars),
                // Get the name of the script, used by Ember.View's templateName property.
                // First look for data-template-name attribute, then fall back to its
                // id if no name is found.
                templateName = script.attr('data-template-name') || script.attr('id') || 'application',
                template = compile(script.html());

                // Check if template of same name already exists
                if (Ember.TEMPLATES[templateName] !== undefined) {
                    throw new EmberError('Template named "' + templateName + '" already exists.');
                }

                // For templates which have a name, we save them and then remove them from the DOM
                Ember.TEMPLATES[templateName] = template;

                // Remove script tag from DOM
                script.remove();
            });
        }

        function _bootstrap() {
            bootstrap( jQuery(document) );
        }

        function registerComponentLookup(container) {
            container.register('component-lookup:main', ComponentLookup);
        }

        /*
              We tie this to application.load to ensure that we've at least
              attempted to bootstrap at the point that the application is loaded.

              We also tie this to document ready since we're guaranteed that all
              the inline templates are present at this point.

              There's no harm to running this twice, since we remove the templates
              from the DOM after processing.
            */

        onLoad('Ember.Application', function(Application) {
            Application.initializer({
                name: 'domTemplates',
                initialize: _bootstrap
            });

            Application.initializer({
                name: 'registerComponentLookup',
                after: 'domTemplates',
                initialize: registerComponentLookup
            });
        });

        __exports__["default"] = bootstrap;
    });
    define("ember-handlebars/string",
    ["ember-runtime/system/string", "exports"],
    function(__dependency1__, __exports__) {
        "use strict";
        // required so we can extend this object.
        var EmberStringUtils = __dependency1__["default"];

        /**
              Mark a string as safe for unescaped output with Handlebars. If you
              return HTML from a Handlebars helper, use this function to
              ensure Handlebars does not escape the HTML.

              ```javascript
              Ember.String.htmlSafe('<div>someString</div>')
              ```

              @method htmlSafe
              @for Ember.String
              @static
              @return {Handlebars.SafeString} a string that will not be html escaped by Handlebars
            */
        function htmlSafe(str) {
            return new Handlebars.SafeString(str);
        }

        EmberStringUtils.htmlSafe = htmlSafe;
        if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {

            /**
                    Mark a string as being safe for unescaped output with Handlebars.

                    ```javascript
                    '<div>someString</div>'.htmlSafe()
                    ```

                    See [Ember.String.htmlSafe](/api/classes/Ember.String.html#method_htmlSafe).

                    @method htmlSafe
                    @for String
                    @return {Handlebars.SafeString} a string that will not be html escaped by Handlebars
                  */
            String.prototype.htmlSafe = function() {
                return htmlSafe(this);
            };
        }

        __exports__["default"] = htmlSafe;
    });
    define("ember-handlebars/views/handlebars_bound_view",
    ["ember-handlebars-compiler", "ember-metal/core", "ember-metal/error", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/merge", "ember-metal/run_loop", "ember-metal/computed", "ember-views/views/view", "ember-views/views/states", "ember-handlebars/views/metamorph_view", "ember-handlebars/ext", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __exports__) {
        "use strict";
        /*globals Handlebars, Metamorph:true */
        /*jshint newcap:false*/


        /**
            @module ember
            @submodule ember-handlebars
            */

        var EmberHandlebars = __dependency1__["default"];
        // EmberHandlebars.SafeString;
        var SafeString = EmberHandlebars.SafeString;

        var Ember = __dependency2__["default"];
        // Ember.K
        var K = Ember.K;

        var Metamorph = requireModule('metamorph');

        var EmberError = __dependency3__["default"];
        var get = __dependency4__.get;
        var set = __dependency5__.set;
        var merge = __dependency6__["default"];
        var run = __dependency7__["default"];
        var computed = __dependency8__.computed;
        var View = __dependency9__["default"];
        var cloneStates = __dependency10__.cloneStates;
        var states = __dependency10__.states;
        var viewStates = states;

        var _MetamorphView = __dependency11__["default"];
        var handlebarsGet = __dependency12__.handlebarsGet;

        function SimpleHandlebarsView(path, pathRoot, isEscaped, templateData) {
            this.path = path;
            this.pathRoot = pathRoot;
            this.isEscaped = isEscaped;
            this.templateData = templateData;

            this._lastNormalizedValue = undefined;
            this.morph = Metamorph();
            this.state = 'preRender';
            this.updateId = null;
            this._parentView = null;
            this.buffer = null;
        }

        SimpleHandlebarsView.prototype = {
            isVirtual: true,
            isView: true,

            destroy: function () {
                if (this.updateId) {
                    run.cancel(this.updateId);
                    this.updateId = null;
                }
                if (this._parentView) {
                    this._parentView.removeChild(this);
                }
                this.morph = null;
                this.state = 'destroyed';
            },

            propertyWillChange: K,

            propertyDidChange: K,

            normalizedValue: function() {
                var path = this.path;
                var pathRoot = this.pathRoot;
                var result, templateData;

                // Use the pathRoot as the result if no path is provided. This
                // happens if the path is `this`, which gets normalized into
                // a `pathRoot` of the current Handlebars context and a path
                // of `''`.
                if (path === '') {
                    result = pathRoot;
                } else {
                    templateData = this.templateData;
                    result = handlebarsGet(pathRoot, path, {
                        data: templateData 
                    });
                }

                return result;
            },

            renderToBuffer: function(buffer) {
                var string = '';

                string += this.morph.startTag();
                string += this.render();
                string += this.morph.endTag();

                buffer.push(string);
            },

            render: function(value) {
                // If not invoked via a triple-mustache ({{{foo}}}), escape
                // the content of the template.
                var escape = this.isEscaped;
                var result = value || this.normalizedValue();
                this._lastNormalizedValue = result;
                if (result === null || result === undefined) {
                    result = "";
                } else if (!(result instanceof SafeString)) {
                    result = String(result);
                }

                if (escape) {
                    result = Handlebars.Utils.escapeExpression(result);
                }
                return result;
            },

            rerender: function() {
                switch (this.state) {
                case 'preRender':
                case 'destroyed':
                    break;
                case 'inBuffer':
                    throw new EmberError("Something you did tried to replace an {{expression}} before it was inserted into the DOM.");
                case 'hasElement':
                case 'inDOM':
                    this.updateId = run.scheduleOnce('render', this, 'update');
                    break;
                }

                return this;
            },

            update: function () {
                this.updateId = null;
                var value = this.normalizedValue();
                if (value !== this._lastNormalizedValue) {
                    this.morph.html(this.render(value));
                }
            },

            _transitionTo: function(state) {
                this.state = state;
            }
        };

        states = cloneStates(viewStates);

        merge(states._default, {
            rerenderIfNeeded: K
        });

        merge(states.inDOM, {
            rerenderIfNeeded: function(view) {
                if (view.normalizedValue() !== view._lastNormalizedValue) {
                    view.rerender();
                }
            }
        });

        /**
              `Ember._HandlebarsBoundView` is a private view created by the Handlebars
              `{{bind}}` helpers that is used to keep track of bound properties.

              Every time a property is bound using a `{{mustache}}`, an anonymous subclass
              of `Ember._HandlebarsBoundView` is created with the appropriate sub-template
              and context set up. When the associated property changes, just the template
              for this view will re-render.

              @class _HandlebarsBoundView
              @namespace Ember
              @extends Ember._MetamorphView
              @private
            */
        var _HandlebarsBoundView = _MetamorphView.extend({
            instrumentName: 'boundHandlebars',

            _states: states,

            /**
                    The function used to determine if the `displayTemplate` or
                    `inverseTemplate` should be rendered. This should be a function that takes
                    a value and returns a Boolean.

                    @property shouldDisplayFunc
                    @type Function
                    @default null
                  */
            shouldDisplayFunc: null,

            /**
                    Whether the template rendered by this view gets passed the context object
                    of its parent template, or gets passed the value of retrieving `path`
                    from the `pathRoot`.

                    For example, this is true when using the `{{#if}}` helper, because the
                    template inside the helper should look up properties relative to the same
                    object as outside the block. This would be `false` when used with `{{#with
                    foo}}` because the template should receive the object found by evaluating
                    `foo`.

                    @property preserveContext
                    @type Boolean
                    @default false
                  */
            preserveContext: false,

            /**
                    If `preserveContext` is true, this is the object that will be used
                    to render the template.

                    @property previousContext
                    @type Object
                  */
            previousContext: null,

            /**
                    The template to render when `shouldDisplayFunc` evaluates to `true`.

                    @property displayTemplate
                    @type Function
                    @default null
                  */
            displayTemplate: null,

            /**
                    The template to render when `shouldDisplayFunc` evaluates to `false`.

                    @property inverseTemplate
                    @type Function
                    @default null
                  */
            inverseTemplate: null,


            /**
                    The path to look up on `pathRoot` that is passed to
                    `shouldDisplayFunc` to determine which template to render.

                    In addition, if `preserveContext` is `false,` the object at this path will
                    be passed to the template when rendering.

                    @property path
                    @type String
                    @default null
                  */
            path: null,

            /**
                    The object from which the `path` will be looked up. Sometimes this is the
                    same as the `previousContext`, but in cases where this view has been
                    generated for paths that start with a keyword such as `view` or
                    `controller`, the path root will be that resolved object.

                    @property pathRoot
                    @type Object
                  */
            pathRoot: null,

            normalizedValue: function() {
                var path = get(this, 'path'),
                pathRoot = get(this, 'pathRoot'),
                valueNormalizer = get(this, 'valueNormalizerFunc'),
                result, templateData;

                // Use the pathRoot as the result if no path is provided. This
                // happens if the path is `this`, which gets normalized into
                // a `pathRoot` of the current Handlebars context and a path
                // of `''`.
                if (path === '') {
                    result = pathRoot;
                } else {
                    templateData = get(this, 'templateData');
                    result = handlebarsGet(pathRoot, path, {
                        data: templateData 
                    });
                }

                return valueNormalizer ? valueNormalizer(result) : result;
            },

            rerenderIfNeeded: function() {
                this.currentState.rerenderIfNeeded(this);
            },

            /**
                    Determines which template to invoke, sets up the correct state based on
                    that logic, then invokes the default `Ember.View` `render` implementation.

                    This method will first look up the `path` key on `pathRoot`,
                    then pass that value to the `shouldDisplayFunc` function. If that returns
                    `true,` the `displayTemplate` function will be rendered to DOM. Otherwise,
                    `inverseTemplate`, if specified, will be rendered.

                    For example, if this `Ember._HandlebarsBoundView` represented the `{{#with
                    foo}}` helper, it would look up the `foo` property of its context, and
                    `shouldDisplayFunc` would always return true. The object found by looking
                    up `foo` would be passed to `displayTemplate`.

                    @method render
                    @param {Ember.RenderBuffer} buffer
                  */
            render: function(buffer) {
                // If not invoked via a triple-mustache ({{{foo}}}), escape
                // the content of the template.
                var escape = get(this, 'isEscaped');

                var shouldDisplay = get(this, 'shouldDisplayFunc'),
                preserveContext = get(this, 'preserveContext'),
                context = get(this, 'previousContext');

                var inverseTemplate = get(this, 'inverseTemplate'),
                displayTemplate = get(this, 'displayTemplate');

                var result = this.normalizedValue();
                this._lastNormalizedValue = result;

                // First, test the conditional to see if we should
                // render the template or not.
                if (shouldDisplay(result)) {
                    set(this, 'template', displayTemplate);

                    // If we are preserving the context (for example, if this
                    // is an #if block, call the template with the same object.
                    if (preserveContext) {
                        set(this, '_context', context);
                    } else {
                        // Otherwise, determine if this is a block bind or not.
                        // If so, pass the specified object to the template
                        if (displayTemplate) {
                            set(this, '_context', result);
                        } else {
                            // This is not a bind block, just push the result of the
                            // expression to the render context and return.
                            if (result === null || result === undefined) {
                                result = "";
                            } else if (!(result instanceof SafeString)) {
                                result = String(result);
                            }

                            if (escape) {
                                result = Handlebars.Utils.escapeExpression(result);
                            }
                            buffer.push(result);
                            return;
                        }
                    }
                } else if (inverseTemplate) {
                    set(this, 'template', inverseTemplate);

                    if (preserveContext) {
                        set(this, '_context', context);
                    } else {
                        set(this, '_context', result);
                    }
                } else {
                    set(this, 'template', function() {
                        return '';
                    });
                }

                return this._super(buffer);
            }
        });

        __exports__._HandlebarsBoundView = _HandlebarsBoundView;
        __exports__.SimpleHandlebarsView = SimpleHandlebarsView;
    });
    define("ember-handlebars/views/metamorph_view",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/property_set", "ember-views/views/core_view", "ember-views/views/view", "ember-metal/mixin", "ember-metal/run_loop", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
        "use strict";
        /* global Metamorph:true */

        /*jshint newcap:false*/
        var Ember = __dependency1__["default"];
        // Ember.deprecate
        // var emberDeprecate = Ember.deprecate;

        var get = __dependency2__.get;
        var set = __dependency3__["default"];

        var CoreView = __dependency4__["default"];
        var View = __dependency5__["default"];
        var Mixin = __dependency6__.Mixin;
        var run = __dependency7__["default"];

        /**
            @module ember
            @submodule ember-handlebars
            */

        var Metamorph = requireModule('metamorph');

        function notifyMutationListeners() {
            run.once(View, 'notifyMutationListeners');
        }

        // DOMManager should just abstract dom manipulation between jquery and metamorph
        var DOMManager = {
            remove: function(view) {
                view.morph.remove();
                notifyMutationListeners();
            },

            prepend: function(view, html) {
                view.morph.prepend(html);
                notifyMutationListeners();
            },

            after: function(view, html) {
                view.morph.after(html);
                notifyMutationListeners();
            },

            html: function(view, html) {
                view.morph.html(html);
                notifyMutationListeners();
            },

            // This is messed up.
            replace: function(view) {
                var morph = view.morph;

                view._transitionTo('preRender');

                run.schedule('render', this, function renderMetamorphView() {
                    if (view.isDestroying) {
                        return;
                    }

                    view.clearRenderedChildren();
                    var buffer = view.renderToBuffer();

                    view.invokeRecursively(function(view) {
                        view.propertyWillChange('element');
                    });
                    view.triggerRecursively('willInsertElement');

                    morph.replaceWith(buffer.string());
                    view._transitionTo('inDOM');

                    view.invokeRecursively(function(view) {
                        view.propertyDidChange('element');
                    });
                    view.triggerRecursively('didInsertElement');

                    notifyMutationListeners();
                });
            },

            empty: function(view) {
                view.morph.html("");
                notifyMutationListeners();
            }
        };

        // The `morph` and `outerHTML` properties are internal only
        // and not observable.

        /**
              @class _Metamorph
              @namespace Ember
              @private
            */
        var _Metamorph = Mixin.create({
            isVirtual: true,
            tagName: '',

            instrumentName: 'metamorph',

            init: function() {
                this._super();
                this.morph = Metamorph();
                Ember.deprecate('Supplying a tagName to Metamorph views is unreliable and is deprecated. You may be setting the tagName on a Handlebars helper that creates a Metamorph.', !this.tagName);
            },

            beforeRender: function(buffer) {
                buffer.push(this.morph.startTag());
                buffer.pushOpeningTag();
            },

            afterRender: function(buffer) {
                buffer.pushClosingTag();
                buffer.push(this.morph.endTag());
            },

            createElement: function() {
                var buffer = this.renderToBuffer();
                this.outerHTML = buffer.string();
                this.clearBuffer();
            },

            domManager: DOMManager
        });
        __exports__._Metamorph = _Metamorph;
        var _wrapMap = Metamorph._wrapMap;
        __exports__._wrapMap = _wrapMap;
        /**
              @class _MetamorphView
              @namespace Ember
              @extends Ember.View
              @uses Ember._Metamorph
              @private
            */
        var _MetamorphView = View.extend(_Metamorph);
        __exports__._MetamorphView = _MetamorphView;
        /**
              @class _SimpleMetamorphView
              @namespace Ember
              @extends Ember.CoreView
              @uses Ember._Metamorph
              @private
            */
        var _SimpleMetamorphView = CoreView.extend(_Metamorph);
        __exports__._SimpleMetamorphView = _SimpleMetamorphView;
        __exports__["default"] = View.extend(_Metamorph);
    });
    define("ember-metal",
    ["ember-metal/core", "ember-metal/merge", "ember-metal/instrumentation", "ember-metal/utils", "ember-metal/error", "ember-metal/enumerable_utils", "ember-metal/platform", "ember-metal/array", "ember-metal/logger", "ember-metal/property_get", "ember-metal/events", "ember-metal/observer_set", "ember-metal/property_events", "ember-metal/properties", "ember-metal/property_set", "ember-metal/map", "ember-metal/get_properties", "ember-metal/set_properties", "ember-metal/watch_key", "ember-metal/chains", "ember-metal/watch_path", "ember-metal/watching", "ember-metal/expand_properties", "ember-metal/computed", "ember-metal/computed_macros", "ember-metal/observer", "ember-metal/mixin", "ember-metal/binding", "ember-metal/run_loop", "ember-metal/libraries", "ember-metal/is_none", "ember-metal/is_empty", "ember-metal/is_blank", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __dependency19__, __dependency20__, __dependency21__, __dependency22__, __dependency23__, __dependency24__, __dependency25__, __dependency26__, __dependency27__, __dependency28__, __dependency29__, __dependency30__, __dependency31__, __dependency32__, __dependency33__, __exports__) {
        "use strict";
        /**
            Ember Metal

            @module ember
            @submodule ember-metal
            */

        // BEGIN IMPORTS
        var Ember = __dependency1__["default"];
        var merge = __dependency2__["default"];
        var instrument = __dependency3__.instrument;
        var subscribe = __dependency3__.subscribe;
        var unsubscribe = __dependency3__.unsubscribe;
        var reset = __dependency3__.reset;
        var generateGuid = __dependency4__.generateGuid;
        var GUID_KEY = __dependency4__.GUID_KEY;
        var GUID_PREFIX = __dependency4__.GUID_PREFIX;
        var guidFor = __dependency4__.guidFor;
        var META_DESC = __dependency4__.META_DESC;
        var EMPTY_META = __dependency4__.EMPTY_META;
        var meta = __dependency4__.meta;
        var getMeta = __dependency4__.getMeta;
        var setMeta = __dependency4__.setMeta;
        var metaPath = __dependency4__.metaPath;
        var inspect = __dependency4__.inspect;
        var typeOf = __dependency4__.typeOf;
        var tryCatchFinally = __dependency4__.tryCatchFinally;
        var isArray = __dependency4__.isArray;
        var makeArray = __dependency4__.makeArray;
        var canInvoke = __dependency4__.canInvoke;
        var tryInvoke = __dependency4__.tryInvoke;
        var tryFinally = __dependency4__.tryFinally;
        var wrap = __dependency4__.wrap;
        var apply = __dependency4__.apply;
        var applyStr = __dependency4__.applyStr;
        var EmberError = __dependency5__["default"];
        var EnumerableUtils = __dependency6__["default"];

        var create = __dependency7__.create;
        var platform = __dependency7__.platform;
        var map = __dependency8__.map;
        var forEach = __dependency8__.forEach;
        var filter = __dependency8__.filter;
        var indexOf = __dependency8__.indexOf;
        var Logger = __dependency9__["default"];

        var get = __dependency10__.get;
        var getWithDefault = __dependency10__.getWithDefault;
        var normalizeTuple = __dependency10__.normalizeTuple;
        var _getPath = __dependency10__._getPath;

        var on = __dependency11__.on;
        var addListener = __dependency11__.addListener;
        var removeListener = __dependency11__.removeListener;
        var suspendListener = __dependency11__.suspendListener;
        var suspendListeners = __dependency11__.suspendListeners;
        var sendEvent = __dependency11__.sendEvent;
        var hasListeners = __dependency11__.hasListeners;
        var watchedEvents = __dependency11__.watchedEvents;
        var listenersFor = __dependency11__.listenersFor;
        var listenersDiff = __dependency11__.listenersDiff;
        var listenersUnion = __dependency11__.listenersUnion;

        var ObserverSet = __dependency12__["default"];

        var propertyWillChange = __dependency13__.propertyWillChange;
        var propertyDidChange = __dependency13__.propertyDidChange;
        var overrideChains = __dependency13__.overrideChains;
        var beginPropertyChanges = __dependency13__.beginPropertyChanges;
        var endPropertyChanges = __dependency13__.endPropertyChanges;
        var changeProperties = __dependency13__.changeProperties;

        var Descriptor = __dependency14__.Descriptor;
        var defineProperty = __dependency14__.defineProperty;
        var set = __dependency15__.set;
        var trySet = __dependency15__.trySet;

        var OrderedSet = __dependency16__.OrderedSet;
        var Map = __dependency16__.Map;
        var MapWithDefault = __dependency16__.MapWithDefault;
        var getProperties = __dependency17__["default"];
        var setProperties = __dependency18__["default"];
        var watchKey = __dependency19__.watchKey;
        var unwatchKey = __dependency19__.unwatchKey;
        var flushPendingChains = __dependency20__.flushPendingChains;
        var removeChainWatcher = __dependency20__.removeChainWatcher;
        var ChainNode = __dependency20__.ChainNode;
        var finishChains = __dependency20__.finishChains;
        var watchPath = __dependency21__.watchPath;
        var unwatchPath = __dependency21__.unwatchPath;
        var watch = __dependency22__.watch;
        var isWatching = __dependency22__.isWatching;
        var unwatch = __dependency22__.unwatch;
        var rewatch = __dependency22__.rewatch;
        var destroy = __dependency22__.destroy;
        var expandProperties = __dependency23__["default"];
        var ComputedProperty = __dependency24__.ComputedProperty;
        var computed = __dependency24__.computed;
        var cacheFor = __dependency24__.cacheFor;

        // side effect of defining the computed.* macros

        var addObserver = __dependency26__.addObserver;
        var observersFor = __dependency26__.observersFor;
        var removeObserver = __dependency26__.removeObserver;
        var addBeforeObserver = __dependency26__.addBeforeObserver;
        var _suspendBeforeObserver = __dependency26__._suspendBeforeObserver;
        var _suspendObserver = __dependency26__._suspendObserver;
        var _suspendBeforeObservers = __dependency26__._suspendBeforeObservers;
        var _suspendObservers = __dependency26__._suspendObservers;
        var beforeObserversFor = __dependency26__.beforeObserversFor;
        var removeBeforeObserver = __dependency26__.removeBeforeObserver;
        var IS_BINDING = __dependency27__.IS_BINDING;
        var mixin = __dependency27__.mixin;
        var Mixin = __dependency27__.Mixin;
        var required = __dependency27__.required;
        var aliasMethod = __dependency27__.aliasMethod;
        var observer = __dependency27__.observer;
        var immediateObserver = __dependency27__.immediateObserver;
        var beforeObserver = __dependency27__.beforeObserver;
        var Binding = __dependency28__.Binding;
        var isGlobalPath = __dependency28__.isGlobalPath;
        var bind = __dependency28__.bind;
        var oneWay = __dependency28__.oneWay;
        var run = __dependency29__["default"];
        var libraries = __dependency30__["default"];
        var isNone = __dependency31__.isNone;
        var none = __dependency31__.none;
        var isEmpty = __dependency32__.isEmpty;
        var empty = __dependency32__.empty;
        var isBlank = __dependency33__["default"];
        // END IMPORTS

        // BEGIN EXPORTS
        var EmberInstrumentation = Ember.Instrumentation = {};
        EmberInstrumentation.instrument = instrument;
        EmberInstrumentation.subscribe = subscribe;
        EmberInstrumentation.unsubscribe = unsubscribe;
        EmberInstrumentation.reset = reset;

        Ember.instrument = instrument;
        Ember.subscribe = subscribe;

        Ember.generateGuid = generateGuid;
        Ember.GUID_KEY = GUID_KEY;
        Ember.GUID_PREFIX = GUID_PREFIX;
        Ember.create = create;
        Ember.platform = platform;

        var EmberArrayPolyfills = Ember.ArrayPolyfills = {};

        EmberArrayPolyfills.map = map;
        EmberArrayPolyfills.forEach = forEach;
        EmberArrayPolyfills.filter = filter;
        EmberArrayPolyfills.indexOf = indexOf;

        Ember.Error = EmberError;
        Ember.guidFor = guidFor;
        Ember.META_DESC = META_DESC;
        Ember.EMPTY_META = EMPTY_META;
        Ember.meta = meta;
        Ember.getMeta = getMeta;
        Ember.setMeta = setMeta;
        Ember.metaPath = metaPath;
        Ember.inspect = inspect;
        Ember.typeOf = typeOf;
        Ember.tryCatchFinally = tryCatchFinally;
        Ember.isArray = isArray;
        Ember.makeArray = makeArray;
        Ember.canInvoke = canInvoke;
        Ember.tryInvoke = tryInvoke;
        Ember.tryFinally = tryFinally;
        Ember.wrap = wrap;
        Ember.apply = apply;
        Ember.applyStr = applyStr;

        Ember.Logger = Logger;

        Ember.get = get;
        Ember.getWithDefault = getWithDefault;
        Ember.normalizeTuple = normalizeTuple;
        Ember._getPath = _getPath;

        Ember.EnumerableUtils = EnumerableUtils;

        Ember.on = on;
        Ember.addListener = addListener;
        Ember.removeListener = removeListener;
        Ember._suspendListener = suspendListener;
        Ember._suspendListeners = suspendListeners;
        Ember.sendEvent = sendEvent;
        Ember.hasListeners = hasListeners;
        Ember.watchedEvents = watchedEvents;
        Ember.listenersFor = listenersFor;
        Ember.listenersDiff = listenersDiff;
        Ember.listenersUnion = listenersUnion;

        Ember._ObserverSet = ObserverSet;

        Ember.propertyWillChange = propertyWillChange;
        Ember.propertyDidChange = propertyDidChange;
        Ember.overrideChains = overrideChains;
        Ember.beginPropertyChanges = beginPropertyChanges;
        Ember.endPropertyChanges = endPropertyChanges;
        Ember.changeProperties = changeProperties;

        Ember.Descriptor = Descriptor;
        Ember.defineProperty = defineProperty;

        Ember.set = set;
        Ember.trySet = trySet;

        Ember.OrderedSet = OrderedSet;
        Ember.Map = Map;
        Ember.MapWithDefault = MapWithDefault;

        Ember.getProperties = getProperties;
        Ember.setProperties = setProperties;

        Ember.watchKey = watchKey;
        Ember.unwatchKey = unwatchKey;

        Ember.flushPendingChains = flushPendingChains;
        Ember.removeChainWatcher = removeChainWatcher;
        Ember._ChainNode = ChainNode;
        Ember.finishChains = finishChains;

        Ember.watchPath = watchPath;
        Ember.unwatchPath = unwatchPath;

        Ember.watch = watch;
        Ember.isWatching = isWatching;
        Ember.unwatch = unwatch;
        Ember.rewatch = rewatch;
        Ember.destroy = destroy;

        Ember.expandProperties = expandProperties;

        Ember.ComputedProperty = ComputedProperty;
        Ember.computed = computed;
        Ember.cacheFor = cacheFor;

        Ember.addObserver = addObserver;
        Ember.observersFor = observersFor;
        Ember.removeObserver = removeObserver;
        Ember.addBeforeObserver = addBeforeObserver;
        Ember._suspendBeforeObserver = _suspendBeforeObserver;
        Ember._suspendBeforeObservers = _suspendBeforeObservers;
        Ember._suspendObserver = _suspendObserver;
        Ember._suspendObservers = _suspendObservers;
        Ember.beforeObserversFor = beforeObserversFor;
        Ember.removeBeforeObserver = removeBeforeObserver;

        Ember.IS_BINDING = IS_BINDING;
        Ember.required = required;
        Ember.aliasMethod = aliasMethod;
        Ember.observer = observer;
        Ember.immediateObserver = immediateObserver;
        Ember.beforeObserver = beforeObserver;
        Ember.mixin = mixin;
        Ember.Mixin = Mixin;

        Ember.oneWay = oneWay;
        Ember.bind = bind;
        Ember.Binding = Binding;
        Ember.isGlobalPath = isGlobalPath;

        Ember.run = run;

        Ember.libraries = libraries;
        Ember.libraries.registerCoreLibrary('Ember', Ember.VERSION);

        Ember.isNone = isNone;
        Ember.none = none;

        Ember.isEmpty = isEmpty;
        Ember.empty = empty;

        Ember.isBlank = isBlank;

        Ember.merge = merge;

        /**
              A function may be assigned to `Ember.onerror` to be called when Ember
              internals encounter an error. This is useful for specialized error handling
              and reporting code.

              ```javascript
              Ember.onerror = function(error) {
                Em.$.ajax('/report-error', 'POST', {
                  stack: error.stack,
                  otherInformation: 'whatever app state you want to provide'
                });
              };
              ```

              Internally, `Ember.onerror` is used as Backburner's error handler.

              @event onerror
              @for Ember
              @param {Exception} error the error object
            */
        Ember.onerror = null;
        // END EXPORTS

        // do this for side-effects of updating Ember.assert, warn, etc when
        // ember-debug is present
        if (Ember.__loader.registry['ember-debug']) {
            requireModule('ember-debug');
        }

        __exports__["default"] = Ember;
    });
    define("ember-metal/alias",
    ["ember-metal/property_get", "ember-metal/property_set", "ember-metal/error", "ember-metal/properties", "ember-metal/computed", "ember-metal/platform", "ember-metal/utils", "ember-metal/dependent_keys", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
        "use strict";
        var get = __dependency1__.get;
        var set = __dependency2__.set;
        var EmberError = __dependency3__["default"];
        var Descriptor = __dependency4__.Descriptor;
        var defineProperty = __dependency4__.defineProperty;
        var ComputedProperty = __dependency5__.ComputedProperty;
        var create = __dependency6__.create;
        var meta = __dependency7__.meta;
        var inspect = __dependency7__.inspect;
        var addDependentKeys = __dependency8__.addDependentKeys;
        var removeDependentKeys = __dependency8__.removeDependentKeys;

        function alias(altKey) {
            return new AliasedProperty(altKey);
        }

        __exports__.alias = alias;
        function AliasedProperty(altKey) {
            this.altKey = altKey;
            this._dependentKeys = [ altKey ];
        }

        __exports__.AliasedProperty = AliasedProperty;
        AliasedProperty.prototype = create(Descriptor.prototype);

        AliasedProperty.prototype.get = function AliasedProperty_get(obj, keyName) {
            return get(obj, this.altKey);
        };

        AliasedProperty.prototype.set = function AliasedProperty_set(obj, keyName, value) {
            return set(obj, this.altKey, value);
        };

        AliasedProperty.prototype.willWatch = function(obj, keyName) {
            addDependentKeys(this, obj, keyName, meta(obj));
        };

        AliasedProperty.prototype.didUnwatch = function(obj, keyName) {
            removeDependentKeys(this, obj, keyName, meta(obj));
        };

        AliasedProperty.prototype.setup = function(obj, keyName) {
            var m = meta(obj);
            if (m.watching[keyName]) {
                addDependentKeys(this, obj, keyName, m);
            }
        };

        AliasedProperty.prototype.teardown = function(obj, keyName) {
            var m = meta(obj);
            if (m.watching[keyName]) {
                removeDependentKeys(this, obj, keyName, m);
            }
        };

        AliasedProperty.prototype.readOnly = function() {
            this.set = AliasedProperty_readOnlySet;
            return this;
        };

        function AliasedProperty_readOnlySet(obj, keyName, value) {
            throw new EmberError('Cannot set read-only property "' + keyName + '" on object: ' + inspect(obj));
        }

        AliasedProperty.prototype.oneWay = function() {
            this.set = AliasedProperty_oneWaySet;
            return this;
        };

        function AliasedProperty_oneWaySet(obj, keyName, value) {
            defineProperty(obj, keyName, null);
            return set(obj, keyName, value);
        }

        // Backwards compatibility with Ember Data
        AliasedProperty.prototype._meta = undefined;
        AliasedProperty.prototype.meta = ComputedProperty.prototype.meta;
    });
    define("ember-metal/array",
    ["exports"],
    function(__exports__) {
        "use strict";
        /**
            @module ember-metal
            */

        var ArrayPrototype = Array.prototype;

        // Testing this is not ideal, but we want to use native functions
        // if available, but not to use versions created by libraries like Prototype
        var isNativeFunc = function(func) {
            // This should probably work in all browsers likely to have ES5 array methods
            return func && Function.prototype.toString.call(func).indexOf('[native code]') > -1;
        };

        // From: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/map
        var map = isNativeFunc(ArrayPrototype.map) ? ArrayPrototype.map : function(fun /*, thisp */
        ) {
            //"use strict";

            if (this === void 0 || this === null) {
                throw new TypeError();
            }

            var t = Object(this);
            var len = t.length >>> 0;
            if (typeof fun !== "function") {
                throw new TypeError();
            }

            var res = new Array(len);
            var thisp = arguments[1];
            for (var i = 0; i < len; i++) {
                if (i in t) {
                    res[i] = fun.call(thisp, t[i], i, t);
                }
            }

            return res;
        };

        // From: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/foreach
        var forEach = isNativeFunc(ArrayPrototype.forEach) ? ArrayPrototype.forEach : function(fun /*, thisp */
        ) {
            //"use strict";

            if (this === void 0 || this === null) {
                throw new TypeError();
            }

            var t = Object(this);
            var len = t.length >>> 0;
            if (typeof fun !== "function") {
                throw new TypeError();
            }

            var thisp = arguments[1];
            for (var i = 0; i < len; i++) {
                if (i in t) {
                    fun.call(thisp, t[i], i, t);
                }
            }
        };

        var indexOf = isNativeFunc(ArrayPrototype.indexOf) ? ArrayPrototype.indexOf : function (obj, fromIndex) {
            if (fromIndex === null || fromIndex === undefined) {
                fromIndex = 0;
            } else if (fromIndex < 0) {
                fromIndex = Math.max(0, this.length + fromIndex);
            }
            for (var i = fromIndex, j = this.length; i < j; i++) {
                if (this[i] === obj) {
                    return i;
                }
            }
            return -1;
        };

        var filter = isNativeFunc(ArrayPrototype.filter) ? ArrayPrototype.filter : function (fn, context) {
            var i,
            value,
            result = [],
            length = this.length;

            for (i = 0; i < length; i++) {
                if (this.hasOwnProperty(i)) {
                    value = this[i];
                    if (fn.call(context, value, i, this)) {
                        result.push(value);
                    }
                }
            }
            return result;
        };


        if (Ember.SHIM_ES5) {
            if (!ArrayPrototype.map) {
                ArrayPrototype.map = map;
            }

            if (!ArrayPrototype.forEach) {
                ArrayPrototype.forEach = forEach;
            }

            if (!ArrayPrototype.filter) {
                ArrayPrototype.filter = filter;
            }

            if (!ArrayPrototype.indexOf) {
                ArrayPrototype.indexOf = indexOf;
            }
        }

        /**
              Array polyfills to support ES5 features in older browsers.

              @namespace Ember
              @property ArrayPolyfills
            */
        __exports__.map = map;
        __exports__.forEach = forEach;
        __exports__.filter = filter;
        __exports__.indexOf = indexOf;
    });
    define("ember-metal/binding",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/utils", "ember-metal/map", "ember-metal/observer", "ember-metal/run_loop", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // Ember.Logger, Ember.LOG_BINDINGS, assert
        var get = __dependency2__.get;
        var set = __dependency3__.set;
        var trySet = __dependency3__.trySet;
        var guidFor = __dependency4__.guidFor;
        var Map = __dependency5__.Map;
        var addObserver = __dependency6__.addObserver;
        var removeObserver = __dependency6__.removeObserver;
        var _suspendObserver = __dependency6__._suspendObserver;
        var run = __dependency7__["default"];

        // ES6TODO: where is Ember.lookup defined?
        /**
            @module ember-metal
            */

        // ..........................................................
        // CONSTANTS
        //

        /**
              Debug parameter you can turn on. This will log all bindings that fire to
              the console. This should be disabled in production code. Note that you
              can also enable this from the console or temporarily.

              @property LOG_BINDINGS
              @for Ember
              @type Boolean
              @default false
            */
        Ember.LOG_BINDINGS = false || !!Ember.ENV.LOG_BINDINGS;

        var IS_GLOBAL = /^([A-Z$]|([0-9][A-Z$]))/;

        /**
              Returns true if the provided path is global (e.g., `MyApp.fooController.bar`)
              instead of local (`foo.bar.baz`).

              @method isGlobalPath
              @for Ember
              @private
              @param {String} path
              @return Boolean
            */
        function isGlobalPath(path) {
            return IS_GLOBAL.test(path);
        }

        function getWithGlobals(obj, path) {
            return get(isGlobalPath(path) ? Ember.lookup : obj, path);
        }

        // ..........................................................
        // BINDING
        //

        function Binding(toPath, fromPath) {
            this._direction = 'fwd';
            this._from = fromPath;
            this._to = toPath;
            this._directionMap = Map.create();
            this._readyToSync = undefined;
            this._oneWay = undefined;
        }

        /**
            @class Binding
            @namespace Ember
            */

        Binding.prototype = {
            /**
                    This copies the Binding so it can be connected to another object.

                    @method copy
                    @return {Ember.Binding} `this`
                  */
            copy: function () {
                var copy = new Binding(this._to, this._from);
                if (this._oneWay) {
                    copy._oneWay = true;
                }
                return copy;
            },

            // ..........................................................
            // CONFIG
            //

            /**
                    This will set `from` property path to the specified value. It will not
                    attempt to resolve this property path to an actual object until you
                    connect the binding.

                    The binding will search for the property path starting at the root object
                    you pass when you `connect()` the binding. It follows the same rules as
                    `get()` - see that method for more information.

                    @method from
                    @param {String} path the property path to connect to
                    @return {Ember.Binding} `this`
                  */
            from: function(path) {
                this._from = path;
                return this;
            },

            /**
                    This will set the `to` property path to the specified value. It will not
                    attempt to resolve this property path to an actual object until you
                    connect the binding.

                    The binding will search for the property path starting at the root object
                    you pass when you `connect()` the binding. It follows the same rules as
                    `get()` - see that method for more information.

                    @method to
                    @param {String|Tuple} path A property path or tuple
                    @return {Ember.Binding} `this`
                  */
            to: function(path) {
                this._to = path;
                return this;
            },

            /**
                    Configures the binding as one way. A one-way binding will relay changes
                    on the `from` side to the `to` side, but not the other way around. This
                    means that if you change the `to` side directly, the `from` side may have
                    a different value.

                    @method oneWay
                    @return {Ember.Binding} `this`
                  */
            oneWay: function() {
                this._oneWay = true;
                return this;
            },

            /**
                    @method toString
                    @return {String} string representation of binding
                  */
            toString: function() {
                var oneWay = this._oneWay ? '[oneWay]' : '';
                return "Ember.Binding<" + guidFor(this) + ">(" + this._from + " -> " + this._to + ")" + oneWay;
            },

            // ..........................................................
            // CONNECT AND SYNC
            //

            /**
                    Attempts to connect this binding instance so that it can receive and relay
                    changes. This method will raise an exception if you have not set the
                    from/to properties yet.

                    @method connect
                    @param {Object} obj The root object for this binding.
                    @return {Ember.Binding} `this`
                  */
            connect: function(obj) {
                Ember.assert('Must pass a valid object to Ember.Binding.connect()', !!obj);

                var fromPath = this._from, toPath = this._to;
                trySet(obj, toPath, getWithGlobals(obj, fromPath));

                // add an observer on the object to be notified when the binding should be updated
                addObserver(obj, fromPath, this, this.fromDidChange);

                // if the binding is a two-way binding, also set up an observer on the target
                if (!this._oneWay) {
                    addObserver(obj, toPath, this, this.toDidChange);
                }

                this._readyToSync = true;

                return this;
            },

            /**
                    Disconnects the binding instance. Changes will no longer be relayed. You
                    will not usually need to call this method.

                    @method disconnect
                    @param {Object} obj The root object you passed when connecting the binding.
                    @return {Ember.Binding} `this`
                  */
            disconnect: function(obj) {
                Ember.assert('Must pass a valid object to Ember.Binding.disconnect()', !!obj);

                var twoWay = !this._oneWay;

                // remove an observer on the object so we're no longer notified of
                // changes that should update bindings.
                removeObserver(obj, this._from, this, this.fromDidChange);

                // if the binding is two-way, remove the observer from the target as well
                if (twoWay) {
                    removeObserver(obj, this._to, this, this.toDidChange);
                }

                this._readyToSync = false; // disable scheduled syncs...
                return this;
            },

            // ..........................................................
            // PRIVATE
            //

            /* called when the from side changes */
            fromDidChange: function(target) {
                this._scheduleSync(target, 'fwd');
            },

            /* called when the to side changes */
            toDidChange: function(target) {
                this._scheduleSync(target, 'back');
            },

            _scheduleSync: function(obj, dir) {
                var directionMap = this._directionMap;
                var existingDir = directionMap.get(obj);

                // if we haven't scheduled the binding yet, schedule it
                if (!existingDir) {
                    run.schedule('sync', this, this._sync, obj);
                    directionMap.set(obj, dir);
                }

                // If both a 'back' and 'fwd' sync have been scheduled on the same object,
                // default to a 'fwd' sync so that it remains deterministic.
                if (existingDir === 'back' && dir === 'fwd') {
                    directionMap.set(obj, 'fwd');
                }
            },

            _sync: function(obj) {
                var log = Ember.LOG_BINDINGS;

                // don't synchronize destroyed objects or disconnected bindings
                if (obj.isDestroyed || !this._readyToSync) {
                    return;
                }

                // get the direction of the binding for the object we are
                // synchronizing from
                var directionMap = this._directionMap;
                var direction = directionMap.get(obj);

                var fromPath = this._from, toPath = this._to;

                directionMap.remove(obj);

                // if we're synchronizing from the remote object...
                if (direction === 'fwd') {
                    var fromValue = getWithGlobals(obj, this._from);
                    if (log) {
                        Ember.Logger.log(' ', this.toString(), '->', fromValue, obj);
                    }
                    if (this._oneWay) {
                        trySet(obj, toPath, fromValue);
                    } else {
                        _suspendObserver(obj, toPath, this, this.toDidChange, function () {
                            trySet(obj, toPath, fromValue);
                        });
                    }
                    // if we're synchronizing *to* the remote object
                } else if (direction === 'back') {
                    var toValue = get(obj, this._to);
                    if (log) {
                        Ember.Logger.log(' ', this.toString(), '<-', toValue, obj);
                    }
                    _suspendObserver(obj, fromPath, this, this.fromDidChange, function () {
                        trySet(isGlobalPath(fromPath) ? Ember.lookup : obj, fromPath, toValue);
                    });
                }
            }

        };

        function mixinProperties(to, from) {
            for (var key in from) {
                if (from.hasOwnProperty(key)) {
                    to[key] = from[key];
                }
            }
        }

        mixinProperties(Binding, {

            /*
                    See `Ember.Binding.from`.

                    @method from
                    @static
                  */
            from: function() {
                var C = this, binding = new C();
                return binding.from.apply(binding, arguments);
            },

            /*
                    See `Ember.Binding.to`.

                    @method to
                    @static
                  */
            to: function() {
                var C = this, binding = new C();
                return binding.to.apply(binding, arguments);
            },

            /**
                    Creates a new Binding instance and makes it apply in a single direction.
                    A one-way binding will relay changes on the `from` side object (supplied
                    as the `from` argument) the `to` side, but not the other way around.
                    This means that if you change the "to" side directly, the "from" side may have
                    a different value.

                    See `Binding.oneWay`.

                    @method oneWay
                    @param {String} from from path.
                    @param {Boolean} [flag] (Optional) passing nothing here will make the
                      binding `oneWay`. You can instead pass `false` to disable `oneWay`, making the
                      binding two way again.
                    @return {Ember.Binding} `this`
                  */
            oneWay: function(from, flag) {
                var C = this, binding = new C(null, from);
                return binding.oneWay(flag);
            }

        });
        /**
              An `Ember.Binding` connects the properties of two objects so that whenever
              the value of one property changes, the other property will be changed also.

              ## Automatic Creation of Bindings with `/^*Binding/`-named Properties

              You do not usually create Binding objects directly but instead describe
              bindings in your class or object definition using automatic binding
              detection.

              Properties ending in a `Binding` suffix will be converted to `Ember.Binding`
              instances. The value of this property should be a string representing a path
              to another object or a custom binding instanced created using Binding helpers
              (see "One Way Bindings"):

              ```
              valueBinding: "MyApp.someController.title"
              ```

              This will create a binding from `MyApp.someController.title` to the `value`
              property of your object instance automatically. Now the two values will be
              kept in sync.

              ## One Way Bindings

              One especially useful binding customization you can use is the `oneWay()`
              helper. This helper tells Ember that you are only interested in
              receiving changes on the object you are binding from. For example, if you
              are binding to a preference and you want to be notified if the preference
              has changed, but your object will not be changing the preference itself, you
              could do:

              ```
              bigTitlesBinding: Ember.Binding.oneWay("MyApp.preferencesController.bigTitles")
              ```

              This way if the value of `MyApp.preferencesController.bigTitles` changes the
              `bigTitles` property of your object will change also. However, if you
              change the value of your `bigTitles` property, it will not update the
              `preferencesController`.

              One way bindings are almost twice as fast to setup and twice as fast to
              execute because the binding only has to worry about changes to one side.

              You should consider using one way bindings anytime you have an object that
              may be created frequently and you do not intend to change a property; only
              to monitor it for changes (such as in the example above).

              ## Adding Bindings Manually

              All of the examples above show you how to configure a custom binding, but the
              result of these customizations will be a binding template, not a fully active
              Binding instance. The binding will actually become active only when you
              instantiate the object the binding belongs to. It is useful however, to
              understand what actually happens when the binding is activated.

              For a binding to function it must have at least a `from` property and a `to`
              property. The `from` property path points to the object/key that you want to
              bind from while the `to` path points to the object/key you want to bind to.

              When you define a custom binding, you are usually describing the property
              you want to bind from (such as `MyApp.someController.value` in the examples
              above). When your object is created, it will automatically assign the value
              you want to bind `to` based on the name of your binding key. In the
              examples above, during init, Ember objects will effectively call
              something like this on your binding:

              ```javascript
              binding = Ember.Binding.from(this.valueBinding).to("value");
              ```

              This creates a new binding instance based on the template you provide, and
              sets the to path to the `value` property of the new object. Now that the
              binding is fully configured with a `from` and a `to`, it simply needs to be
              connected to become active. This is done through the `connect()` method:

              ```javascript
              binding.connect(this);
              ```

              Note that when you connect a binding you pass the object you want it to be
              connected to. This object will be used as the root for both the from and
              to side of the binding when inspecting relative paths. This allows the
              binding to be automatically inherited by subclassed objects as well.

              Now that the binding is connected, it will observe both the from and to side
              and relay changes.

              If you ever needed to do so (you almost never will, but it is useful to
              understand this anyway), you could manually create an active binding by
              using the `Ember.bind()` helper method. (This is the same method used by
              to setup your bindings on objects):

              ```javascript
              Ember.bind(MyApp.anotherObject, "value", "MyApp.someController.value");
              ```

              Both of these code fragments have the same effect as doing the most friendly
              form of binding creation like so:

              ```javascript
              MyApp.anotherObject = Ember.Object.create({
                valueBinding: "MyApp.someController.value",

                // OTHER CODE FOR THIS OBJECT...
              });
              ```

              Ember's built in binding creation method makes it easy to automatically
              create bindings for you. You should always use the highest-level APIs
              available, even if you understand how it works underneath.

              @class Binding
              @namespace Ember
              @since Ember 0.9
            */
        // Ember.Binding = Binding; ES6TODO: where to put this?


        /**
              Global helper method to create a new binding. Just pass the root object
              along with a `to` and `from` path to create and connect the binding.

              @method bind
              @for Ember
              @param {Object} obj The root object of the transform.
              @param {String} to The path to the 'to' side of the binding.
                Must be relative to obj.
              @param {String} from The path to the 'from' side of the binding.
                Must be relative to obj or a global path.
              @return {Ember.Binding} binding instance
            */
        function bind(obj, to, from) {
            return new Binding(to, from).connect(obj);
        }

        __exports__.bind = bind; /**
              @method oneWay
              @for Ember
              @param {Object} obj The root object of the transform.
              @param {String} to The path to the 'to' side of the binding.
                Must be relative to obj.
              @param {String} from The path to the 'from' side of the binding.
                Must be relative to obj or a global path.
              @return {Ember.Binding} binding instance
            */
        function oneWay(obj, to, from) {
            return new Binding(to, from).oneWay().connect(obj);
        }

        __exports__.oneWay = oneWay;
        __exports__.Binding = Binding;
        __exports__.isGlobalPath = isGlobalPath;
    });
    define("ember-metal/chains",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/utils", "ember-metal/array", "ember-metal/watch_key", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // warn, assert, etc;
        var get = __dependency2__.get;
        var normalizeTuple = __dependency2__.normalizeTuple;
        var meta = __dependency3__.meta;
        var META_KEY = __dependency3__.META_KEY;
        var forEach = __dependency4__.forEach;
        var watchKey = __dependency5__.watchKey;
        var unwatchKey = __dependency5__.unwatchKey;

        var metaFor = meta,
        warn = Ember.warn,
        FIRST_KEY = /^([^\.]+)/;

        function firstKey(path) {
            return path.match(FIRST_KEY)[0];
        }

        var pendingQueue = [];

        // attempts to add the pendingQueue chains again. If some of them end up
        // back in the queue and reschedule is true, schedules a timeout to try
        // again.
        function flushPendingChains() {
            if (pendingQueue.length === 0) {
                return;
            }
            // nothing to do

            var queue = pendingQueue;
            pendingQueue = [];

            forEach.call(queue, function(q) {
                q[0].add(q[1]);
            });

            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);
        }

        __exports__.flushPendingChains = flushPendingChains;
        function addChainWatcher(obj, keyName, node) {
            if (!obj || ('object' !== typeof obj)) {
                return;
            }
            // nothing to do

            var m = metaFor(obj), nodes = m.chainWatchers;

            if (!m.hasOwnProperty('chainWatchers')) {
                nodes = m.chainWatchers = {};
            }

            if (!nodes[keyName]) {
                nodes[keyName] = [];
            }
            nodes[keyName].push(node);
            watchKey(obj, keyName, m);
        }

        function removeChainWatcher(obj, keyName, node) {
            if (!obj || 'object' !== typeof obj) {
                return;
            }
            // nothing to do

            var m = obj[META_KEY];
            if (m && !m.hasOwnProperty('chainWatchers')) {
                return;
            }
            // nothing to do

            var nodes = m && m.chainWatchers;

            if (nodes && nodes[keyName]) {
                nodes = nodes[keyName];
                for (var i = 0, l = nodes.length; i < l; i++) {
                    if (nodes[i] === node) {
                        nodes.splice(i, 1);
                        break;
                    }
                }
            }
            unwatchKey(obj, keyName, m);
        }

        // A ChainNode watches a single key on an object. If you provide a starting
        // value for the key then the node won't actually watch it. For a root node
        // pass null for parent and key and object for value.
        function ChainNode(parent, key, value) {
            this._parent = parent;
            this._key = key;

            // _watching is true when calling get(this._parent, this._key) will
            // return the value of this node.
            //
            // It is false for the root of a chain (because we have no parent)
            // and for global paths (because the parent node is the object with
            // the observer on it)
            this._watching = value === undefined;

            this._value = value;
            this._paths = {};
            if (this._watching) {
                this._object = parent.value();
                if (this._object) {
                    addChainWatcher(this._object, this._key, this);
                }
            }

            // Special-case: the EachProxy relies on immediate evaluation to
            // establish its observers.
            //
            // TODO: Replace this with an efficient callback that the EachProxy
            // can implement.
            if (this._parent && this._parent._key === '@each') {
                this.value();
            }
        }

        var ChainNodePrototype = ChainNode.prototype;

        function lazyGet(obj, key) {
            if (!obj) 
                return undefined;

            var meta = obj[META_KEY];
            // check if object meant only to be a prototype
            if (meta && meta.proto === obj) 
                return undefined;

            if (key === "@each") 
                return get(obj, key);

            // if a CP only return cached value
            var desc = meta && meta.descs[key];
            if (desc && desc._cacheable) {
                if (key in meta.cache) {
                    return meta.cache[key];
                } else {
                    return undefined;
                }
            }

            return get(obj, key);
        }

        ChainNodePrototype.value = function() {
            if (this._value === undefined && this._watching) {
                var obj = this._parent.value();
                this._value = lazyGet(obj, this._key);
            }
            return this._value;
        };

        ChainNodePrototype.destroy = function() {
            if (this._watching) {
                var obj = this._object;
                if (obj) {
                    removeChainWatcher(obj, this._key, this);
                }
                this._watching = false; // so future calls do nothing
            }
        };

        // copies a top level object only
        ChainNodePrototype.copy = function(obj) {
            var ret = new ChainNode(null, null, obj),
            paths = this._paths, path;
            for (path in paths) {
                if (paths[path] <= 0) {
                    continue;
                }
                // this check will also catch non-number vals.
                ret.add(path);
            }
            return ret;
        };

        // called on the root node of a chain to setup watchers on the specified
        // path.
        ChainNodePrototype.add = function(path) {
            var obj, tuple, key, src, paths;

            paths = this._paths;
            paths[path] = (paths[path] || 0) + 1;

            obj = this.value();
            tuple = normalizeTuple(obj, path);

            // the path was a local path
            if (tuple[0] && tuple[0] === obj) {
                path = tuple[1];
                key = firstKey(path);
                path = path.slice(key.length + 1);

                // global path, but object does not exist yet.
                // put into a queue and try to connect later.
            } else if (!tuple[0]) {
                pendingQueue.push([this, path]);
                tuple.length = 0;
                return;

                // global path, and object already exists
            } else {
                src = tuple[0];
                key = path.slice(0, 0 - (tuple[1].length + 1));
                path = tuple[1];
            }

            tuple.length = 0;
            this.chain(key, path, src);
        };

        // called on the root node of a chain to teardown watcher on the specified
        // path
        ChainNodePrototype.remove = function(path) {
            var obj, tuple, key, src, paths;

            paths = this._paths;
            if (paths[path] > 0) {
                paths[path]--;
            }

            obj = this.value();
            tuple = normalizeTuple(obj, path);
            if (tuple[0] === obj) {
                path = tuple[1];
                key = firstKey(path);
                path = path.slice(key.length + 1);
            } else {
                src = tuple[0];
                key = path.slice(0, 0 - (tuple[1].length + 1));
                path = tuple[1];
            }

            tuple.length = 0;
            this.unchain(key, path);
        };

        ChainNodePrototype.count = 0;

        ChainNodePrototype.chain = function(key, path, src) {
            var chains = this._chains, node;
            if (!chains) {
                chains = this._chains = {};
            }

            node = chains[key];
            if (!node) {
                node = chains[key] = new ChainNode(this, key, src);
            }
            node.count++; // count chains...

            // chain rest of path if there is one
            if (path) {
                key = firstKey(path);
                path = path.slice(key.length + 1);
                node.chain(key, path); // NOTE: no src means it will observe changes...
            }
        };

        ChainNodePrototype.unchain = function(key, path) {
            var chains = this._chains, node = chains[key];

            // unchain rest of path first...
            if (path && path.length > 1) {
                key = firstKey(path);
                path = path.slice(key.length + 1);
                node.unchain(key, path);
            }

            // delete node if needed.
            node.count--;
            if (node.count <= 0) {
                delete chains[node._key];
                node.destroy();
            }

        };

        ChainNodePrototype.willChange = function(events) {
            var chains = this._chains;
            if (chains) {
                for (var key in chains) {
                    if (!chains.hasOwnProperty(key)) {
                        continue;
                    }
                    chains[key].willChange(events);
                }
            }

            if (this._parent) {
                this._parent.chainWillChange(this, this._key, 1, events);
            }
        };

        ChainNodePrototype.chainWillChange = function(chain, path, depth, events) {
            if (this._key) {
                path = this._key + '.' + path;
            }

            if (this._parent) {
                this._parent.chainWillChange(this, path, depth + 1, events);
            } else {
                if (depth > 1) {
                    events.push(this.value(), path);
                }
                path = 'this.' + path;
                if (this._paths[path] > 0) {
                    events.push(this.value(), path);
                }
            }
        };

        ChainNodePrototype.chainDidChange = function(chain, path, depth, events) {
            if (this._key) {
                path = this._key + '.' + path;
            }
            if (this._parent) {
                this._parent.chainDidChange(this, path, depth + 1, events);
            } else {
                if (depth > 1) {
                    events.push(this.value(), path);
                }
                path = 'this.' + path;
                if (this._paths[path] > 0) {
                    events.push(this.value(), path);
                }
            }
        };

        ChainNodePrototype.didChange = function(events) {
            // invalidate my own value first.
            if (this._watching) {
                var obj = this._parent.value();
                if (obj !== this._object) {
                    removeChainWatcher(this._object, this._key, this);
                    this._object = obj;
                    addChainWatcher(obj, this._key, this);
                }
                this._value = undefined;

                // Special-case: the EachProxy relies on immediate evaluation to
                // establish its observers.
                if (this._parent && this._parent._key === '@each')
                    this.value();
            }

            // then notify chains...
            var chains = this._chains;
            if (chains) {
                for (var key in chains) {
                    if (!chains.hasOwnProperty(key)) {
                        continue;
                    }
                    chains[key].didChange(events);
                }
            }

            // if no events are passed in then we only care about the above wiring update
            if (events === null) {
                return;
            }

            // and finally tell parent about my path changing...
            if (this._parent) {
                this._parent.chainDidChange(this, this._key, 1, events);
            }
        };

        function finishChains(obj) {
            // We only create meta if we really have to
            var m = obj[META_KEY], chains = m && m.chains;
            if (chains) {
                if (chains.value() !== obj) {
                    metaFor(obj).chains = chains = chains.copy(obj);
                } else {
                    chains.didChange(null);
                }
            }
        }

        __exports__.finishChains = finishChains;
        __exports__.removeChainWatcher = removeChainWatcher;
        __exports__.ChainNode = ChainNode;
    });
    define("ember-metal/computed",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/utils", "ember-metal/expand_properties", "ember-metal/error", "ember-metal/properties", "ember-metal/property_events", "ember-metal/dependent_keys", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        var get = __dependency2__.get;
        var set = __dependency3__.set;
        var meta = __dependency4__.meta;
        var META_KEY = __dependency4__.META_KEY;
        var inspect = __dependency4__.inspect;
        var expandProperties = __dependency5__["default"];
        var EmberError = __dependency6__["default"];
        var Descriptor = __dependency7__.Descriptor;
        var defineProperty = __dependency7__.defineProperty;
        var propertyWillChange = __dependency8__.propertyWillChange;
        var propertyDidChange = __dependency8__.propertyDidChange;
        var addDependentKeys = __dependency9__.addDependentKeys;
        var removeDependentKeys = __dependency9__.removeDependentKeys;

        /**
            @module ember-metal
            */

        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);


        var metaFor = meta,
        a_slice = [].slice;

        function UNDEFINED() {}

        // ..........................................................
        // COMPUTED PROPERTY
        //

        /**
              A computed property transforms an objects function into a property.

              By default the function backing the computed property will only be called
              once and the result will be cached. You can specify various properties
              that your computed property is dependent on. This will force the cached
              result to be recomputed if the dependencies are modified.

              In the following example we declare a computed property (by calling
              `.property()` on the fullName function) and setup the properties
              dependencies (depending on firstName and lastName). The fullName function
              will be called once (regardless of how many times it is accessed) as long
              as it's dependencies have not been changed. Once firstName or lastName are updated
              any future calls (or anything bound) to fullName will incorporate the new
              values.

              ```javascript
              var Person = Ember.Object.extend({
                // these will be supplied by `create`
                firstName: null,
                lastName: null,

                fullName: function() {
                  var firstName = this.get('firstName');
                  var lastName = this.get('lastName');

                 return firstName + ' ' + lastName;
                }.property('firstName', 'lastName')
              });

              var tom = Person.create({
                firstName: 'Tom',
                lastName: 'Dale'
              });

              tom.get('fullName') // 'Tom Dale'
              ```

              You can also define what Ember should do when setting a computed property.
              If you try to set a computed property, it will be invoked with the key and
              value you want to set it to. You can also accept the previous value as the
              third parameter.

              ```javascript
              var Person = Ember.Object.extend({
                // these will be supplied by `create`
                firstName: null,
                lastName: null,

                fullName: function(key, value, oldValue) {
                  // getter
                  if (arguments.length === 1) {
                    var firstName = this.get('firstName');
                    var lastName = this.get('lastName');

                    return firstName + ' ' + lastName;

                  // setter
                  } else {
                    var name = value.split(' ');

                    this.set('firstName', name[0]);
                    this.set('lastName', name[1]);

                    return value;
                  }
                }.property('firstName', 'lastName')
              });

              var person = Person.create();

              person.set('fullName', 'Peter Wagenet');
              person.get('firstName'); // 'Peter'
              person.get('lastName');  // 'Wagenet'
              ```

              @class ComputedProperty
              @namespace Ember
              @extends Ember.Descriptor
              @constructor
            */
        function ComputedProperty(func, opts) {
            func.__ember_arity__ = func.length;
            this.func = func;

            this._cacheable = (opts && opts.cacheable !== undefined) ? opts.cacheable : true;
            this._dependentKeys = opts && opts.dependentKeys;
            this._readOnly = opts && (opts.readOnly !== undefined || !!opts.readOnly) || false;
        }

        ComputedProperty.prototype = new Descriptor();

        var ComputedPropertyPrototype = ComputedProperty.prototype;
        ComputedPropertyPrototype._dependentKeys = undefined;
        ComputedPropertyPrototype._suspended = undefined;
        ComputedPropertyPrototype._meta = undefined;

        /**
              Properties are cacheable by default. Computed property will automatically
              cache the return value of your function until one of the dependent keys changes.

              Call `volatile()` to set it into non-cached mode. When in this mode
              the computed property will not automatically cache the return value.

              However, if a property is properly observable, there is no reason to disable
              caching.

              @method cacheable
              @param {Boolean} aFlag optional set to `false` to disable caching
              @return {Ember.ComputedProperty} this
              @chainable
            */
        ComputedPropertyPrototype.cacheable = function(aFlag) {
            this._cacheable = aFlag !== false;
            return this;
        };

        /**
              Call on a computed property to set it into non-cached mode. When in this
              mode the computed property will not automatically cache the return value.

              ```javascript
              var outsideService = Ember.Object.extend({
                value: function() {
                  return OutsideService.getValue();
                }.property().volatile()
              }).create();
              ```

              @method volatile
              @return {Ember.ComputedProperty} this
              @chainable
            */
        ComputedPropertyPrototype["volatile"] = function() {
            return this.cacheable(false);
        };

        /**
              Call on a computed property to set it into read-only mode. When in this
              mode the computed property will throw an error when set.

              ```javascript
              var Person = Ember.Object.extend({
                guid: function() {
                  return 'guid-guid-guid';
                }.property().readOnly()
              });

              var person = Person.create();

              person.set('guid', 'new-guid'); // will throw an exception
              ```

              @method readOnly
              @return {Ember.ComputedProperty} this
              @chainable
            */
        ComputedPropertyPrototype.readOnly = function(readOnly) {
            this._readOnly = readOnly === undefined || !!readOnly;
            return this;
        };

        /**
              Sets the dependent keys on this computed property. Pass any number of
              arguments containing key paths that this computed property depends on.

              ```javascript
              var President = Ember.Object.extend({
                fullName: computed(function() {
                  return this.get('firstName') + ' ' + this.get('lastName');

                  // Tell Ember that this computed property depends on firstName
                  // and lastName
                }).property('firstName', 'lastName')
              });

              var president = President.create({
                firstName: 'Barack',
                lastName: 'Obama'
              });

              president.get('fullName'); // 'Barack Obama'
              ```

              @method property
              @param {String} path* zero or more property paths
              @return {Ember.ComputedProperty} this
              @chainable
            */
        ComputedPropertyPrototype.property = function() {
            var args;

            var addArg = function (property) {
                args.push(property);
            };

            args = [];
            for (var i = 0, l = arguments.length; i < l; i++) {
                expandProperties(arguments[i], addArg);
            }

            this._dependentKeys = args;
            return this;
        };

        /**
              In some cases, you may want to annotate computed properties with additional
              metadata about how they function or what values they operate on. For example,
              computed property functions may close over variables that are then no longer
              available for introspection.

              You can pass a hash of these values to a computed property like this:

              ```
              person: function() {
                var personId = this.get('personId');
                return App.Person.create({ id: personId });
              }.property().meta({ type: App.Person })
              ```

              The hash that you pass to the `meta()` function will be saved on the
              computed property descriptor under the `_meta` key. Ember runtime
              exposes a public API for retrieving these values from classes,
              via the `metaForProperty()` function.

              @method meta
              @param {Hash} meta
              @chainable
            */

        ComputedPropertyPrototype.meta = function(meta) {
            if (arguments.length === 0) {
                return this._meta || {};
            } else {
                this._meta = meta;
                return this;
            }
        };

        /* impl descriptor API */
        ComputedPropertyPrototype.didChange = function(obj, keyName) {
            // _suspended is set via a CP.set to ensure we don't clear
            // the cached value set by the setter
            if (this._cacheable && this._suspended !== obj) {
                var meta = metaFor(obj);
                if (meta.cache[keyName] !== undefined) {
                    meta.cache[keyName] = undefined;
                    removeDependentKeys(this, obj, keyName, meta);
                }
            }
        };

        function finishChains(chainNodes)
        {
            for (var i = 0, l = chainNodes.length; i < l; i++) {
                chainNodes[i].didChange(null);
            }
        }

        /**
              Access the value of the function backing the computed property.
              If this property has already been cached, return the cached result.
              Otherwise, call the function passing the property name as an argument.

              ```javascript
              var Person = Ember.Object.extend({
                fullName: function(keyName) {
                  // the keyName parameter is 'fullName' in this case.
                  return this.get('firstName') + ' ' + this.get('lastName');
                }.property('firstName', 'lastName')
              });


              var tom = Person.create({
                firstName: 'Tom',
                lastName: 'Dale'
              });

              tom.get('fullName') // 'Tom Dale'
              ```

              @method get
              @param {String} keyName The key being accessed.
              @return {Object} The return value of the function backing the CP.
            */
        ComputedPropertyPrototype.get = function(obj, keyName) {
            var ret, cache, meta, chainNodes;
            if (this._cacheable) {
                meta = metaFor(obj);
                cache = meta.cache;

                var result = cache[keyName];

                if (result === UNDEFINED) {
                    return undefined;
                } else if (result !== undefined) {
                    return result;
                }

                ret = this.func.call(obj, keyName);
                if (ret === undefined) {
                    cache[keyName] = UNDEFINED;
                } else {
                    cache[keyName] = ret;
                }

                chainNodes = meta.chainWatchers && meta.chainWatchers[keyName];
                if (chainNodes) {
                    finishChains(chainNodes);
                }
                addDependentKeys(this, obj, keyName, meta);
            } else {
                ret = this.func.call(obj, keyName);
            }
            return ret;
        };

        /**
              Set the value of a computed property. If the function that backs your
              computed property does not accept arguments then the default action for
              setting would be to define the property on the current object, and set
              the value of the property to the value being set.

              Generally speaking if you intend for your computed property to be set
              your backing function should accept either two or three arguments.

              @method set
              @param {String} keyName The key being accessed.
              @param {Object} newValue The new value being assigned.
              @param {String} oldValue The old value being replaced.
              @return {Object} The return value of the function backing the CP.
            */
        ComputedPropertyPrototype.set = function(obj, keyName, value) {
            var cacheable = this._cacheable,
            func = this.func,
            meta = metaFor(obj, cacheable),
            oldSuspended = this._suspended,
            hadCachedValue = false,
            cache = meta.cache,
            funcArgLength, cachedValue, ret;

            if (this._readOnly) {
                throw new EmberError('Cannot set read-only property "' + keyName + '" on object: ' + inspect(obj));
            }

            this._suspended = obj;

            try {

                if (cacheable && cache[keyName] !== undefined) {
                    if (cache[keyName] !== UNDEFINED) {
                        cachedValue = cache[keyName];
                    }

                    hadCachedValue = true;
                }

                // Check if the CP has been wrapped. If it has, use the
                // length from the wrapped function.

                funcArgLength = func.wrappedFunction ? func.wrappedFunction.__ember_arity__ : func.__ember_arity__;

                // For backwards-compatibility with computed properties
                // that check for arguments.length === 2 to determine if
                // they are being get or set, only pass the old cached
                // value if the computed property opts into a third
                // argument.
                if (funcArgLength === 3) {
                    ret = func.call(obj, keyName, value, cachedValue);
                } else if (funcArgLength === 2) {
                    ret = func.call(obj, keyName, value);
                } else {
                    defineProperty(obj, keyName, null, cachedValue);
                    set(obj, keyName, value);
                    return;
                }

                if (hadCachedValue && cachedValue === ret) {
                    return;
                }

                var watched = meta.watching[keyName];
                if (watched) {
                    propertyWillChange(obj, keyName);
                }

                if (hadCachedValue) {
                    cache[keyName] = undefined;
                }

                if (cacheable) {
                    if (!hadCachedValue) {
                        addDependentKeys(this, obj, keyName, meta);
                    }
                    if (ret === undefined) {
                        cache[keyName] = UNDEFINED;
                    } else {
                        cache[keyName] = ret;
                    }
                }

                if (watched) {
                    propertyDidChange(obj, keyName);
                }
            } finally {
                this._suspended = oldSuspended;
            }
            return ret;
        };

        /* called before property is overridden */
        ComputedPropertyPrototype.teardown = function(obj, keyName) {
            var meta = metaFor(obj);

            if (keyName in meta.cache) {
                removeDependentKeys(this, obj, keyName, meta);
            }

            if (this._cacheable) {
                delete meta.cache[keyName];
            }

            return null; // no value to restore
        };


        /**
              This helper returns a new property descriptor that wraps the passed
              computed property function. You can use this helper to define properties
              with mixins or via `Ember.defineProperty()`.

              The function you pass will be used to both get and set property values.
              The function should accept two parameters, key and value. If value is not
              undefined you should set the value first. In either case return the
              current value of the property.

              @method computed
              @for Ember
              @param {Function} func The computed property function.
              @return {Ember.ComputedProperty} property descriptor instance
            */
        function computed(func) {
            var args;

            if (arguments.length > 1) {
                args = a_slice.call(arguments);
                func = args.pop();
            }

            if (typeof func !== "function") {
                throw new EmberError("Computed Property declared without a property function");
            }

            var cp = new ComputedProperty(func);

            if (args) {
                cp.property.apply(cp, args);
            }

            return cp;
        }

        /**
              Returns the cached value for a property, if one exists.
              This can be useful for peeking at the value of a computed
              property that is generated lazily, without accidentally causing
              it to be created.

              @method cacheFor
              @for Ember
              @param {Object} obj the object whose property you want to check
              @param {String} key the name of the property whose cached value you want
                to return
              @return {Object} the cached value
            */
        function cacheFor(obj, key) {
            var meta = obj[META_KEY],
            cache = meta && meta.cache,
            ret = cache && cache[key];

            if (ret === UNDEFINED) {
                return undefined;
            }
            return ret;
        }

        cacheFor.set = function(cache, key, value) {
            if (value === undefined) {
                cache[key] = UNDEFINED;
            } else {
                cache[key] = value;
            }
        };

        cacheFor.get = function(cache, key) {
            var ret = cache[key];
            if (ret === UNDEFINED) {
                return undefined;
            }
            return ret;
        };

        cacheFor.remove = function(cache, key) {
            cache[key] = undefined;
        };

        __exports__.ComputedProperty = ComputedProperty;
        __exports__.computed = computed;
        __exports__.cacheFor = cacheFor;
    });
    define("ember-metal/computed_macros",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/computed", "ember-metal/is_empty", "ember-metal/is_none", "ember-metal/alias"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__) {
        "use strict";
        var Ember = __dependency1__["default"];
        var get = __dependency2__.get;
        var set = __dependency3__.set;
        var computed = __dependency4__.computed;
        var isEmpty = __dependency5__["default"];
        var isNone = __dependency6__.isNone;
        var alias = __dependency7__.alias;

        /**
            @module ember-metal
            */

        var a_slice = [].slice;

        function getProperties(self, propertyNames) {
            var ret = {};
            for (var i = 0; i < propertyNames.length; i++) {
                ret[propertyNames[i]] = get(self, propertyNames[i]);
            }
            return ret;
        }

        function registerComputed(name, macro) {
            computed[name] = function(dependentKey) {
                var args = a_slice.call(arguments);
                return computed(dependentKey, function() {
                    return macro.apply(this, args);
                });
            };
        }

        function registerComputedWithProperties(name, macro) {
            computed[name] = function() {
                var properties = a_slice.call(arguments);

                var computedFunc = computed(function() {
                    return macro.apply(this, [getProperties(this, properties)]);
                });

                return computedFunc.property.apply(computedFunc, properties);
            };
        }

        /**
              A computed property that returns true if the value of the dependent
              property is null, an empty string, empty array, or empty function.

              Example

              ```javascript
              var ToDoList = Ember.Object.extend({
                done: Ember.computed.empty('todos')
              });

              var todoList = ToDoList.create({
                todos: ['Unit Test', 'Documentation', 'Release']
              });

              todoList.get('done'); // false
              todoList.get('todos').clear();
              todoList.get('done'); // true
              ```

              @since 1.6.0
              @method computed.empty
              @for Ember
              @param {String} dependentKey
              @return {Ember.ComputedProperty} computed property which negate
              the original value for property
            */
        computed.empty = function (dependentKey) {
            return computed(dependentKey + '.length', function () {
                return isEmpty(get(this, dependentKey));
            });
        };

        /**
              A computed property that returns true if the value of the dependent
              property is NOT null, an empty string, empty array, or empty function.

              Note: When using `computed.notEmpty` to watch an array make sure to
              use the `array.[]` syntax so the computed can subscribe to transitions
              from empty to non-empty states.

              Example

              ```javascript
              var Hamster = Ember.Object.extend({
                hasStuff: Ember.computed.notEmpty('backpack.[]')
              });

              var hamster = Hamster.create({ backpack: ['Food', 'Sleeping Bag', 'Tent'] });

              hamster.get('hasStuff');         // true
              hamster.get('backpack').clear(); // []
              hamster.get('hasStuff');         // false
              ```

              @method computed.notEmpty
              @for Ember
              @param {String} dependentKey
              @return {Ember.ComputedProperty} computed property which returns true if
              original value for property is not empty.
            */
        registerComputed('notEmpty', function(dependentKey) {
            return !isEmpty(get(this, dependentKey));
        });

        /**
              A computed property that returns true if the value of the dependent
              property is null or undefined. This avoids errors from JSLint complaining
              about use of ==, which can be technically confusing.

              Example

              ```javascript
              var Hamster = Ember.Object.extend({
                isHungry: Ember.computed.none('food')
              });

              var hamster = Hamster.create();

              hamster.get('isHungry'); // true
              hamster.set('food', 'Banana');
              hamster.get('isHungry'); // false
              hamster.set('food', null);
              hamster.get('isHungry'); // true
              ```

              @method computed.none
              @for Ember
              @param {String} dependentKey
              @return {Ember.ComputedProperty} computed property which
              returns true if original value for property is null or undefined.
            */
        registerComputed('none', function(dependentKey) {
            return isNone(get(this, dependentKey));
        });

        /**
              A computed property that returns the inverse boolean value
              of the original value for the dependent property.

              Example

              ```javascript
              var User = Ember.Object.extend({
                isAnonymous: Ember.computed.not('loggedIn')
              });

              var user = User.create({loggedIn: false});

              user.get('isAnonymous'); // true
              user.set('loggedIn', true);
              user.get('isAnonymous'); // false
              ```

              @method computed.not
              @for Ember
              @param {String} dependentKey
              @return {Ember.ComputedProperty} computed property which returns
              inverse of the original value for property
            */
        registerComputed('not', function(dependentKey) {
            return !get(this, dependentKey);
        });

        /**
              A computed property that converts the provided dependent property
              into a boolean value.

              ```javascript
              var Hamster = Ember.Object.extend({
                hasBananas: Ember.computed.bool('numBananas')
              });

              var hamster = Hamster.create();

              hamster.get('hasBananas'); // false
              hamster.set('numBananas', 0);
              hamster.get('hasBananas'); // false
              hamster.set('numBananas', 1);
              hamster.get('hasBananas'); // true
              hamster.set('numBananas', null);
              hamster.get('hasBananas'); // false
              ```

              @method computed.bool
              @for Ember
              @param {String} dependentKey
              @return {Ember.ComputedProperty} computed property which converts
              to boolean the original value for property
            */
        registerComputed('bool', function(dependentKey) {
            return !!get(this, dependentKey);
        });

        /**
              A computed property which matches the original value for the
              dependent property against a given RegExp, returning `true`
              if they values matches the RegExp and `false` if it does not.

              Example

              ```javascript
              var User = Ember.Object.extend({
                hasValidEmail: Ember.computed.match('email', /^.+@.+\..+$/)
              });

              var user = User.create({loggedIn: false});

              user.get('hasValidEmail'); // false
              user.set('email', '');
              user.get('hasValidEmail'); // false
              user.set('email', 'ember_hamster@example.com');
              user.get('hasValidEmail'); // true
              ```

              @method computed.match
              @for Ember
              @param {String} dependentKey
              @param {RegExp} regexp
              @return {Ember.ComputedProperty} computed property which match
              the original value for property against a given RegExp
            */
        registerComputed('match', function(dependentKey, regexp) {
            var value = get(this, dependentKey);
            return typeof value === 'string' ? regexp.test(value) : false;
        });

        /**
              A computed property that returns true if the provided dependent property
              is equal to the given value.

              Example

              ```javascript
              var Hamster = Ember.Object.extend({
                napTime: Ember.computed.equal('state', 'sleepy')
              });

              var hamster = Hamster.create();

              hamster.get('napTime'); // false
              hamster.set('state', 'sleepy');
              hamster.get('napTime'); // true
              hamster.set('state', 'hungry');
              hamster.get('napTime'); // false
              ```

              @method computed.equal
              @for Ember
              @param {String} dependentKey
              @param {String|Number|Object} value
              @return {Ember.ComputedProperty} computed property which returns true if
              the original value for property is equal to the given value.
            */
        registerComputed('equal', function(dependentKey, value) {
            return get(this, dependentKey) === value;
        });

        /**
              A computed property that returns true if the provied dependent property
              is greater than the provided value.

              Example

              ```javascript
              var Hamster = Ember.Object.extend({
                hasTooManyBananas: Ember.computed.gt('numBananas', 10)
              });

              var hamster = Hamster.create();

              hamster.get('hasTooManyBananas'); // false
              hamster.set('numBananas', 3);
              hamster.get('hasTooManyBananas'); // false
              hamster.set('numBananas', 11);
              hamster.get('hasTooManyBananas'); // true
              ```

              @method computed.gt
              @for Ember
              @param {String} dependentKey
              @param {Number} value
              @return {Ember.ComputedProperty} computed property which returns true if
              the original value for property is greater then given value.
            */
        registerComputed('gt', function(dependentKey, value) {
            return get(this, dependentKey) > value;
        });

        /**
              A computed property that returns true if the provided dependent property
              is greater than or equal to the provided value.

              Example

              ```javascript
              var Hamster = Ember.Object.extend({
                hasTooManyBananas: Ember.computed.gte('numBananas', 10)
              });

              var hamster = Hamster.create();

              hamster.get('hasTooManyBananas'); // false
              hamster.set('numBananas', 3);
              hamster.get('hasTooManyBananas'); // false
              hamster.set('numBananas', 10);
              hamster.get('hasTooManyBananas'); // true
              ```

              @method computed.gte
              @for Ember
              @param {String} dependentKey
              @param {Number} value
              @return {Ember.ComputedProperty} computed property which returns true if
              the original value for property is greater or equal then given value.
            */
        registerComputed('gte', function(dependentKey, value) {
            return get(this, dependentKey) >= value;
        });

        /**
              A computed property that returns true if the provided dependent property
              is less than the provided value.

              Example

              ```javascript
              var Hamster = Ember.Object.extend({
                needsMoreBananas: Ember.computed.lt('numBananas', 3)
              });

              var hamster = Hamster.create();

              hamster.get('needsMoreBananas'); // true
              hamster.set('numBananas', 3);
              hamster.get('needsMoreBananas'); // false
              hamster.set('numBananas', 2);
              hamster.get('needsMoreBananas'); // true
              ```

              @method computed.lt
              @for Ember
              @param {String} dependentKey
              @param {Number} value
              @return {Ember.ComputedProperty} computed property which returns true if
              the original value for property is less then given value.
            */
        registerComputed('lt', function(dependentKey, value) {
            return get(this, dependentKey) < value;
        });

        /**
              A computed property that returns true if the provided dependent property
              is less than or equal to the provided value.

              Example

              ```javascript
              var Hamster = Ember.Object.extend({
                needsMoreBananas: Ember.computed.lte('numBananas', 3)
              });

              var hamster = Hamster.create();

              hamster.get('needsMoreBananas'); // true
              hamster.set('numBananas', 5);
              hamster.get('needsMoreBananas'); // false
              hamster.set('numBananas', 3);
              hamster.get('needsMoreBananas'); // true
              ```

              @method computed.lte
              @for Ember
              @param {String} dependentKey
              @param {Number} value
              @return {Ember.ComputedProperty} computed property which returns true if
              the original value for property is less or equal then given value.
            */
        registerComputed('lte', function(dependentKey, value) {
            return get(this, dependentKey) <= value;
        });

        /**
              A computed property that performs a logical `and` on the
              original values for the provided dependent properties.

              Example

              ```javascript
              var Hamster = Ember.Object.extend({
                readyForCamp: Ember.computed.and('hasTent', 'hasBackpack')
              });

              var hamster = Hamster.create();

              hamster.get('readyForCamp'); // false
              hamster.set('hasTent', true);
              hamster.get('readyForCamp'); // false
              hamster.set('hasBackpack', true);
              hamster.get('readyForCamp'); // true
              ```

              @method computed.and
              @for Ember
              @param {String} dependentKey*
              @return {Ember.ComputedProperty} computed property which performs
              a logical `and` on the values of all the original values for properties.
            */
        registerComputedWithProperties('and', function(properties) {
            for (var key in properties) {
                if (properties.hasOwnProperty(key) && !properties[key]) {
                    return false;
                }
            }
            return true;
        });

        /**
              A computed property which performs a logical `or` on the
              original values for the provided dependent properties.

              Example

              ```javascript
              var Hamster = Ember.Object.extend({
                readyForRain: Ember.computed.or('hasJacket', 'hasUmbrella')
              });

              var hamster = Hamster.create();

              hamster.get('readyForRain'); // false
              hamster.set('hasJacket', true);
              hamster.get('readyForRain'); // true
              ```

              @method computed.or
              @for Ember
              @param {String} dependentKey*
              @return {Ember.ComputedProperty} computed property which performs
              a logical `or` on the values of all the original values for properties.
            */
        registerComputedWithProperties('or', function(properties) {
            for (var key in properties) {
                if (properties.hasOwnProperty(key) && properties[key]) {
                    return true;
                }
            }
            return false;
        });

        /**
              A computed property that returns the first truthy value
              from a list of dependent properties.

              Example

              ```javascript
              var Hamster = Ember.Object.extend({
                hasClothes: Ember.computed.any('hat', 'shirt')
              });

              var hamster = Hamster.create();

              hamster.get('hasClothes'); // null
              hamster.set('shirt', 'Hawaiian Shirt');
              hamster.get('hasClothes'); // 'Hawaiian Shirt'
              ```

              @method computed.any
              @for Ember
              @param {String} dependentKey*
              @return {Ember.ComputedProperty} computed property which returns
              the first truthy value of given list of properties.
            */
        registerComputedWithProperties('any', function(properties) {
            for (var key in properties) {
                if (properties.hasOwnProperty(key) && properties[key]) {
                    return properties[key];
                }
            }
            return null;
        });

        /**
              A computed property that returns the array of values
              for the provided dependent properties.

              Example

              ```javascript
              var Hamster = Ember.Object.extend({
                clothes: Ember.computed.collect('hat', 'shirt')
              });

              var hamster = Hamster.create();

              hamster.get('clothes'); // [null, null]
              hamster.set('hat', 'Camp Hat');
              hamster.set('shirt', 'Camp Shirt');
              hamster.get('clothes'); // ['Camp Hat', 'Camp Shirt']
              ```

              @method computed.collect
              @for Ember
              @param {String} dependentKey*
              @return {Ember.ComputedProperty} computed property which maps
              values of all passed properties in to an array.
            */
        registerComputedWithProperties('collect', function(properties) {
            var res = [];
            for (var key in properties) {
                if (properties.hasOwnProperty(key)) {
                    if (isNone(properties[key])) {
                        res.push(null);
                    } else {
                        res.push(properties[key]);
                    }
                }
            }
            return res;
        });

        /**
              Creates a new property that is an alias for another property
              on an object. Calls to `get` or `set` this property behave as
              though they were called on the original property.

              ```javascript
              var Person = Ember.Object.extend({
                name: 'Alex Matchneer',
                nomen: Ember.computed.alias('name')
              });

              var alex = Person.create();

              alex.get('nomen'); // 'Alex Matchneer'
              alex.get('name');  // 'Alex Matchneer'

              alex.set('nomen', '@machty');
              alex.get('name');  // '@machty'
              ```

              @method computed.alias
              @for Ember
              @param {String} dependentKey
              @return {Ember.ComputedProperty} computed property which creates an
              alias to the original value for property.
            */
        computed.alias = alias;

        /**
              Where `computed.alias` aliases `get` and `set`, and allows for bidirectional
              data flow, `computed.oneWay` only provides an aliased `get`. The `set` will
              not mutate the upstream property, rather causes the current property to
              become the value set. This causes the downstream property to permanently
              diverge from the upstream property.

              Example

              ```javascript
              var User = Ember.Object.extend({
                firstName: null,
                lastName: null,
                nickName: Ember.computed.oneWay('firstName')
              });

              var teddy = User.create({
                firstName: 'Teddy',
                lastName:  'Zeenny'
              });

              teddy.get('nickName');              // 'Teddy'
              teddy.set('nickName', 'TeddyBear'); // 'TeddyBear'
              teddy.get('firstName');             // 'Teddy'
              ```

              @method computed.oneWay
              @for Ember
              @param {String} dependentKey
              @return {Ember.ComputedProperty} computed property which creates a
              one way computed property to the original value for property.
            */
        computed.oneWay = function(dependentKey) {
            return alias(dependentKey).oneWay();
        };


        /**
                This is a more semantically meaningful alias of `computed.oneWay`,
                whose name is somewhat ambiguous as to which direction the data flows.

                @method computed.reads
                @for Ember
                @param {String} dependentKey
                @return {Ember.ComputedProperty} computed property which creates a
                  one way computed property to the original value for property.
               */
        computed.reads = computed.oneWay;


        /**
              Where `computed.oneWay` provides oneWay bindings, `computed.readOnly` provides
              a readOnly one way binding. Very often when using `computed.oneWay` one does
              not also want changes to propogate back up, as they will replace the value.

              This prevents the reverse flow, and also throws an exception when it occurs.

              Example

              ```javascript
              var User = Ember.Object.extend({
                firstName: null,
                lastName: null,
                nickName: Ember.computed.readOnly('firstName')
              });

              var teddy = User.create({
                firstName: 'Teddy',
                lastName:  'Zeenny'
              });

              teddy.get('nickName');              // 'Teddy'
              teddy.set('nickName', 'TeddyBear'); // throws Exception
              // throw new Ember.Error('Cannot Set: nickName on: <User:ember27288>' );`
              teddy.get('firstName');             // 'Teddy'
              ```

              @method computed.readOnly
              @for Ember
              @param {String} dependentKey
              @return {Ember.ComputedProperty} computed property which creates a
              one way computed property to the original value for property.
              @since 1.5.0
            */
        computed.readOnly = function(dependentKey) {
            return alias(dependentKey).readOnly();
        };
        /**
              A computed property that acts like a standard getter and setter,
              but returns the value at the provided `defaultPath` if the
              property itself has not been set to a value

              Example

              ```javascript
              var Hamster = Ember.Object.extend({
                wishList: Ember.computed.defaultTo('favoriteFood')
              });

              var hamster = Hamster.create({ favoriteFood: 'Banana' });

              hamster.get('wishList');                     // 'Banana'
              hamster.set('wishList', 'More Unit Tests');
              hamster.get('wishList');                     // 'More Unit Tests'
              hamster.get('favoriteFood');                 // 'Banana'
              ```

              @method computed.defaultTo
              @for Ember
              @param {String} defaultPath
              @return {Ember.ComputedProperty} computed property which acts like
              a standard getter and setter, but defaults to the value from `defaultPath`.
            */
        // ES6TODO: computed should have its own export path so you can do import {defaultTo} from computed
        computed.defaultTo = function(defaultPath) {
            return computed(function(key, newValue, cachedValue) {
                if (arguments.length === 1) {
                    return get(this, defaultPath);
                }
                return newValue != null ? newValue : get(this, defaultPath);
            });
        };

        /**
              Creates a new property that is an alias for another property
              on an object. Calls to `get` or `set` this property behave as
              though they were called on the original property, but also
              print a deprecation warning.

              @method computed.deprecatingAlias
              @for Ember
              @param {String} dependentKey
              @return {Ember.ComputedProperty} computed property which creates an
              alias with a deprecation to the original value for property.
            */
        computed.deprecatingAlias = function(dependentKey) {
            return computed(dependentKey, function(key, value) {
                Ember.deprecate('Usage of `' + key + '` is deprecated, use `' + dependentKey + '` instead.');

                if (arguments.length > 1) {
                    set(this, dependentKey, value);
                    return value;
                } else {
                    return get(this, dependentKey);
                }
            });
        };
    });
    define("ember-metal/core",
    ["exports"],
    function(__exports__) {
        "use strict";
        /*globals Ember:true,Em:true,ENV,EmberENV,MetamorphENV:true */

        /**
            @module ember
            @submodule ember-metal
            */

        /**
              All Ember methods and functions are defined inside of this namespace. You
              generally should not add new properties to this namespace as it may be
              overwritten by future versions of Ember.

              You can also use the shorthand `Em` instead of `Ember`.

              Ember-Runtime is a framework that provides core functions for Ember including
              cross-platform functions, support for property observing and objects. Its
              focus is on small size and performance. You can use this in place of or
              along-side other cross-platform libraries such as jQuery.

              The core Runtime framework is based on the jQuery API with a number of
              performance optimizations.

              @class Ember
              @static
              @version 1.7.0-beta.4+pre.4b6ff143
            */

        if ('undefined' === typeof Ember) {
            // Create core object. Make it act like an instance of Ember.Namespace so that
            // objects assigned to it are given a sane string representation.
            Ember = {};
        }

        // Default imports, exports and lookup to the global object;
        var imports = Ember.imports = Ember.imports || this;
        var exports = Ember.exports = Ember.exports || this;
        var lookup = Ember.lookup = Ember.lookup || this;

        // aliases needed to keep minifiers from removing the global context
        exports.Em = exports.Ember = Ember;

        // Make sure these are set whether Ember was already defined or not

        Ember.isNamespace = true;

        Ember.toString = function() {
            return "Ember";
        };


        /**
              @property VERSION
              @type String
              @default '1.7.0-beta.4+pre.4b6ff143'
              @static
            */
        Ember.VERSION = '1.7.0-beta.4+pre.4b6ff143';

        /**
              Standard environmental variables. You can define these in a global `EmberENV`
              variable before loading Ember to control various configuration settings.

              For backwards compatibility with earlier versions of Ember the global `ENV`
              variable will be used if `EmberENV` is not defined.

              @property ENV
              @type Hash
            */

        if (Ember.ENV) {
            // do nothing if Ember.ENV is already setup
        } else if ('undefined' !== typeof EmberENV) {
            Ember.ENV = EmberENV;
        } else if ('undefined' !== typeof ENV) {
            Ember.ENV = ENV;
        } else {
            Ember.ENV = {};
        }

        Ember.config = Ember.config || {};

        // We disable the RANGE API by default for performance reasons
        if ('undefined' === typeof Ember.ENV.DISABLE_RANGE_API) {
            Ember.ENV.DISABLE_RANGE_API = true;
        }

        if ("undefined" === typeof MetamorphENV) {
            exports.MetamorphENV = {};
        }

        MetamorphENV.DISABLE_RANGE_API = Ember.ENV.DISABLE_RANGE_API;

        /**
              Hash of enabled Canary features. Add to before creating your application.

              You can also define `ENV.FEATURES` if you need to enable features flagged at runtime.

              @class FEATURES
              @namespace Ember
              @static
              @since 1.1.0
            */

        Ember.FEATURES = Ember.ENV.FEATURES || {};

        /**
              Test that a feature is enabled. Parsed by Ember's build tools to leave
              experimental features out of beta/stable builds.

              You can define the following configuration options:

              * `ENV.ENABLE_ALL_FEATURES` - force all features to be enabled.
              * `ENV.ENABLE_OPTIONAL_FEATURES` - enable any features that have not been explicitly
                enabled/disabled.

              @method isEnabled
              @param {String} feature
              @return {Boolean}
              @for Ember.FEATURES
              @since 1.1.0
            */

        Ember.FEATURES.isEnabled = function(feature) {
            var featureValue = Ember.FEATURES[feature];

            if (Ember.ENV.ENABLE_ALL_FEATURES) {
                return true;
            } else if (featureValue === true || featureValue === false || featureValue === undefined) {
                return featureValue;
            } else if (Ember.ENV.ENABLE_OPTIONAL_FEATURES) {
                return true;
            } else {
                return false;
            }
        };

        // ..........................................................
        // BOOTSTRAP
        //

        /**
              Determines whether Ember should enhance some built-in object prototypes to
              provide a more friendly API. If enabled, a few methods will be added to
              `Function`, `String`, and `Array`. `Object.prototype` will not be enhanced,
              which is the one that causes most trouble for people.

              In general we recommend leaving this option set to true since it rarely
              conflicts with other code. If you need to turn it off however, you can
              define an `ENV.EXTEND_PROTOTYPES` config to disable it.

              @property EXTEND_PROTOTYPES
              @type Boolean
              @default true
              @for Ember
            */
        Ember.EXTEND_PROTOTYPES = Ember.ENV.EXTEND_PROTOTYPES;

        if (typeof Ember.EXTEND_PROTOTYPES === 'undefined') {
            Ember.EXTEND_PROTOTYPES = true;
        }

        /**
              Determines whether Ember logs a full stack trace during deprecation warnings

              @property LOG_STACKTRACE_ON_DEPRECATION
              @type Boolean
              @default true
            */
        Ember.LOG_STACKTRACE_ON_DEPRECATION = (Ember.ENV.LOG_STACKTRACE_ON_DEPRECATION !== false);

        /**
              Determines whether Ember should add ECMAScript 5 shims to older browsers.

              @property SHIM_ES5
              @type Boolean
              @default Ember.EXTEND_PROTOTYPES
            */
        Ember.SHIM_ES5 = (Ember.ENV.SHIM_ES5 === false) ? false : Ember.EXTEND_PROTOTYPES;

        /**
              Determines whether Ember logs info about version of used libraries

              @property LOG_VERSION
              @type Boolean
              @default true
            */
        Ember.LOG_VERSION = (Ember.ENV.LOG_VERSION === false) ? false : true;

        /**
              Empty function. Useful for some operations. Always returns `this`.

              @method K
              @private
              @return {Object}
            */
        var K = function() {
            return this;
        };
        var K = K;
        __exports__.K = K;
        Ember.K = K;
        //TODO: ES6 GLOBL TODO

        // Stub out the methods defined by the ember-debug package in case it's not loaded

        if ('undefined' === typeof Ember.assert) {
            Ember.assert = Ember.K;
        }
        if ('undefined' === typeof Ember.warn) {
            Ember.warn = Ember.K;
        }
        if ('undefined' === typeof Ember.debug) {
            Ember.debug = Ember.K;
        }
        if ('undefined' === typeof Ember.runInDebug) {
            Ember.runInDebug = Ember.K;
        }
        if ('undefined' === typeof Ember.deprecate) {
            Ember.deprecate = Ember.K;
        }
        if ('undefined' === typeof Ember.deprecateFunc) {
            Ember.deprecateFunc = function(_, func) {
                return func;
            };
        }

        __exports__["default"] = Ember;
    });
    define("ember-metal/dependent_keys",
    ["ember-metal/platform", "ember-metal/watching", "exports"],
    function(__dependency1__, __dependency2__, __exports__) {
        "use strict";
        var create = __dependency1__.create;
        var watch = __dependency2__.watch;
        var unwatch = __dependency2__.unwatch;

        /**
            @module ember-metal
            */

        var o_create = create;

        // ..........................................................
        // DEPENDENT KEYS
        //

        // data structure:
        //  meta.deps = {
        //    'depKey': {
        //      'keyName': count,
        //    }
        //  }

        /*
              This function returns a map of unique dependencies for a
              given object and key.
            */
        function keysForDep(depsMeta, depKey) {
            var keys = depsMeta[depKey];
            if (!keys) {
                // if there are no dependencies yet for a the given key
                // create a new empty list of dependencies for the key
                keys = depsMeta[depKey] = {};
            } else if (!depsMeta.hasOwnProperty(depKey)) {
                // otherwise if the dependency list is inherited from
                // a superclass, clone the hash
                keys = depsMeta[depKey] = o_create(keys);
            }
            return keys;
        }

        function metaForDeps(meta) {
            return keysForDep(meta, 'deps');
        }

        function addDependentKeys(desc, obj, keyName, meta) {
            // the descriptor has a list of dependent keys, so
            // add all of its dependent keys.
            var depKeys = desc._dependentKeys, depsMeta, idx, len, depKey, keys;
            if (!depKeys) 
                return;

            depsMeta = metaForDeps(meta);

            for (idx = 0, len = depKeys.length; idx < len; idx++) {
                depKey = depKeys[idx];
                // Lookup keys meta for depKey
                keys = keysForDep(depsMeta, depKey);
                // Increment the number of times depKey depends on keyName.
                keys[keyName] = (keys[keyName] || 0) + 1;
                // Watch the depKey
                watch(obj, depKey, meta);
            }
        }

        __exports__.addDependentKeys = addDependentKeys;
        function removeDependentKeys(desc, obj, keyName, meta) {
            // the descriptor has a list of dependent keys, so
            // remove all of its dependent keys.
            var depKeys = desc._dependentKeys, depsMeta, idx, len, depKey, keys;
            if (!depKeys) 
                return;

            depsMeta = metaForDeps(meta);

            for (idx = 0, len = depKeys.length; idx < len; idx++) {
                depKey = depKeys[idx];
                // Lookup keys meta for depKey
                keys = keysForDep(depsMeta, depKey);
                // Decrement the number of times depKey depends on keyName.
                keys[keyName] = (keys[keyName] || 0) - 1;
                // Unwatch the depKey
                unwatch(obj, depKey, meta);
            }
        }
        __exports__.removeDependentKeys = removeDependentKeys;
    });
    define("ember-metal/enumerable_utils",
    ["ember-metal/array", "exports"],
    function(__dependency1__, __exports__) {
        "use strict";
        var _filter = __dependency1__.filter;
        var a_forEach = __dependency1__.forEach;
        var _indexOf = __dependency1__.indexOf;
        var _map = __dependency1__.map;

        var splice = Array.prototype.splice;

        /**
             * Defines some convenience methods for working with Enumerables.
             * `Ember.EnumerableUtils` uses `Ember.ArrayPolyfills` when necessary.
             *
             * @class EnumerableUtils
             * @namespace Ember
             * @static
             * */

        /**
             * Calls the map function on the passed object with a specified callback. This
             * uses `Ember.ArrayPolyfill`'s-map method when necessary.
             *
             * @method map
             * @param {Object} obj The object that should be mapped
             * @param {Function} callback The callback to execute
             * @param {Object} thisArg Value to use as this when executing *callback*
             *
             * @return {Array} An array of mapped values.
             */
        function map(obj, callback, thisArg) {
            return obj.map ? obj.map.call(obj, callback, thisArg) : _map.call(obj, callback, thisArg);
        }

        __exports__.map = map; /**
             * Calls the forEach function on the passed object with a specified callback. This
             * uses `Ember.ArrayPolyfill`'s-forEach method when necessary.
             *
             * @method forEach
             * @param {Object} obj The object to call forEach on
             * @param {Function} callback The callback to execute
             * @param {Object} thisArg Value to use as this when executing *callback*
             *
             */
        function forEach(obj, callback, thisArg) {
            return obj.forEach ? obj.forEach.call(obj, callback, thisArg) : a_forEach.call(obj, callback, thisArg);
        }

        __exports__.forEach = forEach; /**
             * Calls the filter function on the passed object with a specified callback. This
             * uses `Ember.ArrayPolyfill`'s-filter method when necessary.
             *
             * @method filter
             * @param {Object} obj The object to call filter on
             * @param {Function} callback The callback to execute
             * @param {Object} thisArg Value to use as this when executing *callback*
             *
             * @return {Array} An array containing the filtered values
             * @since 1.4.0
             */
        function filter(obj, callback, thisArg) {
            return obj.filter ? obj.filter.call(obj, callback, thisArg) : _filter.call(obj, callback, thisArg);
        }

        __exports__.filter = filter; /**
             * Calls the indexOf function on the passed object with a specified callback. This
             * uses `Ember.ArrayPolyfill`'s-indexOf method when necessary.
             *
             * @method indexOf
             * @param {Object} obj The object to call indexOn on
             * @param {Function} callback The callback to execute
             * @param {Object} index The index to start searching from
             *
             */
        function indexOf(obj, element, index) {
            return obj.indexOf ? obj.indexOf.call(obj, element, index) : _indexOf.call(obj, element, index);
        }

        __exports__.indexOf = indexOf; /**
             * Returns an array of indexes of the first occurrences of the passed elements
             * on the passed object.
             *
             * ```javascript
             *  var array = [1, 2, 3, 4, 5];
             *  Ember.EnumerableUtils.indexesOf(array, [2, 5]); // [1, 4]
             *
             *  var fubar = "Fubarr";
             *  Ember.EnumerableUtils.indexesOf(fubar, ['b', 'r']); // [2, 4]
             * ```
             *
             * @method indexesOf
             * @param {Object} obj The object to check for element indexes
             * @param {Array} elements The elements to search for on *obj*
             *
             * @return {Array} An array of indexes.
             *
             */
        function indexesOf(obj, elements) {
            return elements === undefined ? [] : map(elements, function(item) {
                return indexOf(obj, item);
            });
        }

        __exports__.indexesOf = indexesOf; /**
             * Adds an object to an array. If the array already includes the object this
             * method has no effect.
             *
             * @method addObject
             * @param {Array} array The array the passed item should be added to
             * @param {Object} item The item to add to the passed array
             *
             * @return 'undefined'
             */
        function addObject(array, item) {
            var index = indexOf(array, item);
            if (index === -1) {
                array.push(item);
            }
        }

        __exports__.addObject = addObject; /**
             * Removes an object from an array. If the array does not contain the passed
             * object this method has no effect.
             *
             * @method removeObject
             * @param {Array} array The array to remove the item from.
             * @param {Object} item The item to remove from the passed array.
             *
             * @return 'undefined'
             */
        function removeObject(array, item) {
            var index = indexOf(array, item);
            if (index !== -1) {
                array.splice(index, 1);
            }
        }

        __exports__.removeObject = removeObject;
        function _replace(array, idx, amt, objects) {
            var args = [].concat(objects), chunk, ret = [],
            // https://code.google.com/p/chromium/issues/detail?id=56588
            size = 60000, start = idx, ends = amt, count;

            while (args.length) {
                count = ends > size ? size : ends;
                if (count <= 0) {
                    count = 0;
                }

                chunk = args.splice(0, size);
                chunk = [start, count].concat(chunk);

                start += size;
                ends -= count;

                ret = ret.concat(splice.apply(array, chunk));
            }
            return ret;
        }

        __exports__._replace = _replace; /**
             * Replaces objects in an array with the passed objects.
             *
             * ```javascript
             *   var array = [1,2,3];
             *   Ember.EnumerableUtils.replace(array, 1, 2, [4, 5]); // [1, 4, 5]
             *
             *   var array = [1,2,3];
             *   Ember.EnumerableUtils.replace(array, 1, 1, [4, 5]); // [1, 4, 5, 3]
             *
             *   var array = [1,2,3];
             *   Ember.EnumerableUtils.replace(array, 10, 1, [4, 5]); // [1, 2, 3, 4, 5]
             * ```
             *
             * @method replace
             * @param {Array} array The array the objects should be inserted into.
             * @param {Number} idx Starting index in the array to replace. If *idx* >=
             * length, then append to the end of the array.
             * @param {Number} amt Number of elements that should be removed from the array,
             * starting at *idx*
             * @param {Array} objects An array of zero or more objects that should be
             * inserted into the array at *idx*
             *
             * @return {Array} The modified array.
             */
        function replace(array, idx, amt, objects) {
            if (array.replace) {
                return array.replace(idx, amt, objects);
            } else {
                return _replace(array, idx, amt, objects);
            }
        }

        __exports__.replace = replace; /**
             * Calculates the intersection of two arrays. This method returns a new array
             * filled with the records that the two passed arrays share with each other.
             * If there is no intersection, an empty array will be returned.
             *
             * ```javascript
             * var array1 = [1, 2, 3, 4, 5];
             * var array2 = [1, 3, 5, 6, 7];
             *
             * Ember.EnumerableUtils.intersection(array1, array2); // [1, 3, 5]
             *
             * var array1 = [1, 2, 3];
             * var array2 = [4, 5, 6];
             *
             * Ember.EnumerableUtils.intersection(array1, array2); // []
             * ```
             *
             * @method intersection
             * @param {Array} array1 The first array
             * @param {Array} array2 The second array
             *
             * @return {Array} The intersection of the two passed arrays.
             */
        function intersection(array1, array2) {
            var result = [];
            forEach(array1, function(element) {
                if (indexOf(array2, element) >= 0) {
                    result.push(element);
                }
            });

            return result;
        }

        __exports__.intersection = intersection; // TODO: this only exists to maintain the existing api, as we move forward it
        // should only be part of the "global build" via some shim
        __exports__["default"] = {
            _replace: _replace,
            addObject: addObject,
            filter: filter,
            forEach: forEach,
            indexOf: indexOf,
            indexesOf: indexesOf,
            intersection: intersection,
            map: map,
            removeObject: removeObject,
            replace: replace
        };
    });
    define("ember-metal/error",
    ["ember-metal/platform", "exports"],
    function(__dependency1__, __exports__) {
        "use strict";
        var create = __dependency1__.create;

        var errorProps = [
        'description',
        'fileName',
        'lineNumber',
        'message',
        'name',
        'number',
        'stack'
        ];

        /**
              A subclass of the JavaScript Error object for use in Ember.

              @class Error
              @namespace Ember
              @extends Error
              @constructor
            */
        function EmberError() {
            var tmp = Error.apply(this, arguments);

            // Adds a `stack` property to the given error object that will yield the
            // stack trace at the time captureStackTrace was called.
            // When collecting the stack trace all frames above the topmost call
            // to this function, including that call, will be left out of the
            // stack trace.
            // This is useful because we can hide Ember implementation details
            // that are not very helpful for the user.
            if (Error.captureStackTrace) {
                Error.captureStackTrace(this, Ember.Error);
            }
            // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
            for (var idx = 0; idx < errorProps.length; idx++) {
                this[errorProps[idx]] = tmp[errorProps[idx]];
            }
        }

        EmberError.prototype = create(Error.prototype);

        __exports__["default"] = EmberError;
    });
    define("ember-metal/events",
    ["ember-metal/core", "ember-metal/utils", "ember-metal/platform", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        /**
            @module ember-metal
            */
        var Ember = __dependency1__["default"];
        var meta = __dependency2__.meta;
        var META_KEY = __dependency2__.META_KEY;
        var tryFinally = __dependency2__.tryFinally;
        var apply = __dependency2__.apply;
        var applyStr = __dependency2__.applyStr;
        var create = __dependency3__.create;

        var a_slice = [].slice,
        metaFor = meta,
        /* listener flags */
        ONCE = 1, SUSPENDED = 2;


        /*
              The event system uses a series of nested hashes to store listeners on an
              object. When a listener is registered, or when an event arrives, these
              hashes are consulted to determine which target and action pair to invoke.

              The hashes are stored in the object's meta hash, and look like this:

                  // Object's meta hash
                  {
                    listeners: {       // variable name: `listenerSet`
                      "foo:changed": [ // variable name: `actions`
                        target, method, flags
                      ]
                    }
                  }

            */

        function indexOf(array, target, method) {
            var index = -1;
            // hashes are added to the end of the event array
            // so it makes sense to start searching at the end
            // of the array and search in reverse
            for (var i = array.length - 3 ; i >= 0; i -= 3) {
                if (target === array[i] && method === array[i + 1]) {
                    index = i;
                    break;
                }
            }
            return index;
        }

        function actionsFor(obj, eventName) {
            var meta = metaFor(obj, true),
            actions;

            if (!meta.listeners) {
                meta.listeners = {};
            }

            if (!meta.hasOwnProperty('listeners')) {
                // setup inherited copy of the listeners object
                meta.listeners = create(meta.listeners);
            }

            actions = meta.listeners[eventName];

            // if there are actions, but the eventName doesn't exist in our listeners, then copy them from the prototype
            if (actions && !meta.listeners.hasOwnProperty(eventName)) {
                actions = meta.listeners[eventName] = meta.listeners[eventName].slice();
            } else if (!actions) {
                actions = meta.listeners[eventName] = [];
            }

            return actions;
        }

        function listenersUnion(obj, eventName, otherActions) {
            var meta = obj[META_KEY],
            actions = meta && meta.listeners && meta.listeners[eventName];

            if (!actions) {
                return;
            }
            for (var i = actions.length - 3; i >= 0; i -= 3) {
                var target = actions[i],
                method = actions[i + 1],
                flags = actions[i + 2],
                actionIndex = indexOf(otherActions, target, method);

                if (actionIndex === -1) {
                    otherActions.push(target, method, flags);
                }
            }
        }

        __exports__.listenersUnion = listenersUnion;
        function listenersDiff(obj, eventName, otherActions) {
            var meta = obj[META_KEY],
            actions = meta && meta.listeners && meta.listeners[eventName],
            diffActions = [];

            if (!actions) {
                return;
            }
            for (var i = actions.length - 3; i >= 0; i -= 3) {
                var target = actions[i],
                method = actions[i + 1],
                flags = actions[i + 2],
                actionIndex = indexOf(otherActions, target, method);

                if (actionIndex !== -1) {
                    continue;
                }

                otherActions.push(target, method, flags);
                diffActions.push(target, method, flags);
            }

            return diffActions;
        }

        __exports__.listenersDiff = listenersDiff; /**
              Add an event listener

              @method addListener
              @for Ember
              @param obj
              @param {String} eventName
              @param {Object|Function} targetOrMethod A target object or a function
              @param {Function|String} method A function or the name of a function to be called on `target`
              @param {Boolean} once A flag whether a function should only be called once
            */
        function addListener(obj, eventName, target, method, once) {
            Ember.assert("You must pass at least an object and event name to Ember.addListener", !!obj && !!eventName);

            if (!method && 'function' === typeof target) {
                method = target;
                target = null;
            }

            var actions = actionsFor(obj, eventName),
            actionIndex = indexOf(actions, target, method),
            flags = 0;

            if (once) 
                flags |= ONCE;

            if (actionIndex !== -1) {
                return;
            }

            actions.push(target, method, flags);

            if ('function' === typeof obj.didAddListener) {
                obj.didAddListener(eventName, target, method);
            }
        }

        __exports__.addListener = addListener; /**
              Remove an event listener

              Arguments should match those passed to `Ember.addListener`.

              @method removeListener
              @for Ember
              @param obj
              @param {String} eventName
              @param {Object|Function} targetOrMethod A target object or a function
              @param {Function|String} method A function or the name of a function to be called on `target`
            */
        function removeListener(obj, eventName, target, method) {
            Ember.assert("You must pass at least an object and event name to Ember.removeListener", !!obj && !!eventName);

            if (!method && 'function' === typeof target) {
                method = target;
                target = null;
            }

            function _removeListener(target, method) {
                var actions = actionsFor(obj, eventName),
                actionIndex = indexOf(actions, target, method);

                // action doesn't exist, give up silently
                if (actionIndex === -1) {
                    return;
                }

                actions.splice(actionIndex, 3);

                if ('function' === typeof obj.didRemoveListener) {
                    obj.didRemoveListener(eventName, target, method);
                }
            }

            if (method) {
                _removeListener(target, method);
            } else {
                var meta = obj[META_KEY],
                actions = meta && meta.listeners && meta.listeners[eventName];

                if (!actions) {
                    return;
                }
                for (var i = actions.length - 3; i >= 0; i -= 3) {
                    _removeListener(actions[i], actions[i + 1]);
                }
            }
        }

        /**
              Suspend listener during callback.

              This should only be used by the target of the event listener
              when it is taking an action that would cause the event, e.g.
              an object might suspend its property change listener while it is
              setting that property.

              @method suspendListener
              @for Ember

              @private
              @param obj
              @param {String} eventName
              @param {Object|Function} targetOrMethod A target object or a function
              @param {Function|String} method A function or the name of a function to be called on `target`
              @param {Function} callback
            */
        function suspendListener(obj, eventName, target, method, callback) {
            if (!method && 'function' === typeof target) {
                method = target;
                target = null;
            }

            var actions = actionsFor(obj, eventName),
            actionIndex = indexOf(actions, target, method);

            if (actionIndex !== -1) {
                actions[actionIndex + 2] |= SUSPENDED; // mark the action as suspended
            }

            function tryable() {
                return callback.call(target);
            }
            function finalizer() {
                if (actionIndex !== -1) {
                    actions[actionIndex + 2] &= ~SUSPENDED;
                }
            }

            return tryFinally(tryable, finalizer);
        }

        __exports__.suspendListener = suspendListener; /**
              Suspends multiple listeners during a callback.

              @method suspendListeners
              @for Ember

              @private
              @param obj
              @param {Array} eventName Array of event names
              @param {Object|Function} targetOrMethod A target object or a function
              @param {Function|String} method A function or the name of a function to be called on `target`
              @param {Function} callback
            */
        function suspendListeners(obj, eventNames, target, method, callback) {
            if (!method && 'function' === typeof target) {
                method = target;
                target = null;
            }

            var suspendedActions = [],
            actionsList = [],
            eventName, actions, i, l;

            for (i = 0, l = eventNames.length; i < l; i++) {
                eventName = eventNames[i];
                actions = actionsFor(obj, eventName);
                var actionIndex = indexOf(actions, target, method);

                if (actionIndex !== -1) {
                    actions[actionIndex + 2] |= SUSPENDED;
                    suspendedActions.push(actionIndex);
                    actionsList.push(actions);
                }
            }

            function tryable() {
                return callback.call(target);
            }

            function finalizer() {
                for (var i = 0, l = suspendedActions.length; i < l; i++) {
                    var actionIndex = suspendedActions[i];
                    actionsList[i][actionIndex + 2] &= ~SUSPENDED;
                }
            }

            return tryFinally(tryable, finalizer);
        }

        __exports__.suspendListeners = suspendListeners; /**
              Return a list of currently watched events

              @private
              @method watchedEvents
              @for Ember
              @param obj
            */
        function watchedEvents(obj) {
            var listeners = obj[META_KEY].listeners, ret = [];

            if (listeners) {
                for (var eventName in listeners) {
                    if (listeners[eventName]) {
                        ret.push(eventName);
                    }
                }
            }
            return ret;
        }

        __exports__.watchedEvents = watchedEvents; /**
              Send an event. The execution of suspended listeners
              is skipped, and once listeners are removed. A listener without
              a target is executed on the passed object. If an array of actions
              is not passed, the actions stored on the passed object are invoked.

              @method sendEvent
              @for Ember
              @param obj
              @param {String} eventName
              @param {Array} params Optional parameters for each listener.
              @param {Array} actions Optional array of actions (listeners).
              @return true
            */
        function sendEvent(obj, eventName, params, actions) {
            // first give object a chance to handle it
            if (obj !== Ember && 'function' === typeof obj.sendEvent) {
                obj.sendEvent(eventName, params);
            }

            if (!actions) {
                var meta = obj[META_KEY];
                actions = meta && meta.listeners && meta.listeners[eventName];
            }

            if (!actions) {
                return;
            }

            for (var i = actions.length - 3; i >= 0; i -= 3) {
                // looping in reverse for once listeners
                var target = actions[i], method = actions[i + 1], flags = actions[i + 2];
                if (!method) {
                    continue;
                }
                if (flags & SUSPENDED) {
                    continue;
                }
                if (flags & ONCE) {
                    removeListener(obj, eventName, target, method);
                }
                if (!target) {
                    target = obj;
                }
                if ('string' === typeof method) {
                    if (params) {
                        applyStr(target, method, params);
                    } else {
                        target[method]();
                    }
                } else {
                    if (params) {
                        apply(target, method, params);
                    } else {
                        method.call(target);
                    }
                }
            }
            return true;
        }

        __exports__.sendEvent = sendEvent; /**
              @private
              @method hasListeners
              @for Ember
              @param obj
              @param {String} eventName
            */
        function hasListeners(obj, eventName) {
            var meta = obj[META_KEY],
            actions = meta && meta.listeners && meta.listeners[eventName];

            return !!(actions && actions.length);
        }

        __exports__.hasListeners = hasListeners; /**
              @private
              @method listenersFor
              @for Ember
              @param obj
              @param {String} eventName
            */
        function listenersFor(obj, eventName) {
            var ret = [];
            var meta = obj[META_KEY],
            actions = meta && meta.listeners && meta.listeners[eventName];

            if (!actions) {
                return ret;
            }

            for (var i = 0, l = actions.length; i < l; i += 3) {
                var target = actions[i],
                method = actions[i + 1];
                ret.push([target, method]);
            }

            return ret;
        }

        __exports__.listenersFor = listenersFor; /**
              Define a property as a function that should be executed when
              a specified event or events are triggered.


              ``` javascript
              var Job = Ember.Object.extend({
                logCompleted: Ember.on('completed', function() {
                  console.log('Job completed!');
                })
              });

              var job = Job.create();

              Ember.sendEvent(job, 'completed'); // Logs 'Job completed!'
             ```

              @method on
              @for Ember
              @param {String} eventNames*
              @param {Function} func
              @return func
            */
        function on() {
            var func = a_slice.call(arguments, -1)[0],
            events = a_slice.call(arguments, 0, -1);
            func.__ember_listens__ = events;
            return func;
        }

        __exports__.on = on;
        __exports__.removeListener = removeListener;
    });
    define("ember-metal/expand_properties",
    ["ember-metal/error", "ember-metal/enumerable_utils", "exports"],
    function(__dependency1__, __dependency2__, __exports__) {
        "use strict";
        var EmberError = __dependency1__["default"];
        var forEach = __dependency2__.forEach;

        /**
              @module ember-metal
              */

        var BRACE_EXPANSION = /^((?:[^\.]*\.)*)\{(.*)\}$/;

        /**
              Expands `pattern`, invoking `callback` for each expansion.

              The only pattern supported is brace-expansion, anything else will be passed
              once to `callback` directly. Brace expansion can only appear at the end of a
              pattern, for an example see the last call below.

              Example
              ```js
              function echo(arg){ console.log(arg); }

              Ember.expandProperties('foo.bar', echo);        //=> 'foo.bar'
              Ember.expandProperties('{foo,bar}', echo);      //=> 'foo', 'bar'
              Ember.expandProperties('foo.{bar,baz}', echo);  //=> 'foo.bar', 'foo.baz'
              Ember.expandProperties('{foo,bar}.baz', echo);  //=> '{foo,bar}.baz'
              ```

              @method
              @private
              @param {string} pattern The property pattern to expand.
              @param {function} callback The callback to invoke.  It is invoked once per
              expansion, and is passed the expansion.
              */
        __exports__["default"] = function expandProperties(pattern, callback) {
            var match, prefix, list;

            if (pattern.indexOf(' ') > -1) {
                throw new EmberError('Brace expanded properties cannot contain spaces, ' + 
                'e.g. `user.{firstName, lastName}` should be `user.{firstName,lastName}`');
            }

            if (match = BRACE_EXPANSION.exec(pattern)) {
                prefix = match[1];
                list = match[2];

                forEach(list.split(','), function (suffix) {
                    callback(prefix + suffix);
                });
            } else {
                callback(pattern);
            }
        }
    });
    define("ember-metal/get_properties",
    ["ember-metal/property_get", "ember-metal/utils", "exports"],
    function(__dependency1__, __dependency2__, __exports__) {
        "use strict";
        var get = __dependency1__.get;
        var typeOf = __dependency2__.typeOf;

        /**
              To get multiple properties at once, call `Ember.getProperties`
              with an object followed by a list of strings or an array:

              ```javascript
              Ember.getProperties(record, 'firstName', 'lastName', 'zipCode');
              // { firstName: 'John', lastName: 'Doe', zipCode: '10011' }
              ```

              is equivalent to:

              ```javascript
              Ember.getProperties(record, ['firstName', 'lastName', 'zipCode']);
              // { firstName: 'John', lastName: 'Doe', zipCode: '10011' }
              ```

              @method getProperties
              @param obj
              @param {String...|Array} list of keys to get
              @return {Hash}
            */
        __exports__["default"] = function getProperties(obj) {
            var ret = {},
            propertyNames = arguments,
            i = 1;

            if (arguments.length === 2 && typeOf(arguments[1]) === 'array') {
                i = 0;
                propertyNames = arguments[1];
            }
            for (var len = propertyNames.length; i < len; i++) {
                ret[propertyNames[i]] = get(obj, propertyNames[i]);
            }
            return ret;
        }
    });
    define("ember-metal/instrumentation",
    ["ember-metal/core", "ember-metal/utils", "exports"],
    function(__dependency1__, __dependency2__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        var tryCatchFinally = __dependency2__.tryCatchFinally;

        /**
              The purpose of the Ember Instrumentation module is
              to provide efficient, general-purpose instrumentation
              for Ember.

              Subscribe to a listener by using `Ember.subscribe`:

              ```javascript
              Ember.subscribe("render", {
                before: function(name, timestamp, payload) {

                },

                after: function(name, timestamp, payload) {

                }
              });
              ```

              If you return a value from the `before` callback, that same
              value will be passed as a fourth parameter to the `after`
              callback.

              Instrument a block of code by using `Ember.instrument`:

              ```javascript
              Ember.instrument("render.handlebars", payload, function() {
                // rendering logic
              }, binding);
              ```

              Event names passed to `Ember.instrument` are namespaced
              by periods, from more general to more specific. Subscribers
              can listen for events by whatever level of granularity they
              are interested in.

              In the above example, the event is `render.handlebars`,
              and the subscriber listened for all events beginning with
              `render`. It would receive callbacks for events named
              `render`, `render.handlebars`, `render.container`, or
              even `render.handlebars.layout`.

              @class Instrumentation
              @namespace Ember
              @static
            */
        var subscribers = [], cache = {};

        var populateListeners = function(name) {
            var listeners = [], subscriber;

            for (var i = 0, l = subscribers.length; i < l; i++) {
                subscriber = subscribers[i];
                if (subscriber.regex.test(name)) {
                    listeners.push(subscriber.object);
                }
            }

            cache[name] = listeners;
            return listeners;
        };

        var time = (function() {
            var perf = 'undefined' !== typeof window ? window.performance || {}
            : {};
            var fn = perf.now || perf.mozNow || perf.webkitNow || perf.msNow || perf.oNow;
            // fn.bind will be available in all the browsers that support the advanced window.performance... ;-)
            return fn ? fn.bind(perf) : function() {
                return + new Date();
            };
        })();

        /**
              Notifies event's subscribers, calls `before` and `after` hooks.

              @method instrument
              @namespace Ember.Instrumentation

              @param {String} [name] Namespaced event name.
              @param {Object} payload
              @param {Function} callback Function that you're instrumenting.
              @param {Object} binding Context that instrument function is called with.
            */
        function instrument(name, payload, callback, binding) {
            var listeners = cache[name], timeName, ret;

            // ES6TODO: Docs. What is this?
            if (Ember.STRUCTURED_PROFILE) {
                timeName = name + ": " + payload.object;
                console.time(timeName);
            }

            if (!listeners) {
                listeners = populateListeners(name);
            }

            if (listeners.length === 0) {
                ret = callback.call(binding);
                if (Ember.STRUCTURED_PROFILE) {
                    console.timeEnd(timeName);
                }
                return ret;
            }

            var beforeValues = [], listener, i, l;

            function tryable() {
                for (i = 0, l = listeners.length; i < l; i++) {
                    listener = listeners[i];
                    beforeValues[i] = listener.before(name, time(), payload);
                }

                return callback.call(binding);
            }

            function catchable(e) {
                payload = payload || {};
                payload.exception = e;
            }

            function finalizer() {
                for (i = 0, l = listeners.length; i < l; i++) {
                    listener = listeners[i];
                    listener.after(name, time(), payload, beforeValues[i]);
                }

                if (Ember.STRUCTURED_PROFILE) {
                    console.timeEnd(timeName);
                }
            }

            return tryCatchFinally(tryable, catchable, finalizer);
        }

        __exports__.instrument = instrument; /**
              Subscribes to a particular event or instrumented block of code.

              @method subscribe
              @namespace Ember.Instrumentation

              @param {String} [pattern] Namespaced event name.
              @param {Object} [object] Before and After hooks.

              @return {Subscriber}
            */
        function subscribe(pattern, object) {
            var paths = pattern.split("."), path, regex = [];

            for (var i = 0, l = paths.length; i < l; i++) {
                path = paths[i];
                if (path === "*") {
                    regex.push("[^\\.]*");
                } else {
                    regex.push(path);
                }
            }

            regex = regex.join("\\.");
            regex = regex + "(\\..*)?";

            var subscriber = {
                pattern: pattern,
                regex: new RegExp("^" + regex + "$"),
                object: object
            };

            subscribers.push(subscriber);
            cache = {};

            return subscriber;
        }

        __exports__.subscribe = subscribe; /**
              Unsubscribes from a particular event or instrumented block of code.

              @method unsubscribe
              @namespace Ember.Instrumentation

              @param {Object} [subscriber]
            */
        function unsubscribe(subscriber) {
            var index;

            for (var i = 0, l = subscribers.length; i < l; i++) {
                if (subscribers[i] === subscriber) {
                    index = i;
                }
            }

            subscribers.splice(index, 1);
            cache = {};
        }

        __exports__.unsubscribe = unsubscribe; /**
              Resets `Ember.Instrumentation` by flushing list of subscribers.

              @method reset
              @namespace Ember.Instrumentation
            */
        function reset() {
            subscribers = [];
            cache = {};
        }

        __exports__.reset = reset;
    });
    define("ember-metal/is_blank",
    ["ember-metal/core", "ember-metal/is_empty", "exports"],
    function(__dependency1__, __dependency2__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // deprecateFunc
        var isEmpty = __dependency2__["default"];

        /**
              A value is blank if it is empty or a whitespace string.

              ```javascript
              Ember.isBlank();                // true
              Ember.isBlank(null);            // true
              Ember.isBlank(undefined);       // true
              Ember.isBlank('');              // true
              Ember.isBlank([]);              // true
              Ember.isBlank('\n\t');          // true
              Ember.isBlank('  ');            // true
              Ember.isBlank({});              // false
              Ember.isBlank('\n\t Hello');    // false
              Ember.isBlank('Hello world');   // false
              Ember.isBlank([1,2,3]);         // false
              ```

              @method isBlank
              @for Ember
              @param {Object} obj Value to test
              @return {Boolean}
              @since 1.5.0
              */
        __exports__["default"] = function isBlank(obj) {
            return isEmpty(obj) || (typeof obj === 'string' && obj.match(/\S/) === null);
        }
    });
    define("ember-metal/is_empty",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/is_none", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // deprecateFunc
        var get = __dependency2__.get;
        var isNone = __dependency3__["default"];

        /**
              Verifies that a value is `null` or an empty string, empty array,
              or empty function.

              Constrains the rules on `Ember.isNone` by returning false for empty
              string and empty arrays.

              ```javascript
              Ember.isEmpty();                // true
              Ember.isEmpty(null);            // true
              Ember.isEmpty(undefined);       // true
              Ember.isEmpty('');              // true
              Ember.isEmpty([]);              // true
              Ember.isEmpty('Adam Hawkins');  // false
              Ember.isEmpty([0,1,2]);         // false
              ```

              @method isEmpty
              @for Ember
              @param {Object} obj Value to test
              @return {Boolean}
            */
        function isEmpty(obj) {
            return isNone(obj) || (obj.length === 0 && typeof obj !== 'function') || (typeof obj === 'object' && get(obj, 'length') === 0);
        }

        var empty = Ember.deprecateFunc("Ember.empty is deprecated. Please use Ember.isEmpty instead.", isEmpty);
        __exports__.empty = empty;
        __exports__["default"] = isEmpty;
        __exports__.isEmpty = isEmpty;
        __exports__.empty = empty;
    });
    define("ember-metal/is_none",
    ["ember-metal/core", "exports"],
    function(__dependency1__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // deprecateFunc

        /**
              Returns true if the passed value is null or undefined. This avoids errors
              from JSLint complaining about use of ==, which can be technically
              confusing.

              ```javascript
              Ember.isNone();              // true
              Ember.isNone(null);          // true
              Ember.isNone(undefined);     // true
              Ember.isNone('');            // false
              Ember.isNone([]);            // false
              Ember.isNone(function() {});  // false
              ```

              @method isNone
              @for Ember
              @param {Object} obj Value to test
              @return {Boolean}
            */
        function isNone(obj) {
            return obj === null || obj === undefined;
        }

        var none = Ember.deprecateFunc("Ember.none is deprecated. Please use Ember.isNone instead.", isNone);
        __exports__.none = none;
        __exports__["default"] = isNone;
        __exports__.isNone = isNone;
    });
    define("ember-metal/libraries",
    ["ember-metal/enumerable_utils", "exports"],
    function(__dependency1__, __exports__) {
        "use strict";
        // Provides a way to register library versions with ember.
        var forEach = __dependency1__.forEach;
        var indexOf = __dependency1__.indexOf;

        var libraries = function() {
            var _libraries = [];
            var coreLibIndex = 0;

            var getLibrary = function(name) {
                for (var i = 0; i < _libraries.length; i++) {
                    if (_libraries[i].name === name) {
                        return _libraries[i];
                    }
                }
            };

            _libraries.register = function(name, version) {
                if (!getLibrary(name)) {
                    _libraries.push({
                        name: name,
                        version: version
                    });
                }
            };

            _libraries.registerCoreLibrary = function(name, version) {
                if (!getLibrary(name)) {
                    _libraries.splice(coreLibIndex++, 0, {
                        name: name,
                        version: version
                    });
                }
            };

            _libraries.deRegister = function(name) {
                var lib = getLibrary(name);
                if (lib) 
                    _libraries.splice(indexOf(_libraries, lib), 1);
            };

            _libraries.each = function (callback) {
                forEach(_libraries, function(lib) {
                    callback(lib.name, lib.version);
                });
            };

            return _libraries;
        }();

        __exports__["default"] = libraries;
    });
    define("ember-metal/logger",
    ["ember-metal/core", "ember-metal/error", "exports"],
    function(__dependency1__, __dependency2__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        var EmberError = __dependency2__["default"];

        function consoleMethod(name) {
            var consoleObj, logToConsole;
            if (Ember.imports.console) {
                consoleObj = Ember.imports.console;
            } else if (typeof console !== 'undefined') {
                consoleObj = console;
            }

            var method = typeof consoleObj === 'object' ? consoleObj[name] : null;

            if (method) {
                // Older IE doesn't support apply, but Chrome needs it
                if (typeof method.apply === 'function') {
                    logToConsole = function() {
                        method.apply(consoleObj, arguments);
                    };
                    logToConsole.displayName = 'console.' + name;
                    return logToConsole;
                } else {
                    return function() {
                        var message = Array.prototype.join.call(arguments, ', ');
                        method(message);
                    };
                }
            }
        }

        function assertPolyfill(test, message) {
            if (!test) {
                try {
                    // attempt to preserve the stack
                    throw new EmberError("assertion failed: " + message);
                } catch (error) {
                    setTimeout(function() {
                        throw error;
                    }, 0);
                }
            }
        }

        /**
              Inside Ember-Metal, simply uses the methods from `imports.console`.
              Override this to provide more robust logging functionality.

              @class Logger
              @namespace Ember
            */
        __exports__["default"] = {
            /**
                   Logs the arguments to the console.
                   You can pass as many arguments as you want and they will be joined together with a space.

                    ```javascript
                    var foo = 1;
                    Ember.Logger.log('log value of foo:', foo);
                    // "log value of foo: 1" will be printed to the console
                    ```

                   @method log
                   @for Ember.Logger
                   @param {*} arguments
                  */
            log: consoleMethod('log') || Ember.K,

            /**
                   Prints the arguments to the console with a warning icon.
                   You can pass as many arguments as you want and they will be joined together with a space.

                    ```javascript
                    Ember.Logger.warn('Something happened!');
                    // "Something happened!" will be printed to the console with a warning icon.
                    ```

                   @method warn
                   @for Ember.Logger
                   @param {*} arguments
                  */
            warn: consoleMethod('warn') || Ember.K,

            /**
                   Prints the arguments to the console with an error icon, red text and a stack trace.
                   You can pass as many arguments as you want and they will be joined together with a space.

                    ```javascript
                    Ember.Logger.error('Danger! Danger!');
                    // "Danger! Danger!" will be printed to the console in red text.
                    ```

                   @method error
                   @for Ember.Logger
                   @param {*} arguments
                  */
            error: consoleMethod('error') || Ember.K,

            /**
                   Logs the arguments to the console.
                   You can pass as many arguments as you want and they will be joined together with a space.

                    ```javascript
                    var foo = 1;
                    Ember.Logger.info('log value of foo:', foo);
                    // "log value of foo: 1" will be printed to the console
                    ```

                   @method info
                   @for Ember.Logger
                   @param {*} arguments
                  */
            info: consoleMethod('info') || Ember.K,

            /**
                   Logs the arguments to the console in blue text.
                   You can pass as many arguments as you want and they will be joined together with a space.

                    ```javascript
                    var foo = 1;
                    Ember.Logger.debug('log value of foo:', foo);
                    // "log value of foo: 1" will be printed to the console
                    ```

                   @method debug
                   @for Ember.Logger
                   @param {*} arguments
                  */
            debug: consoleMethod('debug') || consoleMethod('info') || Ember.K,

            /**
                   If the value passed into `Ember.Logger.assert` is not truthy it will throw an error with a stack trace.

                    ```javascript
                    Ember.Logger.assert(true); // undefined
                    Ember.Logger.assert(true === false); // Throws an Assertion failed error.
                    ```

                   @method assert
                   @for Ember.Logger
                   @param {Boolean} bool Value to test
                  */
            assert: consoleMethod('assert') || assertPolyfill
        };
    });
    define("ember-metal/map",
    ["ember-metal/property_set", "ember-metal/utils", "ember-metal/array", "ember-metal/platform", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
        "use strict";
        /**
            @module ember-metal
            */

        /*
              JavaScript (before ES6) does not have a Map implementation. Objects,
              which are often used as dictionaries, may only have Strings as keys.

              Because Ember has a way to get a unique identifier for every object
              via `Ember.guidFor`, we can implement a performant Map with arbitrary
              keys. Because it is commonly used in low-level bookkeeping, Map is
              implemented as a pure JavaScript object for performance.

              This implementation follows the current iteration of the ES6 proposal for
              maps (http://wiki.ecmascript.org/doku.php?id=harmony:simple_maps_and_sets),
              with two exceptions. First, because we need our implementation to be pleasant
              on older browsers, we do not use the `delete` name (using `remove` instead).
              Second, as we do not have the luxury of in-VM iteration, we implement a
              forEach method for iteration.

              Map is mocked out to look like an Ember object, so you can do
              `Ember.Map.create()` for symmetry with other Ember classes.
            */

        var set = __dependency1__.set;
        var guidFor = __dependency2__.guidFor;
        var indexOf = __dependency3__.indexOf;
        var create = __dependency4__.create;

        function copy(obj) {
            var output = {};

            for (var prop in obj) {
                if (obj.hasOwnProperty(prop)) {
                    output[prop] = obj[prop];
                }
            }

            return output;
        }

        function copyMap(original, newObject) {
            var keys = original.keys.copy(),
            values = copy(original.values);

            newObject.keys = keys;
            newObject.values = values;
            newObject.length = original.length;

            return newObject;
        }

        /**
              This class is used internally by Ember and Ember Data.
              Please do not use it at this time. We plan to clean it up
              and add many tests soon.

              @class OrderedSet
              @namespace Ember
              @constructor
              @private
            */
        function OrderedSet() {
            this.clear();
        }

        /**
              @method create
              @static
              @return {Ember.OrderedSet}
            */
        OrderedSet.create = function() {
            return new OrderedSet();
        };


        OrderedSet.prototype = {
            /**
                    @method clear
                  */
            clear: function() {
                this.presenceSet = {};
                this.list = [];
            },

            /**
                    @method add
                    @param obj
                  */
            add: function(obj) {
                var guid = guidFor(obj),
                presenceSet = this.presenceSet,
                list = this.list;

                if (guid in presenceSet) {
                    return;
                }

                presenceSet[guid] = true;
                list.push(obj);
            },

            /**
                    @method remove
                    @param obj
                  */
            remove: function(obj) {
                var guid = guidFor(obj),
                presenceSet = this.presenceSet,
                list = this.list;

                delete presenceSet[guid];

                var index = indexOf.call(list, obj);
                if (index > -1) {
                    list.splice(index, 1);
                }
            },

            /**
                    @method isEmpty
                    @return {Boolean}
                  */
            isEmpty: function() {
                return this.list.length === 0;
            },

            /**
                    @method has
                    @param obj
                    @return {Boolean}
                  */
            has: function(obj) {
                var guid = guidFor(obj),
                presenceSet = this.presenceSet;

                return guid in presenceSet;
            },

            /**
                    @method forEach
                    @param {Function} fn
                    @param self
                  */
            forEach: function(fn, self) {
                // allow mutation during iteration
                var list = this.toArray();

                for (var i = 0, j = list.length; i < j; i++) {
                    fn.call(self, list[i]);
                }
            },

            /**
                    @method toArray
                    @return {Array}
                  */
            toArray: function() {
                return this.list.slice();
            },

            /**
                    @method copy
                    @return {Ember.OrderedSet}
                  */
            copy: function() {
                var set = new OrderedSet();

                set.presenceSet = copy(this.presenceSet);
                set.list = this.toArray();

                return set;
            }
        };

        /**
              A Map stores values indexed by keys. Unlike JavaScript's
              default Objects, the keys of a Map can be any JavaScript
              object.

              Internally, a Map has two data structures:

              1. `keys`: an OrderedSet of all of the existing keys
              2. `values`: a JavaScript Object indexed by the `Ember.guidFor(key)`

              When a key/value pair is added for the first time, we
              add the key to the `keys` OrderedSet, and create or
              replace an entry in `values`. When an entry is deleted,
              we delete its entry in `keys` and `values`.

              @class Map
              @namespace Ember
              @private
              @constructor
            */
        function Map() {
            this.keys = OrderedSet.create();
            this.values = {};
        }

        Ember.Map = Map;

        /**
              @method create
              @static
            */
        Map.create = function() {
            return new Map();
        };

        Map.prototype = {
            /**
                    This property will change as the number of objects in the map changes.

                    @property length
                    @type number
                    @default 0
                  */
            length: 0,

            /**
                    Retrieve the value associated with a given key.

                    @method get
                    @param {*} key
                    @return {*} the value associated with the key, or `undefined`
                  */
            get: function(key) {
                var values = this.values,
                guid = guidFor(key);

                return values[guid];
            },

            /**
                    Adds a value to the map. If a value for the given key has already been
                    provided, the new value will replace the old value.

                    @method set
                    @param {*} key
                    @param {*} value
                  */
            set: function(key, value) {
                var keys = this.keys,
                values = this.values,
                guid = guidFor(key);

                keys.add(key);
                values[guid] = value;
                set(this, 'length', keys.list.length);
            },

            /**
                    Removes a value from the map for an associated key.

                    @method remove
                    @param {*} key
                    @return {Boolean} true if an item was removed, false otherwise
                  */
            remove: function(key) {
                // don't use ES6 "delete" because it will be annoying
                // to use in browsers that are not ES6 friendly;
                var keys = this.keys,
                values = this.values,
                guid = guidFor(key);

                if (values.hasOwnProperty(guid)) {
                    keys.remove(key);
                    delete values[guid];
                    set(this, 'length', keys.list.length);
                    return true;
                } else {
                    return false;
                }
            },

            /**
                    Check whether a key is present.

                    @method has
                    @param {*} key
                    @return {Boolean} true if the item was present, false otherwise
                  */
            has: function(key) {
                var values = this.values,
                guid = guidFor(key);

                return values.hasOwnProperty(guid);
            },

            /**
                    Iterate over all the keys and values. Calls the function once
                    for each key, passing in the key and value, in that order.

                    The keys are guaranteed to be iterated over in insertion order.

                    @method forEach
                    @param {Function} callback
                    @param {*} self if passed, the `this` value inside the
                      callback. By default, `this` is the map.
                  */
            forEach: function(callback, self) {
                var keys = this.keys,
                values = this.values;

                keys.forEach(function(key) {
                    var guid = guidFor(key);
                    callback.call(self, key, values[guid]);
                });
            },

            /**
                    @method copy
                    @return {Ember.Map}
                  */
            copy: function() {
                return copyMap(this, new Map());
            }
        };

        /**
              @class MapWithDefault
              @namespace Ember
              @extends Ember.Map
              @private
              @constructor
              @param [options]
                @param {*} [options.defaultValue]
            */
        function MapWithDefault(options) {
            Map.call(this);
            this.defaultValue = options.defaultValue;
        }

        /**
              @method create
              @static
              @param [options]
                @param {*} [options.defaultValue]
              @return {Ember.MapWithDefault|Ember.Map} If options are passed, returns
                `Ember.MapWithDefault` otherwise returns `Ember.Map`
            */
        MapWithDefault.create = function(options) {
            if (options) {
                return new MapWithDefault(options);
            } else {
                return new Map();
            }
        };

        MapWithDefault.prototype = create(Map.prototype);

        /**
              Retrieve the value associated with a given key.

              @method get
              @param {*} key
              @return {*} the value associated with the key, or the default value
            */
        MapWithDefault.prototype.get = function(key) {
            var hasValue = this.has(key);

            if (hasValue) {
                return Map.prototype.get.call(this, key);
            } else {
                var defaultValue = this.defaultValue(key);
                this.set(key, defaultValue);
                return defaultValue;
            }
        };

        /**
              @method copy
              @return {Ember.MapWithDefault}
            */
        MapWithDefault.prototype.copy = function() {
            return copyMap(this, new MapWithDefault({
                defaultValue: this.defaultValue
            }));
        };

        __exports__.OrderedSet = OrderedSet;
        __exports__.Map = Map;
        __exports__.MapWithDefault = MapWithDefault;
    });
    define("ember-metal/merge",
    ["exports"],
    function(__exports__) {
        "use strict";
        /**
              Merge the contents of two objects together into the first object.

              ```javascript
              Ember.merge({first: 'Tom'}, {last: 'Dale'}); // {first: 'Tom', last: 'Dale'}
              var a = {first: 'Yehuda'}, b = {last: 'Katz'};
              Ember.merge(a, b); // a == {first: 'Yehuda', last: 'Katz'}, b == {last: 'Katz'}
              ```

              @method merge
              @for Ember
              @param {Object} original The object to merge into
              @param {Object} updates The object to copy properties from
              @return {Object}
            */
        __exports__["default"] = function merge(original, updates) {
            for (var prop in updates) {
                if (!updates.hasOwnProperty(prop)) {
                    continue;
                }
                original[prop] = updates[prop];
            }
            return original;
        }
    });
    define("ember-metal/mixin",
    ["ember-metal/core", "ember-metal/merge", "ember-metal/array", "ember-metal/platform", "ember-metal/utils", "ember-metal/expand_properties", "ember-metal/properties", "ember-metal/computed", "ember-metal/binding", "ember-metal/observer", "ember-metal/events", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-metal
            */

        var Ember = __dependency1__["default"];
        // warn, assert, wrap, et;
        var merge = __dependency2__["default"];
        var map = __dependency3__.map;
        var indexOf = __dependency3__.indexOf;
        var forEach = __dependency3__.forEach;
        var create = __dependency4__.create;
        var guidFor = __dependency5__.guidFor;
        var meta = __dependency5__.meta;
        var META_KEY = __dependency5__.META_KEY;
        var wrap = __dependency5__.wrap;
        var makeArray = __dependency5__.makeArray;
        var apply = __dependency5__.apply;
        var expandProperties = __dependency6__["default"];
        var Descriptor = __dependency7__.Descriptor;
        var defineProperty = __dependency7__.defineProperty;
        var ComputedProperty = __dependency8__.ComputedProperty;
        var Binding = __dependency9__.Binding;
        var addObserver = __dependency10__.addObserver;
        var removeObserver = __dependency10__.removeObserver;
        var addBeforeObserver = __dependency10__.addBeforeObserver;
        var removeBeforeObserver = __dependency10__.removeBeforeObserver;
        var addListener = __dependency11__.addListener;
        var removeListener = __dependency11__.removeListener;

        var REQUIRED,
        a_map = map,
        a_indexOf = indexOf,
        a_forEach = forEach,
        a_slice = [].slice,
        o_create = create,
        metaFor = meta;

        function superFunction() {
            var ret, func = this.__nextSuper;
            if (func) {
                this.__nextSuper = null;
                ret = apply(this, func, arguments);
                this.__nextSuper = func;
            }
            return ret;
        }

        function mixinsMeta(obj) {
            var m = metaFor(obj, true), ret = m.mixins;
            if (!ret) {
                ret = m.mixins = {};
            } else if (!m.hasOwnProperty('mixins')) {
                ret = m.mixins = o_create(ret);
            }
            return ret;
        }

        function initMixin(mixin, args) {
            if (args && args.length > 0) {
                mixin.mixins = a_map.call(args, function(x) {
                    if (x instanceof Mixin) {
                        return x;
                    }

                    // Note: Manually setup a primitive mixin here. This is the only
                    // way to actually get a primitive mixin. This way normal creation
                    // of mixins will give you combined mixins...
                    var mixin = new Mixin();
                    mixin.properties = x;
                    return mixin;
                });
            }
            return mixin;
        }

        function isMethod(obj) {
            return 'function' === typeof obj &&
            obj.isMethod !== false &&
            obj !== Boolean && obj !== Object && obj !== Number && obj !== Array && obj !== Date && obj !== String;
        }

        var CONTINUE = {};

        function mixinProperties(mixinsMeta, mixin) {
            var guid;

            if (mixin instanceof Mixin) {
                guid = guidFor(mixin);
                if (mixinsMeta[guid]) {
                    return CONTINUE;
                }
                mixinsMeta[guid] = mixin;
                return mixin.properties;
            } else {
                return mixin; // apply anonymous mixin properties
            }
        }

        function concatenatedMixinProperties(concatProp, props, values, base) {
            var concats;

            // reset before adding each new mixin to pickup concats from previous
            concats = values[concatProp] || base[concatProp];
            if (props[concatProp]) {
                concats = concats ? concats.concat(props[concatProp]) : props[concatProp];
            }

            return concats;
        }

        function giveDescriptorSuper(meta, key, property, values, descs) {
            var superProperty;

            // Computed properties override methods, and do not call super to them
            if (values[key] === undefined) {
                // Find the original descriptor in a parent mixin
                superProperty = descs[key];
            }

            // If we didn't find the original descriptor in a parent mixin, find
            // it on the original object.
            superProperty = superProperty || meta.descs[key];

            if (!superProperty || !(superProperty instanceof ComputedProperty)) {
                return property;
            }

            // Since multiple mixins may inherit from the same parent, we need
            // to clone the computed property so that other mixins do not receive
            // the wrapped version.
            property = o_create(property);
            property.func = wrap(property.func, superProperty.func);

            return property;
        }

        function giveMethodSuper(obj, key, method, values, descs) {
            var superMethod;

            // Methods overwrite computed properties, and do not call super to them.
            if (descs[key] === undefined) {
                // Find the original method in a parent mixin
                superMethod = values[key];
            }

            // If we didn't find the original value in a parent mixin, find it in
            // the original object
            superMethod = superMethod || obj[key];

            // Only wrap the new method if the original method was a function
            if ('function' !== typeof superMethod) {
                return method;
            }

            return wrap(method, superMethod);
        }

        function applyConcatenatedProperties(obj, key, value, values) {
            var baseValue = values[key] || obj[key];

            if (baseValue) {
                if ('function' === typeof baseValue.concat) {
                    return baseValue.concat(value);
                } else {
                    return makeArray(baseValue).concat(value);
                }
            } else {
                return makeArray(value);
            }
        }

        function applyMergedProperties(obj, key, value, values) {
            var baseValue = values[key] || obj[key];

            if (!baseValue) {
                return value;
            }

            var newBase = merge({}, baseValue),
            hasFunction = false;

            for (var prop in value) {
                if (!value.hasOwnProperty(prop)) {
                    continue;
                }

                var propValue = value[prop];
                if (isMethod(propValue)) {
                    // TODO: support for Computed Properties, etc?
                    hasFunction = true;
                    newBase[prop] = giveMethodSuper(obj, prop, propValue, baseValue, {});
                } else {
                    newBase[prop] = propValue;
                }
            }

            if (hasFunction) {
                newBase._super = superFunction;
            }

            return newBase;
        }

        function addNormalizedProperty(base, key, value, meta, descs, values, concats, mergings) {
            if (value instanceof Descriptor) {
                if (value === REQUIRED && descs[key]) {
                    return CONTINUE;
                }

                // Wrap descriptor function to implement
                // __nextSuper() if needed
                if (value.func) {
                    value = giveDescriptorSuper(meta, key, value, values, descs);
                }

                descs[key] = value;
                values[key] = undefined;
            } else {
                if ((concats && a_indexOf.call(concats, key) >= 0) ||
                key === 'concatenatedProperties' ||
                key === 'mergedProperties') {
                    value = applyConcatenatedProperties(base, key, value, values);
                } else if ((mergings && a_indexOf.call(mergings, key) >= 0)) {
                    value = applyMergedProperties(base, key, value, values);
                } else if (isMethod(value)) {
                    value = giveMethodSuper(base, key, value, values, descs);
                }

                descs[key] = undefined;
                values[key] = value;
            }
        }

        function mergeMixins(mixins, m, descs, values, base, keys) {
            var mixin, props, key, concats, mergings, meta;

            function removeKeys(keyName) {
                delete descs[keyName];
                delete values[keyName];
            }

            for (var i = 0, l = mixins.length; i < l; i++) {
                mixin = mixins[i];
                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]');

                props = mixinProperties(m, mixin);
                if (props === CONTINUE) {
                    continue;
                }

                if (props) {
                    meta = metaFor(base);
                    if (base.willMergeMixin) {
                        base.willMergeMixin(props);
                    }
                    concats = concatenatedMixinProperties('concatenatedProperties', props, values, base);
                    mergings = concatenatedMixinProperties('mergedProperties', props, values, base);

                    for (key in props) {
                        if (!props.hasOwnProperty(key)) {
                            continue;
                        }
                        keys.push(key);
                        addNormalizedProperty(base, key, props[key], meta, descs, values, concats, mergings);
                    }

                    // manually copy toString() because some JS engines do not enumerate it
                    if (props.hasOwnProperty('toString')) {
                        base.toString = props.toString;
                    }
                } else if (mixin.mixins) {
                    mergeMixins(mixin.mixins, m, descs, values, base, keys);
                    if (mixin._without) {
                        a_forEach.call(mixin._without, removeKeys);
                    }
                }
            }
        }

        var IS_BINDING = /^.+Binding$/;

        function detectBinding(obj, key, value, m) {
            if (IS_BINDING.test(key)) {
                var bindings = m.bindings;
                if (!bindings) {
                    bindings = m.bindings = {};
                } else if (!m.hasOwnProperty('bindings')) {
                    bindings = m.bindings = o_create(m.bindings);
                }
                bindings[key] = value;
            }
        }

        function connectBindings(obj, m) {
            // TODO Mixin.apply(instance) should disconnect binding if exists
            var bindings = m.bindings, key, binding, to;
            if (bindings) {
                for (key in bindings) {
                    binding = bindings[key];
                    if (binding) {
                        to = key.slice(0, -7); // strip Binding off end
                        if (binding instanceof Binding) {
                            binding = binding.copy(); // copy prototypes' instance
                            binding.to(to);
                        } else {
                            // binding is string path
                            binding = new Binding(to, binding);
                        }
                        binding.connect(obj);
                        obj[key] = binding;
                    }
                }
                // mark as applied
                m.bindings = {};
            }
        }

        function finishPartial(obj, m) {
            connectBindings(obj, m || metaFor(obj));
            return obj;
        }

        function followAlias(obj, desc, m, descs, values) {
            var altKey = desc.methodName, value;
            if (descs[altKey] || values[altKey]) {
                value = values[altKey];
                desc = descs[altKey];
            } else if (m.descs[altKey]) {
                desc = m.descs[altKey];
                value = undefined;
            } else {
                desc = undefined;
                value = obj[altKey];
            }

            return {
                desc: desc,
                value: value 
            };
        }

        function updateObserversAndListeners(obj, key, observerOrListener, pathsKey, updateMethod) {
            var paths = observerOrListener[pathsKey];

            if (paths) {
                for (var i = 0, l = paths.length; i < l; i++) {
                    updateMethod(obj, paths[i], null, key);
                }
            }
        }

        function replaceObserversAndListeners(obj, key, observerOrListener) {
            var prev = obj[key];

            if ('function' === typeof prev) {
                updateObserversAndListeners(obj, key, prev, '__ember_observesBefore__', removeBeforeObserver);
                updateObserversAndListeners(obj, key, prev, '__ember_observes__', removeObserver);
                updateObserversAndListeners(obj, key, prev, '__ember_listens__', removeListener);
            }

            if ('function' === typeof observerOrListener) {
                updateObserversAndListeners(obj, key, observerOrListener, '__ember_observesBefore__', addBeforeObserver);
                updateObserversAndListeners(obj, key, observerOrListener, '__ember_observes__', addObserver);
                updateObserversAndListeners(obj, key, observerOrListener, '__ember_listens__', addListener);
            }
        }

        function applyMixin(obj, mixins, partial) {
            var descs = {}, values = {}, m = metaFor(obj),
            key, value, desc, keys = [];

            obj._super = superFunction;

            // Go through all mixins and hashes passed in, and:
            //
            // * Handle concatenated properties
            // * Handle merged properties
            // * Set up _super wrapping if necessary
            // * Set up computed property descriptors
            // * Copying `toString` in broken browsers
            mergeMixins(mixins, mixinsMeta(obj), descs, values, obj, keys);

            for (var i = 0, l = keys.length; i < l; i++) {
                key = keys[i];
                if (key === 'constructor' || !values.hasOwnProperty(key)) {
                    continue;
                }

                desc = descs[key];
                value = values[key];

                if (desc === REQUIRED) {
                    continue;
                }

                while (desc && desc instanceof Alias) {
                    var followed = followAlias(obj, desc, m, descs, values);
                    desc = followed.desc;
                    value = followed.value;
                }

                if (desc === undefined && value === undefined) {
                    continue;
                }

                replaceObserversAndListeners(obj, key, value);
                detectBinding(obj, key, value, m);
                defineProperty(obj, key, desc, value, m);
            }

            if (!partial) {
                // don't apply to prototype
                finishPartial(obj, m);
            }

            return obj;
        }

        /**
              @method mixin
              @for Ember
              @param obj
              @param mixins*
              @return obj
            */
        function mixin(obj) {
            var args = a_slice.call(arguments, 1);
            applyMixin(obj, args, false);
            return obj;
        }

        __exports__.mixin = mixin; /**
              The `Ember.Mixin` class allows you to create mixins, whose properties can be
              added to other classes. For instance,

              ```javascript
              App.Editable = Ember.Mixin.create({
                edit: function() {
                  console.log('starting to edit');
                  this.set('isEditing', true);
                },
                isEditing: false
              });

              // Mix mixins into classes by passing them as the first arguments to
              // .extend.
              App.CommentView = Ember.View.extend(App.Editable, {
                template: Ember.Handlebars.compile('{{#if view.isEditing}}...{{else}}...{{/if}}')
              });

              commentView = App.CommentView.create();
              commentView.edit(); // outputs 'starting to edit'
              ```

              Note that Mixins are created with `Ember.Mixin.create`, not
              `Ember.Mixin.extend`.

              Note that mixins extend a constructor's prototype so arrays and object literals
              defined as properties will be shared amongst objects that implement the mixin.
              If you want to define a property in a mixin that is not shared, you can define
              it either as a computed property or have it be created on initialization of the object.

              ```javascript
              //filters array will be shared amongst any object implementing mixin
              App.Filterable = Ember.Mixin.create({
                filters: Ember.A()
              });

              //filters will be a separate  array for every object implementing the mixin
              App.Filterable = Ember.Mixin.create({
                filters: Ember.computed(function(){return Ember.A();})
              });

              //filters will be created as a separate array during the object's initialization
              App.Filterable = Ember.Mixin.create({
                init: function() {
                  this._super();
                  this.set("filters", Ember.A());
                }
              });
              ```

              @class Mixin
              @namespace Ember
            */
        __exports__["default"] = Mixin;
        function Mixin() {
            return initMixin(this, arguments);
        }
        Mixin.prototype = {
            properties: null,
            mixins: null,
            ownerConstructor: null
        };

        Mixin._apply = applyMixin;

        Mixin.applyPartial = function(obj) {
            var args = a_slice.call(arguments, 1);
            return applyMixin(obj, args, true);
        };

        Mixin.finishPartial = finishPartial;

        // ES6TODO: this relies on a global state?
        Ember.anyUnprocessedMixins = false;

        /**
              @method create
              @static
              @param arguments*
            */
        Mixin.create = function() {
            // ES6TODO: this relies on a global state?
            Ember.anyUnprocessedMixins = true;
            var M = this;
            return initMixin(new M(), arguments);
        };

        var MixinPrototype = Mixin.prototype;

        /**
              @method reopen
              @param arguments*
            */
        MixinPrototype.reopen = function() {
            var mixin, tmp;

            if (this.properties) {
                mixin = Mixin.create();
                mixin.properties = this.properties;
                delete this.properties;
                this.mixins = [mixin];
            } else if (!this.mixins) {
                this.mixins = [];
            }

            var len = arguments.length, mixins = this.mixins, idx;

            for (idx = 0; idx < len; idx++) {
                mixin = arguments[idx];
                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]');

                if (mixin instanceof Mixin) {
                    mixins.push(mixin);
                } else {
                    tmp = Mixin.create();
                    tmp.properties = mixin;
                    mixins.push(tmp);
                }
            }

            return this;
        };

        /**
              @method apply
              @param obj
              @return applied object
            */
        MixinPrototype.apply = function(obj) {
            return applyMixin(obj, [this], false);
        };

        MixinPrototype.applyPartial = function(obj) {
            return applyMixin(obj, [this], true);
        };

        function _detect(curMixin, targetMixin, seen) {
            var guid = guidFor(curMixin);

            if (seen[guid]) {
                return false;
            }
            seen[guid] = true;

            if (curMixin === targetMixin) {
                return true;
            }
            var mixins = curMixin.mixins, loc = mixins ? mixins.length : 0;
            while (--loc >= 0) {
                if (_detect(mixins[loc], targetMixin, seen)) {
                    return true;
                }
            }
            return false;
        }

        /**
              @method detect
              @param obj
              @return {Boolean}
            */
        MixinPrototype.detect = function(obj) {
            if (!obj) {
                return false;
            }
            if (obj instanceof Mixin) {
                return _detect(obj, this, {});
            }
            var m = obj[META_KEY],
            mixins = m && m.mixins;
            if (mixins) {
                return !!mixins[guidFor(this)];
            }
            return false;
        };

        MixinPrototype.without = function() {
            var ret = new Mixin(this);
            ret._without = a_slice.call(arguments);
            return ret;
        };

        function _keys(ret, mixin, seen) {
            if (seen[guidFor(mixin)]) {
                return;
            }
            seen[guidFor(mixin)] = true;

            if (mixin.properties) {
                var props = mixin.properties;
                for (var key in props) {
                    if (props.hasOwnProperty(key)) {
                        ret[key] = true;
                    }
                }
            } else if (mixin.mixins) {
                a_forEach.call(mixin.mixins, function(x) {
                    _keys(ret, x, seen);
                });
            }
        }

        MixinPrototype.keys = function() {
            var keys = {}, seen = {}, ret = [];
            _keys(keys, this, seen);
            for (var key in keys) {
                if (keys.hasOwnProperty(key)) {
                    ret.push(key);
                }
            }
            return ret;
        };

        // returns the mixins currently applied to the specified object
        // TODO: Make Ember.mixin
        Mixin.mixins = function(obj) {
            var m = obj[META_KEY],
            mixins = m && m.mixins, ret = [];

            if (!mixins) {
                return ret;
            }

            for (var key in mixins) {
                var mixin = mixins[key];

                // skip primitive mixins since these are always anonymous
                if (!mixin.properties) {
                    ret.push(mixin);
                }
            }

            return ret;
        };

        REQUIRED = new Descriptor();
        REQUIRED.toString = function() {
            return '(Required Property)';
        };

        /**
              Denotes a required property for a mixin

              @method required
              @for Ember
            */
        function required() {
            return REQUIRED;
        }

        __exports__.required = required;
        function Alias(methodName) {
            this.methodName = methodName;
        }

        Alias.prototype = new Descriptor();

        /**
              Makes a method available via an additional name.

              ```javascript
              App.Person = Ember.Object.extend({
                name: function() {
                  return 'Tomhuda Katzdale';
                },
                moniker: Ember.aliasMethod('name')
              });

              var goodGuy = App.Person.create();
              
              goodGuy.name();    // 'Tomhuda Katzdale'
              goodGuy.moniker(); // 'Tomhuda Katzdale'
              ```

              @method aliasMethod
              @for Ember
              @param {String} methodName name of the method to alias
              @return {Ember.Descriptor}
            */
        function aliasMethod(methodName) {
            return new Alias(methodName);
        }

        __exports__.aliasMethod = aliasMethod; // ..........................................................
        // OBSERVER HELPER
        //

        /**
              Specify a method that observes property changes.

              ```javascript
              Ember.Object.extend({
                valueObserver: Ember.observer('value', function() {
                  // Executes whenever the "value" property changes
                })
              });
              ```

              In the future this method may become asynchronous. If you want to ensure
              synchronous behavior, use `immediateObserver`.

              Also available as `Function.prototype.observes` if prototype extensions are
              enabled.

              @method observer
              @for Ember
              @param {String} propertyNames*
              @param {Function} func
              @return func
            */
        function observer() {
            var func = a_slice.call(arguments, -1)[0];
            var paths;

            var addWatchedProperty = function (path) {
                paths.push(path);
            };
            var _paths = a_slice.call(arguments, 0, -1);

            if (typeof func !== "function") {
                // revert to old, soft-deprecated argument ordering

                func = arguments[0];
                _paths = a_slice.call(arguments, 1);
            }

            paths = [];

            for (var i = 0; i < _paths.length; ++i) {
                expandProperties(_paths[i], addWatchedProperty);
            }

            if (typeof func !== "function") {
                throw new Ember.Error("Ember.observer called without a function");
            }

            func.__ember_observes__ = paths;
            return func;
        }

        __exports__.observer = observer; /**
              Specify a method that observes property changes.

              ```javascript
              Ember.Object.extend({
                valueObserver: Ember.immediateObserver('value', function() {
                  // Executes whenever the "value" property changes
                })
              });
              ```

              In the future, `Ember.observer` may become asynchronous. In this event,
              `Ember.immediateObserver` will maintain the synchronous behavior.

              Also available as `Function.prototype.observesImmediately` if prototype extensions are
              enabled.

              @method immediateObserver
              @for Ember
              @param {String} propertyNames*
              @param {Function} func
              @return func
            */
        function immediateObserver() {
            for (var i = 0, l = arguments.length; i < l; i++) {
                var arg = arguments[i];
                Ember.assert("Immediate observers must observe internal properties only, not properties on other objects.", typeof arg !== "string" || arg.indexOf('.') === -1);
            }

            return observer.apply(this, arguments);
        }

        __exports__.immediateObserver = immediateObserver; /**
              When observers fire, they are called with the arguments `obj`, `keyName`.

              Note, `@each.property` observer is called per each add or replace of an element
              and it's not called with a specific enumeration item.

              A `beforeObserver` fires before a property changes.

              A `beforeObserver` is an alternative form of `.observesBefore()`.

              ```javascript
              App.PersonView = Ember.View.extend({
                friends: [{ name: 'Tom' }, { name: 'Stefan' }, { name: 'Kris' }],

                valueWillChange: Ember.beforeObserver('content.value', function(obj, keyName) {
                  this.changingFrom = obj.get(keyName);
                }),

                valueDidChange: Ember.observer('content.value', function(obj, keyName) {
                    // only run if updating a value already in the DOM
                    if (this.get('state') === 'inDOM') {
                      var color = obj.get(keyName) > this.changingFrom ? 'green' : 'red';
                      // logic
                    }
                }),

                friendsDidChange: Ember.observer('friends.@each.name', function(obj, keyName) {
                  // some logic
                  // obj.get(keyName) returns friends array
                })
              });
              ```

              Also available as `Function.prototype.observesBefore` if prototype extensions are
              enabled.

              @method beforeObserver
              @for Ember
              @param {String} propertyNames*
              @param {Function} func
              @return func
            */
        function beforeObserver() {
            var func = a_slice.call(arguments, -1)[0];
            var paths;

            var addWatchedProperty = function(path) {
                paths.push(path);
            };

            var _paths = a_slice.call(arguments, 0, -1);

            if (typeof func !== "function") {
                // revert to old, soft-deprecated argument ordering

                func = arguments[0];
                _paths = a_slice.call(arguments, 1);
            }

            paths = [];

            for (var i = 0; i < _paths.length; ++i) {
                expandProperties(_paths[i], addWatchedProperty);
            }

            if (typeof func !== "function") {
                throw new Ember.Error("Ember.beforeObserver called without a function");
            }

            func.__ember_observesBefore__ = paths;
            return func;
        }

        __exports__.beforeObserver = beforeObserver;
        __exports__.IS_BINDING = IS_BINDING;
        __exports__.Mixin = Mixin;
    });
    define("ember-metal/observer",
    ["ember-metal/watching", "ember-metal/array", "ember-metal/events", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        var watch = __dependency1__.watch;
        var unwatch = __dependency1__.unwatch;
        var map = __dependency2__.map;
        var listenersFor = __dependency3__.listenersFor;
        var addListener = __dependency3__.addListener;
        var removeListener = __dependency3__.removeListener;
        var suspendListeners = __dependency3__.suspendListeners;
        var suspendListener = __dependency3__.suspendListener;
        /**
            @module ember-metal
            */

        var AFTER_OBSERVERS = ':change';
        var BEFORE_OBSERVERS = ':before';

        function changeEvent(keyName) {
            return keyName + AFTER_OBSERVERS;
        }

        function beforeEvent(keyName) {
            return keyName + BEFORE_OBSERVERS;
        }

        /**
              @method addObserver
              @for Ember
              @param obj
              @param {String} path
              @param {Object|Function} targetOrMethod
              @param {Function|String} [method]
            */
        function addObserver(obj, _path, target, method) {
            addListener(obj, changeEvent(_path), target, method);
            watch(obj, _path);

            return this;
        }

        __exports__.addObserver = addObserver;
        function observersFor(obj, path) {
            return listenersFor(obj, changeEvent(path));
        }

        __exports__.observersFor = observersFor; /**
              @method removeObserver
              @for Ember
              @param obj
              @param {String} path
              @param {Object|Function} targetOrMethod
              @param {Function|String} [method]
            */
        function removeObserver(obj, _path, target, method) {
            unwatch(obj, _path);
            removeListener(obj, changeEvent(_path), target, method);

            return this;
        }

        __exports__.removeObserver = removeObserver; /**
              @method addBeforeObserver
              @for Ember
              @param obj
              @param {String} path
              @param {Object|Function} targetOrMethod
              @param {Function|String} [method]
            */
        function addBeforeObserver(obj, _path, target, method) {
            addListener(obj, beforeEvent(_path), target, method);
            watch(obj, _path);

            return this;
        }

        __exports__.addBeforeObserver = addBeforeObserver; // Suspend observer during callback.
        //
        // This should only be used by the target of the observer
        // while it is setting the observed path.
        function _suspendBeforeObserver(obj, path, target, method, callback) {
            return suspendListener(obj, beforeEvent(path), target, method, callback);
        }

        __exports__._suspendBeforeObserver = _suspendBeforeObserver;
        function _suspendObserver(obj, path, target, method, callback) {
            return suspendListener(obj, changeEvent(path), target, method, callback);
        }

        __exports__._suspendObserver = _suspendObserver;
        function _suspendBeforeObservers(obj, paths, target, method, callback) {
            var events = map.call(paths, beforeEvent);
            return suspendListeners(obj, events, target, method, callback);
        }

        __exports__._suspendBeforeObservers = _suspendBeforeObservers;
        function _suspendObservers(obj, paths, target, method, callback) {
            var events = map.call(paths, changeEvent);
            return suspendListeners(obj, events, target, method, callback);
        }

        __exports__._suspendObservers = _suspendObservers;
        function beforeObserversFor(obj, path) {
            return listenersFor(obj, beforeEvent(path));
        }

        __exports__.beforeObserversFor = beforeObserversFor; /**
              @method removeBeforeObserver
              @for Ember
              @param obj
              @param {String} path
              @param {Object|Function} targetOrMethod
              @param {Function|String} [method]
            */
        function removeBeforeObserver(obj, _path, target, method) {
            unwatch(obj, _path);
            removeListener(obj, beforeEvent(_path), target, method);

            return this;
        }

        __exports__.removeBeforeObserver = removeBeforeObserver;
    });
    define("ember-metal/observer_set",
    ["ember-metal/utils", "ember-metal/events", "exports"],
    function(__dependency1__, __dependency2__, __exports__) {
        "use strict";
        var guidFor = __dependency1__.guidFor;
        var sendEvent = __dependency2__.sendEvent;

        /*
              this.observerSet = {
                [senderGuid]: { // variable name: `keySet`
                  [keyName]: listIndex
                }
              },
              this.observers = [
                {
                  sender: obj,
                  keyName: keyName,
                  eventName: eventName,
                  listeners: [
                    [target, method, flags]
                  ]
                },
                ...
              ]
            */
        __exports__["default"] = ObserverSet;
        function ObserverSet() {
            this.clear();
        }


        ObserverSet.prototype.add = function(sender, keyName, eventName) {
            var observerSet = this.observerSet,
            observers = this.observers,
            senderGuid = guidFor(sender),
            keySet = observerSet[senderGuid],
            index;

            if (!keySet) {
                observerSet[senderGuid] = keySet = {};
            }
            index = keySet[keyName];
            if (index === undefined) {
                index = observers.push({
                    sender: sender,
                    keyName: keyName,
                    eventName: eventName,
                    listeners: []
                }) - 1;
                keySet[keyName] = index;
            }
            return observers[index].listeners;
        };

        ObserverSet.prototype.flush = function() {
            var observers = this.observers, i, len, observer, sender;
            this.clear();
            for (i = 0, len = observers.length; i < len; ++i) {
                observer = observers[i];
                sender = observer.sender;
                if (sender.isDestroying || sender.isDestroyed) {
                    continue;
                }
                sendEvent(sender, observer.eventName, [sender, observer.keyName], observer.listeners);
            }
        };

        ObserverSet.prototype.clear = function() {
            this.observerSet = {};
            this.observers = [];
        };
    });
    define("ember-metal/platform",
    ["ember-metal/core", "exports"],
    function(__dependency1__, __exports__) {
        "use strict";
        /*globals Node */

        var Ember = __dependency1__["default"];

        /**
            @module ember-metal
            */

        /**
              Platform specific methods and feature detectors needed by the framework.

              @class platform
              @namespace Ember
              @static
            */
        // TODO remove this
        var platform = {};

        /**
              Identical to `Object.create()`. Implements if not available natively.

              @method create
              @for Ember
            */
        var create = Object.create;

        // IE8 has Object.create but it couldn't treat property descriptors.
        if (create) {
            if (create({
                a: 1
            }, {
                a: {
                    value: 2
                }
            }).a !== 2) {
                create = null;
            }
        }

        // STUB_OBJECT_CREATE allows us to override other libraries that stub
        // Object.create different than we would prefer
        if (!create || Ember.ENV.STUB_OBJECT_CREATE) {
            var K = function() {};

            create = function(obj, props) {
                K.prototype = obj;
                obj = new K();
                if (props) {
                    K.prototype = obj;
                    for (var prop in props) {
                        K.prototype[prop] = props[prop].value;
                    }
                    obj = new K();
                }
                K.prototype = null;

                return obj;
            };

            create.isSimulated = true;
        }

        var defineProperty = Object.defineProperty;
        var canRedefineProperties, canDefinePropertyOnDOM;

        // Catch IE8 where Object.defineProperty exists but only works on DOM elements
        if (defineProperty) {
            try {
                defineProperty({}, 'a', {
                    get: function() {}
                });
            } catch (e) {
                defineProperty = null;
            }
        }

        if (defineProperty) {
            // Detects a bug in Android <3.2 where you cannot redefine a property using
            // Object.defineProperty once accessors have already been set.
            canRedefineProperties = (function() {
                var obj = {};

                defineProperty(obj, 'a', {
                    configurable: true,
                    enumerable: true,
                    get: function() {},
                    set: function() {}
                });

                defineProperty(obj, 'a', {
                    configurable: true,
                    enumerable: true,
                    writable: true,
                    value: true
                });

                return obj.a === true;
            })();

            // This is for Safari 5.0, which supports Object.defineProperty, but not
            // on DOM nodes.
            canDefinePropertyOnDOM = (function() {
                try {
                    defineProperty(document.createElement('div'), 'definePropertyOnDOM', {});
                    return true;
                } catch (e) {}

                return false;
            })();

            if (!canRedefineProperties) {
                defineProperty = null;
            } else if (!canDefinePropertyOnDOM) {
                defineProperty = function(obj, keyName, desc) {
                    var isNode;

                    if (typeof Node === "object") {
                        isNode = obj instanceof Node;
                    } else {
                        isNode = typeof obj === "object" && typeof obj.nodeType === "number" && typeof obj.nodeName === "string";
                    }

                    if (isNode) {
                        // TODO: Should we have a warning here?
                        return (obj[keyName] = desc.value);
                    } else {
                        return Object.defineProperty(obj, keyName, desc);
                    }
                };
            }
        }

        /**
            @class platform
            @namespace Ember
            */

        /**
              Identical to `Object.defineProperty()`. Implements as much functionality
              as possible if not available natively.

              @method defineProperty
              @param {Object} obj The object to modify
              @param {String} keyName property name to modify
              @param {Object} desc descriptor hash
              @return {void}
            */
        platform.defineProperty = defineProperty;

        /**
              Set to true if the platform supports native getters and setters.

              @property hasPropertyAccessors
              @final
            */
        platform.hasPropertyAccessors = true;

        if (!platform.defineProperty) {
            platform.hasPropertyAccessors = false;

            platform.defineProperty = function(obj, keyName, desc) {
                if (!desc.get) {
                    obj[keyName] = desc.value;
                }
            };

            platform.defineProperty.isSimulated = true;
        }

        if (Ember.ENV.MANDATORY_SETTER && !platform.hasPropertyAccessors) {
            Ember.ENV.MANDATORY_SETTER = false;
        }

        __exports__.create = create;
        __exports__.platform = platform;
    });
    define("ember-metal/properties",
    ["ember-metal/core", "ember-metal/utils", "ember-metal/platform", "ember-metal/property_events", "ember-metal/property_get", "ember-metal/property_set", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
        "use strict";
        /**
            @module ember-metal
            */

        var Ember = __dependency1__["default"];
        var META_KEY = __dependency2__.META_KEY;
        var meta = __dependency2__.meta;
        var platform = __dependency3__.platform;
        var overrideChains = __dependency4__.overrideChains;
        var get = __dependency5__.get;
        var set = __dependency6__.set;

        var metaFor = meta,
        objectDefineProperty = platform.defineProperty;

        var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER;

        // ..........................................................
        // DESCRIPTOR
        //

        /**
              Objects of this type can implement an interface to respond to requests to
              get and set. The default implementation handles simple properties.

              You generally won't need to create or subclass this directly.

              @class Descriptor
              @namespace Ember
              @private
              @constructor
            */
        function Descriptor() {}

        __exports__.Descriptor = Descriptor; // ..........................................................
        // DEFINING PROPERTIES API
        //

        var MANDATORY_SETTER_FUNCTION = Ember.MANDATORY_SETTER_FUNCTION = function(value) {
            Ember.assert("You must use Ember.set() to access this property (of " + this + ")", false);
        };

        var DEFAULT_GETTER_FUNCTION = Ember.DEFAULT_GETTER_FUNCTION = function DEFAULT_GETTER_FUNCTION(name) {
            return function() {
                var meta = this[META_KEY];
                return meta && meta.values[name];
            };
        };

        /**
              NOTE: This is a low-level method used by other parts of the API. You almost
              never want to call this method directly. Instead you should use
              `Ember.mixin()` to define new properties.

              Defines a property on an object. This method works much like the ES5
              `Object.defineProperty()` method except that it can also accept computed
              properties and other special descriptors.

              Normally this method takes only three parameters. However if you pass an
              instance of `Ember.Descriptor` as the third param then you can pass an
              optional value as the fourth parameter. This is often more efficient than
              creating new descriptor hashes for each property.

              ## Examples

              ```javascript
              // ES5 compatible mode
              Ember.defineProperty(contact, 'firstName', {
                writable: true,
                configurable: false,
                enumerable: true,
                value: 'Charles'
              });

              // define a simple property
              Ember.defineProperty(contact, 'lastName', undefined, 'Jolley');

              // define a computed property
              Ember.defineProperty(contact, 'fullName', Ember.computed(function() {
                return this.firstName+' '+this.lastName;
              }).property('firstName', 'lastName'));
              ```

              @private
              @method defineProperty
              @for Ember
              @param {Object} obj the object to define this property on. This may be a prototype.
              @param {String} keyName the name of the property
              @param {Ember.Descriptor} [desc] an instance of `Ember.Descriptor` (typically a
                computed property) or an ES5 descriptor.
                You must provide this or `data` but not both.
              @param {*} [data] something other than a descriptor, that will
                become the explicit value of this property.
            */
        function defineProperty(obj, keyName, desc, data, meta) {
            var descs, existingDesc, watching, value;

            if (!meta) 
                meta = metaFor(obj);
            descs = meta.descs;
            existingDesc = meta.descs[keyName];
            watching = meta.watching[keyName] > 0;

            if (existingDesc instanceof Descriptor) {
                existingDesc.teardown(obj, keyName);
            }

            if (desc instanceof Descriptor) {
                value = desc;

                descs[keyName] = desc;
                if (MANDATORY_SETTER && watching) {
                    objectDefineProperty(obj, keyName, {
                        configurable: true,
                        enumerable: true,
                        writable: true,
                        value: undefined // make enumerable
                    });
                } else {
                    obj[keyName] = undefined; // make enumerable
                }
                if (desc.setup) {
                    desc.setup(obj, keyName);
                }
            } else {
                descs[keyName] = undefined; // shadow descriptor in proto
                if (desc == null) {
                    value = data;

                    if (MANDATORY_SETTER && watching) {
                        meta.values[keyName] = data;
                        objectDefineProperty(obj, keyName, {
                            configurable: true,
                            enumerable: true,
                            set: MANDATORY_SETTER_FUNCTION,
                            get: DEFAULT_GETTER_FUNCTION(keyName)
                        });
                    } else {
                        obj[keyName] = data;
                    }
                } else {
                    value = desc;

                    // compatibility with ES5
                    objectDefineProperty(obj, keyName, desc);
                }
            }

            // if key is being watched, override chains that
            // were initialized with the prototype
            if (watching) {
                overrideChains(obj, keyName, meta);
            }

            // The `value` passed to the `didDefineProperty` hook is
            // either the descriptor or data, whichever was passed.
            if (obj.didDefineProperty) {
                obj.didDefineProperty(obj, keyName, value);
            }

            return this;
        }

        __exports__.defineProperty = defineProperty; /**
              Used internally to allow changing properties in a backwards compatible way, and print a helpful
              deprecation warning.

              @method deprecateProperty
              @param {Object} object The object to add the deprecated property to.
              @param {String} deprecatedKey The property to add (and print deprecation warnings upon accessing).
              @param {String} newKey The property that will be aliased.
              @private
            */

        function deprecateProperty(object, deprecatedKey, newKey) {
            function deprecate() {
                Ember.deprecate('Usage of `' + deprecatedKey + '` is deprecated, use `' + newKey + '` instead.');
            }

            if (platform.hasPropertyAccessors) {
                defineProperty(object, deprecatedKey, {
                    configurable: true,
                    enumerable: false,
                    set: function(value) {
                        deprecate();
                        set(object, newKey, value);
                    },
                    get: function() {
                        deprecate();
                        return get(object, newKey);
                    }
                });
            }
        }

        __exports__.deprecateProperty = deprecateProperty;
    });
    define("ember-metal/property_events",
    ["ember-metal/utils", "ember-metal/events", "ember-metal/observer_set", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        var META_KEY = __dependency1__.META_KEY;
        var guidFor = __dependency1__.guidFor;
        var tryFinally = __dependency1__.tryFinally;
        var sendEvent = __dependency2__.sendEvent;
        var listenersUnion = __dependency2__.listenersUnion;
        var listenersDiff = __dependency2__.listenersDiff;
        var ObserverSet = __dependency3__["default"];

        var beforeObserverSet = new ObserverSet();
        var observerSet = new ObserverSet();
        var deferred = 0;

        // ..........................................................
        // PROPERTY CHANGES
        //

        /**
              This function is called just before an object property is about to change.
              It will notify any before observers and prepare caches among other things.

              Normally you will not need to call this method directly but if for some
              reason you can't directly watch a property you can invoke this method
              manually along with `Ember.propertyDidChange()` which you should call just
              after the property value changes.

              @method propertyWillChange
              @for Ember
              @param {Object} obj The object with the property that will change
              @param {String} keyName The property key (or path) that will change.
              @return {void}
            */
        function propertyWillChange(obj, keyName) {
            var m = obj[META_KEY],
            watching = (m && m.watching[keyName] > 0) || keyName === 'length',
            proto = m && m.proto,
            desc = m && m.descs[keyName];

            if (!watching) {
                return;
            }
            if (proto === obj) {
                return;
            }
            if (desc && desc.willChange) {
                desc.willChange(obj, keyName);
            }
            dependentKeysWillChange(obj, keyName, m);
            chainsWillChange(obj, keyName, m);
            notifyBeforeObservers(obj, keyName);
        }

        /**
              This function is called just after an object property has changed.
              It will notify any observers and clear caches among other things.

              Normally you will not need to call this method directly but if for some
              reason you can't directly watch a property you can invoke this method
              manually along with `Ember.propertyWillChange()` which you should call just
              before the property value changes.

              @method propertyDidChange
              @for Ember
              @param {Object} obj The object with the property that will change
              @param {String} keyName The property key (or path) that will change.
              @return {void}
            */
        function propertyDidChange(obj, keyName) {
            var m = obj[META_KEY],
            watching = (m && m.watching[keyName] > 0) || keyName === 'length',
            proto = m && m.proto,
            desc = m && m.descs[keyName];

            if (proto === obj) {
                return;
            }

            // shouldn't this mean that we're watching this key?
            if (desc && desc.didChange) {
                desc.didChange(obj, keyName);
            }
            if (!watching && keyName !== 'length') {
                return;
            }

            dependentKeysDidChange(obj, keyName, m);
            chainsDidChange(obj, keyName, m, false);
            notifyObservers(obj, keyName);
        }

        var WILL_SEEN, DID_SEEN;

        // called whenever a property is about to change to clear the cache of any dependent keys (and notify those properties of changes, etc...)
        function dependentKeysWillChange(obj, depKey, meta) {
            if (obj.isDestroying) {
                return;
            }

            var seen = WILL_SEEN, top = !seen;
            if (top) {
                seen = WILL_SEEN = {};
            }
            iterDeps(propertyWillChange, obj, depKey, seen, meta);
            if (top) {
                WILL_SEEN = null;
            }
        }

        // called whenever a property has just changed to update dependent keys
        function dependentKeysDidChange(obj, depKey, meta) {
            if (obj.isDestroying) {
                return;
            }

            var seen = DID_SEEN, top = !seen;
            if (top) {
                seen = DID_SEEN = {};
            }
            iterDeps(propertyDidChange, obj, depKey, seen, meta);
            if (top) {
                DID_SEEN = null;
            }
        }

        function iterDeps(method, obj, depKey, seen, meta) {
            var guid = guidFor(obj);
            if (!seen[guid]) 
                seen[guid] = {};
            if (seen[guid][depKey]) 
                return;
            seen[guid][depKey] = true;

            var deps = meta.deps;
            deps = deps && deps[depKey];
            if (deps) {
                for (var key in deps) {
                    var desc = meta.descs[key];
                    if (desc && desc._suspended === obj) 
                        continue;
                    method(obj, key);
                }
            }
        }

        function chainsWillChange(obj, keyName, m) {
            if (!(m.hasOwnProperty('chainWatchers') &&
            m.chainWatchers[keyName])) {
                return;
            }

            var nodes = m.chainWatchers[keyName],
            events = [],
            i, l;

            for (i = 0, l = nodes.length; i < l; i++) {
                nodes[i].willChange(events);
            }

            for (i = 0, l = events.length; i < l; i += 2) {
                propertyWillChange(events[i], events[i + 1]);
            }
        }

        function chainsDidChange(obj, keyName, m, suppressEvents) {
            if (!(m && m.hasOwnProperty('chainWatchers') &&
            m.chainWatchers[keyName])) {
                return;
            }

            var nodes = m.chainWatchers[keyName],
            events = suppressEvents ? null : [],
            i, l;

            for (i = 0, l = nodes.length; i < l; i++) {
                nodes[i].didChange(events);
            }

            if (suppressEvents) {
                return;
            }

            for (i = 0, l = events.length; i < l; i += 2) {
                propertyDidChange(events[i], events[i + 1]);
            }
        }

        function overrideChains(obj, keyName, m) {
            chainsDidChange(obj, keyName, m, true);
        }

        /**
              @method beginPropertyChanges
              @chainable
              @private
            */
        function beginPropertyChanges() {
            deferred++;
        }

        /**
              @method endPropertyChanges
              @private
            */
        function endPropertyChanges() {
            deferred--;
            if (deferred <= 0) {
                beforeObserverSet.clear();
                observerSet.flush();
            }
        }

        /**
              Make a series of property changes together in an
              exception-safe way.

              ```javascript
              Ember.changeProperties(function() {
                obj1.set('foo', mayBlowUpWhenSet);
                obj2.set('bar', baz);
              });
              ```

              @method changeProperties
              @param {Function} callback
              @param [binding]
            */
        function changeProperties(cb, binding) {
            beginPropertyChanges();
            tryFinally(cb, endPropertyChanges, binding);
        }

        function notifyBeforeObservers(obj, keyName) {
            if (obj.isDestroying) {
                return;
            }

            var eventName = keyName + ':before', listeners, diff;
            if (deferred) {
                listeners = beforeObserverSet.add(obj, keyName, eventName);
                diff = listenersDiff(obj, eventName, listeners);
                sendEvent(obj, eventName, [obj, keyName], diff);
            } else {
                sendEvent(obj, eventName, [obj, keyName]);
            }
        }

        function notifyObservers(obj, keyName) {
            if (obj.isDestroying) {
                return;
            }

            var eventName = keyName + ':change', listeners;
            if (deferred) {
                listeners = observerSet.add(obj, keyName, eventName);
                listenersUnion(obj, eventName, listeners);
            } else {
                sendEvent(obj, eventName, [obj, keyName]);
            }
        }

        __exports__.propertyWillChange = propertyWillChange;
        __exports__.propertyDidChange = propertyDidChange;
        __exports__.overrideChains = overrideChains;
        __exports__.beginPropertyChanges = beginPropertyChanges;
        __exports__.endPropertyChanges = endPropertyChanges;
        __exports__.changeProperties = changeProperties;
    });
    define("ember-metal/property_get",
    ["ember-metal/core", "ember-metal/utils", "ember-metal/error", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        /**
            @module ember-metal
            */

        var Ember = __dependency1__["default"];
        var META_KEY = __dependency2__.META_KEY;
        var EmberError = __dependency3__["default"];

        var get;

        var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER;

        var IS_GLOBAL_PATH = /^([A-Z$]|([0-9][A-Z$])).*[\.]/;
        var HAS_THIS = 'this.';
        var FIRST_KEY = /^([^\.]+)/;

        // ..........................................................
        // GET AND SET
        //
        // If we are on a platform that supports accessors we can use those.
        // Otherwise simulate accessors by looking up the property directly on the
        // object.

        /**
              Gets the value of a property on an object. If the property is computed,
              the function will be invoked. If the property is not defined but the
              object implements the `unknownProperty` method then that will be invoked.

              If you plan to run on IE8 and older browsers then you should use this
              method anytime you want to retrieve a property on an object that you don't
              know for sure is private. (Properties beginning with an underscore '_'
              are considered private.)

              On all newer browsers, you only need to use this method to retrieve
              properties if the property might not be defined on the object and you want
              to respect the `unknownProperty` handler. Otherwise you can ignore this
              method.

              Note that if the object itself is `undefined`, this method will throw
              an error.

              @method get
              @for Ember
              @param {Object} obj The object to retrieve from.
              @param {String} keyName The property key to retrieve
              @return {Object} the property value or `null`.
            */
        var get = function get(obj, keyName) {
            // Helpers that operate with 'this' within an #each
            if (keyName === '') {
                return obj;
            }

            if (!keyName && 'string' === typeof obj) {
                keyName = obj;
                obj = null;
            }

            Ember.assert("Cannot call get with " + keyName + " key.", !!keyName);
            Ember.assert("Cannot call get with '" + keyName + "' on an undefined object.", obj !== undefined);

            if (obj === null) {
                return _getPath(obj, keyName);
            }

            var meta = obj[META_KEY], desc = meta && meta.descs[keyName], ret;

            if (desc === undefined && keyName.indexOf('.') !== -1) {
                return _getPath(obj, keyName);
            }

            if (desc) {
                return desc.get(obj, keyName);
            } else {
                if (MANDATORY_SETTER && meta && meta.watching[keyName] > 0) {
                    ret = meta.values[keyName];
                } else {
                    ret = obj[keyName];
                }

                if (ret === undefined &&
                'object' === typeof obj && !(keyName in obj) && 'function' === typeof obj.unknownProperty) {
                    return obj.unknownProperty(keyName);
                }

                return ret;
            }
        };

        // Currently used only by Ember Data tests
        if (Ember.config.overrideAccessors) {
            Ember.get = get;
            Ember.config.overrideAccessors();
            get = Ember.get;
        }

        /**
              Normalizes a target/path pair to reflect that actual target/path that should
              be observed, etc. This takes into account passing in global property
              paths (i.e. a path beginning with a captial letter not defined on the
              target).

              @private
              @method normalizeTuple
              @for Ember
              @param {Object} target The current target. May be `null`.
              @param {String} path A path on the target or a global property path.
              @return {Array} a temporary array with the normalized target/path pair.
            */
        function normalizeTuple(target, path) {
            var hasThis = path.indexOf(HAS_THIS) === 0,
            isGlobal = !hasThis && IS_GLOBAL_PATH.test(path),
            key;

            if (!target || isGlobal) 
                target = Ember.lookup;
            if (hasThis) 
                path = path.slice(5);

            if (target === Ember.lookup) {
                key = path.match(FIRST_KEY)[0];
                target = get(target, key);
                path = path.slice(key.length + 1);
            }

            // must return some kind of path to be valid else other things will break.
            if (!path || path.length === 0) 
                throw new EmberError('Path cannot be empty');

            return [ target, path ];
        }

        function _getPath(root, path) {
            var hasThis, parts, tuple, idx, len;

            // If there is no root and path is a key name, return that
            // property from the global object.
            // E.g. get('Ember') -> Ember
            if (root === null && path.indexOf('.') === -1) {
                return get(Ember.lookup, path);
            }

            // detect complicated paths and normalize them
            hasThis = path.indexOf(HAS_THIS) === 0;

            if (!root || hasThis) {
                tuple = normalizeTuple(root, path);
                root = tuple[0];
                path = tuple[1];
                tuple.length = 0;
            }

            parts = path.split(".");
            len = parts.length;
            for (idx = 0; root != null && idx < len; idx++) {
                root = get(root, parts[idx], true);
                if (root && root.isDestroyed) {
                    return undefined;
                }
            }
            return root;
        }

        function getWithDefault(root, key, defaultValue) {
            var value = get(root, key);

            if (value === undefined) {
                return defaultValue;
            }
            return value;
        }

        __exports__.getWithDefault = getWithDefault;
        __exports__["default"] = get;
        __exports__.get = get;
        __exports__.normalizeTuple = normalizeTuple;
        __exports__._getPath = _getPath;
    });
    define("ember-metal/property_set",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/utils", "ember-metal/property_events", "ember-metal/properties", "ember-metal/error", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        var getPath = __dependency2__._getPath;
        var META_KEY = __dependency3__.META_KEY;
        var propertyWillChange = __dependency4__.propertyWillChange;
        var propertyDidChange = __dependency4__.propertyDidChange;
        var defineProperty = __dependency5__.defineProperty;
        var EmberError = __dependency6__["default"];

        var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER;
        var IS_GLOBAL = /^([A-Z$]|([0-9][A-Z$]))/;

        /**
              Sets the value of a property on an object, respecting computed properties
              and notifying observers and other listeners of the change. If the
              property is not defined but the object implements the `setUnknownProperty`
              method then that will be invoked as well.

              @method set
              @for Ember
              @param {Object} obj The object to modify.
              @param {String} keyName The property key to set
              @param {Object} value The value to set
              @return {Object} the passed value.
            */
        var set = function set(obj, keyName, value, tolerant) {
            if (typeof obj === 'string') {
                Ember.assert("Path '" + obj + "' must be global if no obj is given.", IS_GLOBAL.test(obj));
                value = keyName;
                keyName = obj;
                obj = null;
            }

            Ember.assert("Cannot call set with " + keyName + " key.", !!keyName);

            if (!obj) {
                return setPath(obj, keyName, value, tolerant);
            }

            var meta = obj[META_KEY], desc = meta && meta.descs[keyName],
            isUnknown, currentValue;

            if (desc === undefined && keyName.indexOf('.') !== -1) {
                return setPath(obj, keyName, value, tolerant);
            }

            Ember.assert("You need to provide an object and key to `set`.", !!obj && keyName !== undefined);
            Ember.assert('calling set on destroyed object', !obj.isDestroyed);

            if (desc !== undefined) {
                desc.set(obj, keyName, value);
            } else {

                if (typeof obj === 'object' && obj !== null && value !== undefined && obj[keyName] === value) {
                    return value;
                }

                isUnknown = 'object' === typeof obj && !(keyName in obj);

                // setUnknownProperty is called if `obj` is an object,
                // the property does not already exist, and the
                // `setUnknownProperty` method exists on the object
                if (isUnknown && 'function' === typeof obj.setUnknownProperty) {
                    obj.setUnknownProperty(keyName, value);
                } else if (meta && meta.watching[keyName] > 0) {
                    if (MANDATORY_SETTER) {
                        currentValue = meta.values[keyName];
                    } else {
                        currentValue = obj[keyName];
                    }
                    // only trigger a change if the value has changed
                    if (value !== currentValue) {
                        propertyWillChange(obj, keyName);
                        if (MANDATORY_SETTER) {
                            if ((currentValue === undefined && !(keyName in obj)) || !obj.propertyIsEnumerable(keyName)) {
                                defineProperty(obj, keyName, null, value); // setup mandatory setter
                            } else {
                                meta.values[keyName] = value;
                            }
                        } else {
                            obj[keyName] = value;
                        }
                        propertyDidChange(obj, keyName);
                    }
                } else {
                    obj[keyName] = value;
                }
            }
            return value;
        };

        // Currently used only by Ember Data tests
        // ES6TODO: Verify still true
        if (Ember.config.overrideAccessors) {
            Ember.set = set;
            Ember.config.overrideAccessors();
            set = Ember.set;
        }

        function setPath(root, path, value, tolerant) {
            var keyName;

            // get the last part of the path
            keyName = path.slice(path.lastIndexOf('.') + 1);

            // get the first part of the part
            path = (path === keyName) ? keyName : path.slice(0, path.length - (keyName.length + 1));

            // unless the path is this, look up the first part to
            // get the root
            if (path !== 'this') {
                root = getPath(root, path);
            }

            if (!keyName || keyName.length === 0) {
                throw new EmberError('Property set failed: You passed an empty path');
            }

            if (!root) {
                if (tolerant) {
                    return;
                } else {
                    throw new EmberError('Property set failed: object in path "' + path + '" could not be found or was destroyed.');
                }
            }

            return set(root, keyName, value);
        }

        /**
              Error-tolerant form of `Ember.set`. Will not blow up if any part of the
              chain is `undefined`, `null`, or destroyed.

              This is primarily used when syncing bindings, which may try to update after
              an object has been destroyed.

              @method trySet
              @for Ember
              @param {Object} obj The object to modify.
              @param {String} path The property path to set
              @param {Object} value The value to set
            */
        function trySet(root, path, value) {
            return set(root, path, value, true);
        }

        __exports__.trySet = trySet;
        __exports__.set = set;
    });
    define("ember-metal/run_loop",
    ["ember-metal/core", "ember-metal/utils", "ember-metal/array", "ember-metal/property_events", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        var apply = __dependency2__.apply;
        var indexOf = __dependency3__.indexOf;
        var beginPropertyChanges = __dependency4__.beginPropertyChanges;
        var endPropertyChanges = __dependency4__.endPropertyChanges;

        function onBegin(current) {
            run.currentRunLoop = current;
        }

        function onEnd(current, next) {
            run.currentRunLoop = next;
        }

        // ES6TODO: should Backburner become es6?
        var Backburner = requireModule('backburner').Backburner;
        var backburner = new Backburner(['sync', 'actions', 'destroy'], {
            sync: {
                before: beginPropertyChanges,
                after: endPropertyChanges
            },
            defaultQueue: 'actions',
            onBegin: onBegin,
            onEnd: onEnd,
            onErrorTarget: Ember,
            onErrorMethod: 'onerror'
        });
        var slice = [].slice;
        var concat = [].concat;

        // ..........................................................
        // run - this is ideally the only public API the dev sees
        //

        /**
              Runs the passed target and method inside of a RunLoop, ensuring any
              deferred actions including bindings and views updates are flushed at the
              end.

              Normally you should not need to invoke this method yourself. However if
              you are implementing raw event handlers when interfacing with other
              libraries or plugins, you should probably wrap all of your code inside this
              call.

              ```javascript
              run(function() {
                // code to be execute within a RunLoop
              });
              ```

              @class run
              @namespace Ember
              @static
              @constructor
              @param {Object} [target] target of method to call
              @param {Function|String} method Method to invoke.
                May be a function or a string. If you pass a string
                then it will be looked up on the passed target.
              @param {Object} [args*] Any additional arguments you wish to pass to the method.
              @return {Object} return value from invoking the passed function.
            */
        __exports__["default"] = run;
        function run() {
            return apply(backburner, backburner.run, arguments);
        }

        /**
              If no run-loop is present, it creates a new one. If a run loop is
              present it will queue itself to run on the existing run-loops action
              queue.

              Please note: This is not for normal usage, and should be used sparingly.

              If invoked when not within a run loop:

              ```javascript
              run.join(function() {
                // creates a new run-loop
              });
              ```

              Alternatively, if called within an existing run loop:

              ```javascript
              run(function() {
                // creates a new run-loop
                run.join(function() {
                  // joins with the existing run-loop, and queues for invocation on
                  // the existing run-loops action queue.
                });
              });
              ```

              @method join
              @namespace Ember
              @param {Object} [target] target of method to call
              @param {Function|String} method Method to invoke.
                May be a function or a string. If you pass a string
                then it will be looked up on the passed target.
              @param {Object} [args*] Any additional arguments you wish to pass to the method.
              @return {Object} Return value from invoking the passed function. Please note,
              when called within an existing loop, no return value is possible.
            */
        run.join = function(target, method /* args */
        ) {
            if (!run.currentRunLoop) {
                return apply(Ember, run, arguments);
            }

            var args = slice.call(arguments);
            args.unshift('actions');
            apply(run, run.schedule, args);
        };

        /**
              Provides a useful utility for when integrating with non-Ember libraries
              that provide asynchronous callbacks.

              Ember utilizes a run-loop to batch and coalesce changes. This works by
              marking the start and end of Ember-related Javascript execution.

              When using events such as a View's click handler, Ember wraps the event
              handler in a run-loop, but when integrating with non-Ember libraries this
              can be tedious.

              For example, the following is rather verbose but is the correct way to combine
              third-party events and Ember code.

              ```javascript
              var that = this;
              jQuery(window).on('resize', function(){
                run(function(){
                  that.handleResize();
                });
              });
              ```

              To reduce the boilerplate, the following can be used to construct a
              run-loop-wrapped callback handler.

              ```javascript
              jQuery(window).on('resize', run.bind(this, this.handleResize));
              ```

              @method bind
              @namespace Ember
              @param {Object} [target] target of method to call
              @param {Function|String} method Method to invoke.
                May be a function or a string. If you pass a string
                then it will be looked up on the passed target.
              @param {Object} [args*] Any additional arguments you wish to pass to the method.
              @return {Object} return value from invoking the passed function. Please note,
              when called within an existing loop, no return value is possible.
              @since 1.4.0
            */
        run.bind = function(target, method /* args*/
        ) {
            var args = slice.call(arguments);
            return function() {
                return apply(run, run.join, args.concat(slice.call(arguments)));
            };
        };

        run.backburner = backburner;
        run.currentRunLoop = null;
        run.queues = backburner.queueNames;

        /**
              Begins a new RunLoop. Any deferred actions invoked after the begin will
              be buffered until you invoke a matching call to `run.end()`. This is
              a lower-level way to use a RunLoop instead of using `run()`.

              ```javascript
              run.begin();
              // code to be execute within a RunLoop
              run.end();
              ```

              @method begin
              @return {void}
            */
        run.begin = function() {
            backburner.begin();
        };

        /**
              Ends a RunLoop. This must be called sometime after you call
              `run.begin()` to flush any deferred actions. This is a lower-level way
              to use a RunLoop instead of using `run()`.

              ```javascript
              run.begin();
              // code to be execute within a RunLoop
              run.end();
              ```

              @method end
              @return {void}
            */
        run.end = function() {
            backburner.end();
        };

        /**
              Array of named queues. This array determines the order in which queues
              are flushed at the end of the RunLoop. You can define your own queues by
              simply adding the queue name to this array. Normally you should not need
              to inspect or modify this property.

              @property queues
              @type Array
              @default ['sync', 'actions', 'destroy']
            */

        /**
              Adds the passed target/method and any optional arguments to the named
              queue to be executed at the end of the RunLoop. If you have not already
              started a RunLoop when calling this method one will be started for you
              automatically.

              At the end of a RunLoop, any methods scheduled in this way will be invoked.
              Methods will be invoked in an order matching the named queues defined in
              the `run.queues` property.

              ```javascript
              run.schedule('sync', this, function() {
                // this will be executed in the first RunLoop queue, when bindings are synced
                console.log("scheduled on sync queue");
              });

              run.schedule('actions', this, function() {
                // this will be executed in the 'actions' queue, after bindings have synced.
                console.log("scheduled on actions queue");
              });

              // Note the functions will be run in order based on the run queues order.
              // Output would be:
              //   scheduled on sync queue
              //   scheduled on actions queue
              ```

              @method schedule
              @param {String} queue The name of the queue to schedule against.
                Default queues are 'sync' and 'actions'
              @param {Object} [target] target object to use as the context when invoking a method.
              @param {String|Function} method The method to invoke. If you pass a string it
                will be resolved on the target object at the time the scheduled item is
                invoked allowing you to change the target function.
              @param {Object} [arguments*] Optional arguments to be passed to the queued method.
              @return {void}
            */
        run.schedule = function(queue, target, method) {
            checkAutoRun();
            apply(backburner, backburner.schedule, arguments);
        };

        // Used by global test teardown
        run.hasScheduledTimers = function() {
            return backburner.hasTimers();
        };

        // Used by global test teardown
        run.cancelTimers = function () {
            backburner.cancelTimers();
        };

        /**
              Immediately flushes any events scheduled in the 'sync' queue. Bindings
              use this queue so this method is a useful way to immediately force all
              bindings in the application to sync.

              You should call this method anytime you need any changed state to propagate
              throughout the app immediately without repainting the UI (which happens
              in the later 'render' queue added by the `ember-views` package).

              ```javascript
              run.sync();
              ```

              @method sync
              @return {void}
            */
        run.sync = function() {
            if (backburner.currentInstance) {
                backburner.currentInstance.queues.sync.flush();
            }
        };

        /**
              Invokes the passed target/method and optional arguments after a specified
              period if time. The last parameter of this method must always be a number
              of milliseconds.

              You should use this method whenever you need to run some action after a
              period of time instead of using `setTimeout()`. This method will ensure that
              items that expire during the same script execution cycle all execute
              together, which is often more efficient than using a real setTimeout.

              ```javascript
              run.later(myContext, function() {
                // code here will execute within a RunLoop in about 500ms with this == myContext
              }, 500);
              ```

              @method later
              @param {Object} [target] target of method to invoke
              @param {Function|String} method The method to invoke.
                If you pass a string it will be resolved on the
                target at the time the method is invoked.
              @param {Object} [args*] Optional arguments to pass to the timeout.
              @param {Number} wait Number of milliseconds to wait.
              @return {String} a string you can use to cancel the timer in
                `run.cancel` later.
            */
        run.later = function(target, method) {
            return apply(backburner, backburner.later, arguments);
        };

        /**
              Schedule a function to run one time during the current RunLoop. This is equivalent
              to calling `scheduleOnce` with the "actions" queue.

              @method once
              @param {Object} [target] The target of the method to invoke.
              @param {Function|String} method The method to invoke.
                If you pass a string it will be resolved on the
                target at the time the method is invoked.
              @param {Object} [args*] Optional arguments to pass to the timeout.
              @return {Object} Timer information for use in cancelling, see `run.cancel`.
            */
        run.once = function(target, method) {
            checkAutoRun();
            var args = slice.call(arguments);
            args.unshift('actions');
            return apply(backburner, backburner.scheduleOnce, args);
        };

        /**
              Schedules a function to run one time in a given queue of the current RunLoop.
              Calling this method with the same queue/target/method combination will have
              no effect (past the initial call).

              Note that although you can pass optional arguments these will not be
              considered when looking for duplicates. New arguments will replace previous
              calls.

              ```javascript
              run(function() {
                var sayHi = function() { console.log('hi'); }
                run.scheduleOnce('afterRender', myContext, sayHi);
                run.scheduleOnce('afterRender', myContext, sayHi);
                // sayHi will only be executed once, in the afterRender queue of the RunLoop
              });
              ```

              Also note that passing an anonymous function to `run.scheduleOnce` will
              not prevent additional calls with an identical anonymous function from
              scheduling the items multiple times, e.g.:

              ```javascript
              function scheduleIt() {
                run.scheduleOnce('actions', myContext, function() { console.log("Closure"); });
              }
              scheduleIt();
              scheduleIt();
              // "Closure" will print twice, even though we're using `run.scheduleOnce`,
              // because the function we pass to it is anonymous and won't match the
              // previously scheduled operation.
              ```

              Available queues, and their order, can be found at `run.queues`

              @method scheduleOnce
              @param {String} [queue] The name of the queue to schedule against. Default queues are 'sync' and 'actions'.
              @param {Object} [target] The target of the method to invoke.
              @param {Function|String} method The method to invoke.
                If you pass a string it will be resolved on the
                target at the time the method is invoked.
              @param {Object} [args*] Optional arguments to pass to the timeout.
              @return {Object} Timer information for use in cancelling, see `run.cancel`.
            */
        run.scheduleOnce = function(queue, target, method) {
            checkAutoRun();
            return apply(backburner, backburner.scheduleOnce, arguments);
        };

        /**
              Schedules an item to run from within a separate run loop, after
              control has been returned to the system. This is equivalent to calling
              `run.later` with a wait time of 1ms.

              ```javascript
              run.next(myContext, function() {
                // code to be executed in the next run loop,
                // which will be scheduled after the current one
              });
              ```

              Multiple operations scheduled with `run.next` will coalesce
              into the same later run loop, along with any other operations
              scheduled by `run.later` that expire right around the same
              time that `run.next` operations will fire.

              Note that there are often alternatives to using `run.next`.
              For instance, if you'd like to schedule an operation to happen
              after all DOM element operations have completed within the current
              run loop, you can make use of the `afterRender` run loop queue (added
              by the `ember-views` package, along with the preceding `render` queue
              where all the DOM element operations happen). Example:

              ```javascript
              App.MyCollectionView = Ember.CollectionView.extend({
                didInsertElement: function() {
                  run.scheduleOnce('afterRender', this, 'processChildElements');
                },
                processChildElements: function() {
                  // ... do something with collectionView's child view
                  // elements after they've finished rendering, which
                  // can't be done within the CollectionView's
                  // `didInsertElement` hook because that gets run
                  // before the child elements have been added to the DOM.
                }
              });
              ```

              One benefit of the above approach compared to using `run.next` is
              that you will be able to perform DOM/CSS operations before unprocessed
              elements are rendered to the screen, which may prevent flickering or
              other artifacts caused by delaying processing until after rendering.

              The other major benefit to the above approach is that `run.next`
              introduces an element of non-determinism, which can make things much
              harder to test, due to its reliance on `setTimeout`; it's much harder
              to guarantee the order of scheduled operations when they are scheduled
              outside of the current run loop, i.e. with `run.next`.

              @method next
              @param {Object} [target] target of method to invoke
              @param {Function|String} method The method to invoke.
                If you pass a string it will be resolved on the
                target at the time the method is invoked.
              @param {Object} [args*] Optional arguments to pass to the timeout.
              @return {Object} Timer information for use in cancelling, see `run.cancel`.
            */
        run.next = function() {
            var args = slice.call(arguments);
            args.push(1);
            return apply(backburner, backburner.later, args);
        };

        /**
              Cancels a scheduled item. Must be a value returned by `run.later()`,
              `run.once()`, `run.next()`, `run.debounce()`, or
              `run.throttle()`.

              ```javascript
              var runNext = run.next(myContext, function() {
                // will not be executed
              });
              run.cancel(runNext);

              var runLater = run.later(myContext, function() {
                // will not be executed
              }, 500);
              run.cancel(runLater);

              var runOnce = run.once(myContext, function() {
                // will not be executed
              });
              run.cancel(runOnce);

              var throttle = run.throttle(myContext, function() {
                // will not be executed
              }, 1, false);
              run.cancel(throttle);

              var debounce = run.debounce(myContext, function() {
                // will not be executed
              }, 1);
              run.cancel(debounce);

              var debounceImmediate = run.debounce(myContext, function() {
                // will be executed since we passed in true (immediate)
              }, 100, true);
              // the 100ms delay until this method can be called again will be cancelled
              run.cancel(debounceImmediate);
              ```

              @method cancel
              @param {Object} timer Timer object to cancel
              @return {Boolean} true if cancelled or false/undefined if it wasn't found
            */
        run.cancel = function(timer) {
            return backburner.cancel(timer);
        };

        /**
              Delay calling the target method until the debounce period has elapsed
              with no additional debounce calls. If `debounce` is called again before
              the specified time has elapsed, the timer is reset and the entire period
              must pass again before the target method is called.

              This method should be used when an event may be called multiple times
              but the action should only be called once when the event is done firing.
              A common example is for scroll events where you only want updates to
              happen once scrolling has ceased.

              ```javascript
                var myFunc = function() { console.log(this.name + ' ran.'); };
                var myContext = {name: 'debounce'};

                run.debounce(myContext, myFunc, 150);

                // less than 150ms passes

                run.debounce(myContext, myFunc, 150);

                // 150ms passes
                // myFunc is invoked with context myContext
                // console logs 'debounce ran.' one time.
              ```

              Immediate allows you to run the function immediately, but debounce
              other calls for this function until the wait time has elapsed. If
              `debounce` is called again before the specified time has elapsed,
              the timer is reset and the entire period must pass again before
              the method can be called again.

              ```javascript
                var myFunc = function() { console.log(this.name + ' ran.'); };
                var myContext = {name: 'debounce'};

                run.debounce(myContext, myFunc, 150, true);

                // console logs 'debounce ran.' one time immediately.
                // 100ms passes

                run.debounce(myContext, myFunc, 150, true);

                // 150ms passes and nothing else is logged to the console and
                // the debouncee is no longer being watched

                run.debounce(myContext, myFunc, 150, true);

                // console logs 'debounce ran.' one time immediately.
                // 150ms passes and nothing else is logged to the console and
                // the debouncee is no longer being watched

              ```

              @method debounce
              @param {Object} [target] target of method to invoke
              @param {Function|String} method The method to invoke.
                May be a function or a string. If you pass a string
                then it will be looked up on the passed target.
              @param {Object} [args*] Optional arguments to pass to the timeout.
              @param {Number} wait Number of milliseconds to wait.
              @param {Boolean} immediate Trigger the function on the leading instead
                of the trailing edge of the wait interval. Defaults to false.
              @return {Array} Timer information for use in cancelling, see `run.cancel`.
            */
        run.debounce = function() {
            return apply(backburner, backburner.debounce, arguments);
        };

        /**
              Ensure that the target method is never called more frequently than
              the specified spacing period. The target method is called immediately.

              ```javascript
                var myFunc = function() { console.log(this.name + ' ran.'); };
                var myContext = {name: 'throttle'};

                run.throttle(myContext, myFunc, 150);
                // myFunc is invoked with context myContext
                // console logs 'throttle ran.'

                // 50ms passes
                run.throttle(myContext, myFunc, 150);

                // 50ms passes
                run.throttle(myContext, myFunc, 150);

                // 150ms passes
                run.throttle(myContext, myFunc, 150);
                // myFunc is invoked with context myContext
                // console logs 'throttle ran.'
              ```

              @method throttle
              @param {Object} [target] target of method to invoke
              @param {Function|String} method The method to invoke.
                May be a function or a string. If you pass a string
                then it will be looked up on the passed target.
              @param {Object} [args*] Optional arguments to pass to the timeout.
              @param {Number} spacing Number of milliseconds to space out requests.
              @param {Boolean} immediate Trigger the function on the leading instead
                of the trailing edge of the wait interval. Defaults to true.
              @return {Array} Timer information for use in cancelling, see `run.cancel`.
            */
        run.throttle = function() {
            return apply(backburner, backburner.throttle, arguments);
        };

        // Make sure it's not an autorun during testing
        function checkAutoRun() {
            if (!run.currentRunLoop) {
                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 run", !Ember.testing);
            }
        }

        /**
              Add a new named queue after the specified queue.

              The queue to add will only be added once.

              @method _addQueue
              @param {String} name the name of the queue to add.
              @param {String} after the name of the queue to add after.
              @private
            */
        run._addQueue = function(name, after) {
            if (indexOf.call(run.queues, name) === -1) {
                run.queues.splice(indexOf.call(run.queues, after) + 1, 0, name);
            }
        };
    });
    define("ember-metal/set_properties",
    ["ember-metal/property_events", "ember-metal/property_set", "exports"],
    function(__dependency1__, __dependency2__, __exports__) {
        "use strict";
        var changeProperties = __dependency1__.changeProperties;
        var set = __dependency2__.set;

        /**
              Set a list of properties on an object. These properties are set inside
              a single `beginPropertyChanges` and `endPropertyChanges` batch, so
              observers will be buffered.

              ```javascript
              var anObject = Ember.Object.create();

              anObject.setProperties({
                firstName: 'Stanley',
                lastName: 'Stuart',
                age: 21
              });
              ```

              @method setProperties
              @param self
              @param {Object} hash
              @return self
            */
        __exports__["default"] = function setProperties(self, hash) {
            changeProperties(function() {
                for (var prop in hash) {
                    if (hash.hasOwnProperty(prop)) {
                        set(self, prop, hash[prop]);
                    }
                }
            });
            return self;
        }
    });
    define("ember-metal/utils",
    ["ember-metal/core", "ember-metal/platform", "ember-metal/array", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        var platform = __dependency2__.platform;
        var create = __dependency2__.create;

        var forEach = __dependency3__.forEach;

        /**
            @module ember-metal
            */

        /**
              Previously we used `Ember.$.uuid`, however `$.uuid` has been removed from
              jQuery master. We'll just bootstrap our own uuid now.

              @private
              @return {Number} the uuid
            */
        var _uuid = 0;

        function uuid() {
            return ++_uuid;
        }

        __exports__.uuid = uuid; /**
              Prefix used for guids through out Ember.
              @private
              @property GUID_PREFIX
              @for Ember
              @type String
              @final
            */
        var GUID_PREFIX = 'ember';

        var o_defineProperty = platform.defineProperty;
        var o_create = create;
        // Used for guid generation...
        var numberCache = [];
        var stringCache = {};
        var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER;

        /**
              A unique key used to assign guids and other private metadata to objects.
              If you inspect an object in your browser debugger you will often see these.
              They can be safely ignored.

              On browsers that support it, these properties are added with enumeration
              disabled so they won't show up when you iterate over your properties.

              @private
              @property GUID_KEY
              @for Ember
              @type String
              @final
            */
        var GUID_KEY = '__ember' + ( + new Date());

        var GUID_DESC = {
            writable: false,
            configurable: false,
            enumerable: false,
            value: null
        };

        /**
              Generates a new guid, optionally saving the guid to the object that you
              pass in. You will rarely need to use this method. Instead you should
              call `Ember.guidFor(obj)`, which return an existing guid if available.

              @private
              @method generateGuid
              @for Ember
              @param {Object} [obj] Object the guid will be used for. If passed in, the guid will
                be saved on the object and reused whenever you pass the same object
                again.

                If no object is passed, just generate a new guid.
              @param {String} [prefix] Prefix to place in front of the guid. Useful when you want to
                separate the guid into separate namespaces.
              @return {String} the guid
            */
        function generateGuid(obj, prefix) {
            if (!prefix) 
                prefix = GUID_PREFIX;
            var ret = (prefix + uuid());
            if (obj) {
                if (obj[GUID_KEY] === null) {
                    obj[GUID_KEY] = ret;
                } else {
                    GUID_DESC.value = ret;
                    o_defineProperty(obj, GUID_KEY, GUID_DESC);
                }
            }
            return ret;
        }

        __exports__.generateGuid = generateGuid; /**
              Returns a unique id for the object. If the object does not yet have a guid,
              one will be assigned to it. You can call this on any object,
              `Ember.Object`-based or not, but be aware that it will add a `_guid`
              property.

              You can also use this method on DOM Element objects.

              @private
              @method guidFor
              @for Ember
              @param {Object} obj any object, string, number, Element, or primitive
              @return {String} the unique guid for this instance.
            */
        function guidFor(obj) {

            // special cases where we don't want to add a key to object
            if (obj === undefined) 
                return "(undefined)";
            if (obj === null) 
                return "(null)";

            var ret;
            var type = typeof obj;

            // Don't allow prototype changes to String etc. to change the guidFor
            switch (type) {
            case 'number':
                ret = numberCache[obj];
                if (!ret) 
                    ret = numberCache[obj] = 'nu' + obj;
                return ret;

            case 'string':
                ret = stringCache[obj];
                if (!ret) 
                    ret = stringCache[obj] = 'st' + uuid();
                return ret;

            case 'boolean':
                return obj ? '(true)' : '(false)';

            default:
                if (obj[GUID_KEY]) 
                    return obj[GUID_KEY];
                if (obj === Object) 
                    return '(Object)';
                if (obj === Array) 
                    return '(Array)';
                ret = 'ember' + uuid();

                if (obj[GUID_KEY] === null) {
                    obj[GUID_KEY] = ret;
                } else {
                    GUID_DESC.value = ret;
                    o_defineProperty(obj, GUID_KEY, GUID_DESC);
                }
                return ret;
            }
        }

        __exports__.guidFor = guidFor; // ..........................................................
        // META
        //

        var META_DESC = {
            writable: true,
            configurable: false,
            enumerable: false,
            value: null
        };

        /**
              The key used to store meta information on object for property observing.

              @property META_KEY
              @for Ember
              @private
              @final
              @type String
            */
        var META_KEY = '__ember_meta__';

        var isDefinePropertySimulated = platform.defineProperty.isSimulated;

        function Meta(obj) {
            this.descs = {};
            this.watching = {};
            this.cache = {};
            this.cacheMeta = {};
            this.source = obj;
        }

        Meta.prototype = {
            descs: null,
            deps: null,
            watching: null,
            listeners: null,
            cache: null,
            cacheMeta: null,
            source: null,
            mixins: null,
            bindings: null,
            chains: null,
            chainWatchers: null,
            values: null,
            proto: null
        };

        if (isDefinePropertySimulated) {
            // on platforms that don't support enumerable false
            // make meta fail jQuery.isPlainObject() to hide from
            // jQuery.extend() by having a property that fails
            // hasOwnProperty check.
            Meta.prototype.__preventPlainObject__ = true;

            // Without non-enumerable properties, meta objects will be output in JSON
            // unless explicitly suppressed
            Meta.prototype.toJSON = function () {};
        }

        // Placeholder for non-writable metas.
        var EMPTY_META = new Meta(null);

        if (MANDATORY_SETTER) {
            EMPTY_META.values = {};
        }

        /**
              Retrieves the meta hash for an object. If `writable` is true ensures the
              hash is writable for this object as well.

              The meta object contains information about computed property descriptors as
              well as any watched properties and other information. You generally will
              not access this information directly but instead work with higher level
              methods that manipulate this hash indirectly.

              @method meta
              @for Ember
              @private

              @param {Object} obj The object to retrieve meta for
              @param {Boolean} [writable=true] Pass `false` if you do not intend to modify
                the meta hash, allowing the method to avoid making an unnecessary copy.
              @return {Object} the meta hash for an object
            */
        function meta(obj, writable) {

            var ret = obj[META_KEY];
            if (writable === false) 
                return ret || EMPTY_META;

            if (!ret) {
                if (!isDefinePropertySimulated) 
                    o_defineProperty(obj, META_KEY, META_DESC);

                ret = new Meta(obj);

                if (MANDATORY_SETTER) {
                    ret.values = {};
                }

                obj[META_KEY] = ret;

                // make sure we don't accidentally try to create constructor like desc
                ret.descs.constructor = null;

            } else if (ret.source !== obj) {
                if (!isDefinePropertySimulated) 
                    o_defineProperty(obj, META_KEY, META_DESC);

                    ret = o_create(ret);
                    ret.descs = o_create(ret.descs);
                    ret.watching = o_create(ret.watching);
                    ret.cache = {};
                    ret.cacheMeta = {};
                    ret.source = obj;

                    if (MANDATORY_SETTER) {
                        ret.values = o_create(ret.values);
                    }

                    obj[META_KEY] = ret;
            }
            return ret;
        }

        function getMeta(obj, property) {
            var _meta = meta(obj, false);
            return _meta[property];
        }

        __exports__.getMeta = getMeta;
        function setMeta(obj, property, value) {
            var _meta = meta(obj, true);
            _meta[property] = value;
            return value;
        }

        __exports__.setMeta = setMeta; /**
              @deprecated
              @private

              In order to store defaults for a class, a prototype may need to create
              a default meta object, which will be inherited by any objects instantiated
              from the class's constructor.

              However, the properties of that meta object are only shallow-cloned,
              so if a property is a hash (like the event system's `listeners` hash),
              it will by default be shared across all instances of that class.

              This method allows extensions to deeply clone a series of nested hashes or
              other complex objects. For instance, the event system might pass
              `['listeners', 'foo:change', 'ember157']` to `prepareMetaPath`, which will
              walk down the keys provided.

              For each key, if the key does not exist, it is created. If it already
              exists and it was inherited from its constructor, the constructor's
              key is cloned.

              You can also pass false for `writable`, which will simply return
              undefined if `prepareMetaPath` discovers any part of the path that
              shared or undefined.

              @method metaPath
              @for Ember
              @param {Object} obj The object whose meta we are examining
              @param {Array} path An array of keys to walk down
              @param {Boolean} writable whether or not to create a new meta
                (or meta property) if one does not already exist or if it's
                shared with its constructor
            */
        function metaPath(obj, path, writable) {
            Ember.deprecate("Ember.metaPath is deprecated and will be removed from future releases.");
            var _meta = meta(obj, writable), keyName, value;

            for (var i = 0, l = path.length; i < l; i++) {
                keyName = path[i];
                value = _meta[keyName];

                if (!value) {
                    if (!writable) {
                        return undefined;
                    }
                    value = _meta[keyName] = {
                        __ember_source__: obj 
                    };
                } else if (value.__ember_source__ !== obj) {
                    if (!writable) {
                        return undefined;
                    }
                    value = _meta[keyName] = o_create(value);
                    value.__ember_source__ = obj;
                }

                _meta = value;
            }

            return value;
        }

        __exports__.metaPath = metaPath; /**
              Wraps the passed function so that `this._super` will point to the superFunc
              when the function is invoked. This is the primitive we use to implement
              calls to super.

              @private
              @method wrap
              @for Ember
              @param {Function} func The function to call
              @param {Function} superFunc The super function.
              @return {Function} wrapped function.
            */
        function wrap(func, superFunc) {
            function superWrapper() {
                var ret, sup = this && this.__nextSuper;
                if (this) {
                    this.__nextSuper = superFunc;
                }
                ret = apply(this, func, arguments);
                if (this) {
                    this.__nextSuper = sup;
                }
                return ret;
            }

            superWrapper.wrappedFunction = func;
            superWrapper.wrappedFunction.__ember_arity__ = func.length;
            superWrapper.__ember_observes__ = func.__ember_observes__;
            superWrapper.__ember_observesBefore__ = func.__ember_observesBefore__;
            superWrapper.__ember_listens__ = func.__ember_listens__;

            return superWrapper;
        }

        __exports__.wrap = wrap;
        var EmberArray;

        /**
              Returns true if the passed object is an array or Array-like.

              Ember Array Protocol:

                - the object has an objectAt property
                - the object is a native Array
                - the object is an Object, and has a length property

              Unlike `Ember.typeOf` this method returns true even if the passed object is
              not formally array but appears to be array-like (i.e. implements `Ember.Array`)

              ```javascript
              Ember.isArray();                                          // false
              Ember.isArray([]);                                        // true
              Ember.isArray(Ember.ArrayProxy.create({ content: [] }));  // true
              ```

              @method isArray
              @for Ember
              @param {Object} obj The object to test
              @return {Boolean} true if the passed object is an array or Array-like
            */
        // ES6TODO: Move up to runtime? This is only use in ember-metal by concatenatedProperties
        function isArray(obj) {
            var modulePath, type;

            if (typeof EmberArray === "undefined") {
                modulePath = 'ember-runtime/mixins/array';
                if (Ember.__loader.registry[modulePath]) {
                    EmberArray = Ember.__loader.require(modulePath)['default'];
                }
            }

            if (!obj || obj.setInterval) {
                return false;
            }
            if (Array.isArray && Array.isArray(obj)) {
                return true;
            }
            if (EmberArray && EmberArray.detect(obj)) {
                return true;
            }

            type = typeOf(obj);
            if ('array' === type) {
                return true;
            }
            if ((obj.length !== undefined) && 'object' === type) {
                return true;
            }
            return false;
        }

        /**
              Forces the passed object to be part of an array. If the object is already
              an array or array-like, returns the object. Otherwise adds the object to
              an array. If obj is `null` or `undefined`, returns an empty array.

              ```javascript
              Ember.makeArray();            // []
              Ember.makeArray(null);        // []
              Ember.makeArray(undefined);   // []
              Ember.makeArray('lindsay');   // ['lindsay']
              Ember.makeArray([1, 2, 42]);  // [1, 2, 42]

              var controller = Ember.ArrayProxy.create({ content: [] });

              Ember.makeArray(controller) === controller;  // true
              ```

              @method makeArray
              @for Ember
              @param {Object} obj the object
              @return {Array}
            */
        function makeArray(obj) {
            if (obj === null || obj === undefined) {
                return [];
            }
            return isArray(obj) ? obj : [obj];
        }

        __exports__.makeArray = makeArray; /**
              Checks to see if the `methodName` exists on the `obj`.

              ```javascript
              var foo = { bar: Ember.K, baz: null };

              Ember.canInvoke(foo, 'bar'); // true
              Ember.canInvoke(foo, 'baz'); // false
              Ember.canInvoke(foo, 'bat'); // false
              ```

              @method canInvoke
              @for Ember
              @param {Object} obj The object to check for the method
              @param {String} methodName The method name to check for
              @return {Boolean}
            */
        function canInvoke(obj, methodName) {
            return !!(obj && typeof obj[methodName] === 'function');
        }

        /**
              Checks to see if the `methodName` exists on the `obj`,
              and if it does, invokes it with the arguments passed.

              ```javascript
              var d = new Date('03/15/2013');

              Ember.tryInvoke(d, 'getTime');              // 1363320000000
              Ember.tryInvoke(d, 'setFullYear', [2014]);  // 1394856000000
              Ember.tryInvoke(d, 'noSuchMethod', [2014]); // undefined
              ```

              @method tryInvoke
              @for Ember
              @param {Object} obj The object to check for the method
              @param {String} methodName The method name to check for
              @param {Array} [args] The arguments to pass to the method
              @return {*} the return value of the invoked method or undefined if it cannot be invoked
            */
        function tryInvoke(obj, methodName, args) {
            if (canInvoke(obj, methodName)) {
                return args ? applyStr(obj, methodName, args) : applyStr(obj, methodName);
            }
        }

        __exports__.tryInvoke = tryInvoke; // https://github.com/emberjs/ember.js/pull/1617
        var needsFinallyFix = (function() {
            var count = 0;
            try {
                try {} finally {
                    count++;
                    throw new Error('needsFinallyFixTest');
                }
            } catch (e) {}

            return count !== 1;
        })();

        /**
              Provides try/finally functionality, while working
              around Safari's double finally bug.

              ```javascript
              var tryable = function() {
                someResource.lock();
                runCallback(); // May throw error.
              };

              var finalizer = function() {
                someResource.unlock();
              };

              Ember.tryFinally(tryable, finalizer);
              ```

              @method tryFinally
              @for Ember
              @param {Function} tryable The function to run the try callback
              @param {Function} finalizer The function to run the finally callback
              @param {Object} [binding] The optional calling object. Defaults to 'this'
              @return {*} The return value is the that of the finalizer,
              unless that value is undefined, in which case it is the return value
              of the tryable
            */

        var tryFinally;
        if (needsFinallyFix) {
            tryFinally = function(tryable, finalizer, binding) {
                var result, finalResult, finalError;

                binding = binding || this;

                try {
                    result = tryable.call(binding);
                } finally {
                    try {
                        finalResult = finalizer.call(binding);
                    } catch (e) {
                        finalError = e;
                    }
                }

                if (finalError) {
                    throw finalError;
                }

                return (finalResult === undefined) ? result : finalResult;
            };
        } else {
            tryFinally = function(tryable, finalizer, binding) {
                var result, finalResult;

                binding = binding || this;

                try {
                    result = tryable.call(binding);
                } finally {
                    finalResult = finalizer.call(binding);
                }

                return (finalResult === undefined) ? result : finalResult;
            };
        }

        /**
              Provides try/catch/finally functionality, while working
              around Safari's double finally bug.

              ```javascript
              var tryable = function() {
                for (i = 0, l = listeners.length; i < l; i++) {
                  listener = listeners[i];
                  beforeValues[i] = listener.before(name, time(), payload);
                }

                return callback.call(binding);
              };

              var catchable = function(e) {
                payload = payload || {};
                payload.exception = e;
              };

              var finalizer = function() {
                for (i = 0, l = listeners.length; i < l; i++) {
                  listener = listeners[i];
                  listener.after(name, time(), payload, beforeValues[i]);
                }
              };

              Ember.tryCatchFinally(tryable, catchable, finalizer);
              ```

              @method tryCatchFinally
              @for Ember
              @param {Function} tryable The function to run the try callback
              @param {Function} catchable The function to run the catchable callback
              @param {Function} finalizer The function to run the finally callback
              @param {Object} [binding] The optional calling object. Defaults to 'this'
              @return {*} The return value is the that of the finalizer,
              unless that value is undefined, in which case it is the return value
              of the tryable.
            */
        var tryCatchFinally;
        if (needsFinallyFix) {
            tryCatchFinally = function(tryable, catchable, finalizer, binding) {
                var result, finalResult, finalError;

                binding = binding || this;

                try {
                    result = tryable.call(binding);
                } catch (error) {
                    result = catchable.call(binding, error);
                } finally {
                    try {
                        finalResult = finalizer.call(binding);
                    } catch (e) {
                        finalError = e;
                    }
                }

                if (finalError) {
                    throw finalError;
                }

                return (finalResult === undefined) ? result : finalResult;
            };
        } else {
            tryCatchFinally = function(tryable, catchable, finalizer, binding) {
                var result, finalResult;

                binding = binding || this;

                try {
                    result = tryable.call(binding);
                } catch (error) {
                    result = catchable.call(binding, error);
                } finally {
                    finalResult = finalizer.call(binding);
                }

                return (finalResult === undefined) ? result : finalResult;
            };
        }

        // ........................................
        // TYPING & ARRAY MESSAGING
        //

        var TYPE_MAP = {};
        var t = "Boolean Number String Function Array Date RegExp Object".split(" ");
        forEach.call(t, function(name) {
            TYPE_MAP[ "[object " + name + "]" ] = name.toLowerCase();
        });

        var toString = Object.prototype.toString;

        var EmberObject;

        /**
              Returns a consistent type for the passed item.

              Use this instead of the built-in `typeof` to get the type of an item.
              It will return the same result across all browsers and includes a bit
              more detail. Here is what will be returned:

                  | Return Value  | Meaning                                              |
                  |---------------|------------------------------------------------------|
                  | 'string'      | String primitive or String object.                   |
                  | 'number'      | Number primitive or Number object.                   |
                  | 'boolean'     | Boolean primitive or Boolean object.                 |
                  | 'null'        | Null value                                           |
                  | 'undefined'   | Undefined value                                      |
                  | 'function'    | A function                                           |
                  | 'array'       | An instance of Array                                 |
                  | 'regexp'      | An instance of RegExp                                |
                  | 'date'        | An instance of Date                                  |
                  | 'class'       | An Ember class (created using Ember.Object.extend()) |
                  | 'instance'    | An Ember object instance                             |
                  | 'error'       | An instance of the Error object                      |
                  | 'object'      | A JavaScript object not inheriting from Ember.Object |

              Examples:

              ```javascript
              Ember.typeOf();                       // 'undefined'
              Ember.typeOf(null);                   // 'null'
              Ember.typeOf(undefined);              // 'undefined'
              Ember.typeOf('michael');              // 'string'
              Ember.typeOf(new String('michael'));  // 'string'
              Ember.typeOf(101);                    // 'number'
              Ember.typeOf(new Number(101));        // 'number'
              Ember.typeOf(true);                   // 'boolean'
              Ember.typeOf(new Boolean(true));      // 'boolean'
              Ember.typeOf(Ember.makeArray);        // 'function'
              Ember.typeOf([1, 2, 90]);             // 'array'
              Ember.typeOf(/abc/);                  // 'regexp'
              Ember.typeOf(new Date());             // 'date'
              Ember.typeOf(Ember.Object.extend());  // 'class'
              Ember.typeOf(Ember.Object.create());  // 'instance'
              Ember.typeOf(new Error('teamocil'));  // 'error'

              // 'normal' JavaScript object
              Ember.typeOf({ a: 'b' });             // 'object'
              ```

              @method typeOf
              @for Ember
              @param {Object} item the item to check
              @return {String} the type
            */
        function typeOf(item) {
            var ret, modulePath;

            // ES6TODO: Depends on Ember.Object which is defined in runtime.
            if (typeof EmberObject === "undefined") {
                modulePath = 'ember-runtime/system/object';
                if (Ember.__loader.registry[modulePath]) {
                    EmberObject = Ember.__loader.require(modulePath)['default'];
                }
            }

            ret = (item === null || item === undefined) ? String(item) : TYPE_MAP[toString.call(item)] || 'object';

            if (ret === 'function') {
                if (EmberObject && EmberObject.detect(item)) 
                    ret = 'class';
            } else if (ret === 'object') {
                if (item instanceof Error) 
                    ret = 'error';
                else if (EmberObject && item instanceof EmberObject) 
                    ret = 'instance';
                else if (item instanceof Date) 
                    ret = 'date';
            }

            return ret;
        }

        /**
              Convenience method to inspect an object. This method will attempt to
              convert the object into a useful string description.

              It is a pretty simple implementation. If you want something more robust,
              use something like JSDump: https://github.com/NV/jsDump

              @method inspect
              @for Ember
              @param {Object} obj The object you want to inspect.
              @return {String} A description of the object
              @since 1.4.0
            */
        function inspect(obj) {
            var type = typeOf(obj);
            if (type === 'array') {
                return '[' + obj + ']';
            }
            if (type !== 'object') {
                return obj + '';
            }

            var v, ret = [];
            for (var key in obj) {
                if (obj.hasOwnProperty(key)) {
                    v = obj[key];
                    if (v === 'toString') {
                        continue;
                    }
                    // ignore useless items
                    if (typeOf(v) === 'function') {
                        v = "function() { ... }";
                    }
                    ret.push(key + ": " + v);
                }
            }
            return "{" + ret.join(", ") + "}";
        }

        __exports__.inspect = inspect; // The following functions are intentionally minified to keep the functions
        // below Chrome's function body size inlining limit of 600 chars.

        function apply(t /* target */
        , m /* method */
        , a /* args */
        ) {
            var l = a && a.length;
            if (!a || !l) {
                return m.call(t);
            }
            switch (l) {
            case 1:
                return m.call(t, a[0]);
            case 2:
                return m.call(t, a[0], a[1]);
            case 3:
                return m.call(t, a[0], a[1], a[2]);
            case 4:
                return m.call(t, a[0], a[1], a[2], a[3]);
            case 5:
                return m.call(t, a[0], a[1], a[2], a[3], a[4]);
            default:
                return m.apply(t, a);
            }
        }

        __exports__.apply = apply;
        function applyStr(t /* target */
        , m /* method */
        , a /* args */
        ) {
            var l = a && a.length;
            if (!a || !l) {
                return t[m]();
            }
            switch (l) {
            case 1:
                return t[m](a[0]);
            case 2:
                return t[m](a[0], a[1]);
            case 3:
                return t[m](a[0], a[1], a[2]);
            case 4:
                return t[m](a[0], a[1], a[2], a[3]);
            case 5:
                return t[m](a[0], a[1], a[2], a[3], a[4]);
            default:
                return t[m].apply(t, a);
            }
        }

        __exports__.applyStr = applyStr;
        __exports__.GUID_KEY = GUID_KEY;
        __exports__.GUID_PREFIX = GUID_PREFIX;
        __exports__.META_DESC = META_DESC;
        __exports__.EMPTY_META = EMPTY_META;
        __exports__.META_KEY = META_KEY;
        __exports__.meta = meta;
        __exports__.typeOf = typeOf;
        __exports__.tryCatchFinally = tryCatchFinally;
        __exports__.isArray = isArray;
        __exports__.canInvoke = canInvoke;
        __exports__.tryFinally = tryFinally;
    });
    define("ember-metal/watch_key",
    ["ember-metal/core", "ember-metal/utils", "ember-metal/platform", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        var meta = __dependency2__.meta;
        var typeOf = __dependency2__.typeOf;
        var platform = __dependency3__.platform;

        var metaFor = meta; // utils.js
        var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER;
        var o_defineProperty = platform.defineProperty;

        function watchKey(obj, keyName, meta) {
            // can't watch length on Array - it is special...
            if (keyName === 'length' && typeOf(obj) === 'array') {
                return;
            }

            var m = meta || metaFor(obj), watching = m.watching;

            // activate watching first time
            if (!watching[keyName]) {
                watching[keyName] = 1;

                var desc = m.descs[keyName];
                if (desc && desc.willWatch) {
                    desc.willWatch(obj, keyName);
                }

                if ('function' === typeof obj.willWatchProperty) {
                    obj.willWatchProperty(keyName);
                }

                if (MANDATORY_SETTER && keyName in obj) {
                    m.values[keyName] = obj[keyName];
                    o_defineProperty(obj, keyName, {
                        configurable: true,
                        enumerable: obj.propertyIsEnumerable(keyName),
                        set: Ember.MANDATORY_SETTER_FUNCTION,
                        get: Ember.DEFAULT_GETTER_FUNCTION(keyName)
                    });
                }
            } else {
                watching[keyName] = (watching[keyName] || 0) + 1;
            }
        }

        __exports__.watchKey = watchKey;
        function unwatchKey(obj, keyName, meta) {
            var m = meta || metaFor(obj), watching = m.watching;

            if (watching[keyName] === 1) {
                watching[keyName] = 0;

                var desc = m.descs[keyName];
                if (desc && desc.didUnwatch) {
                    desc.didUnwatch(obj, keyName);
                }

                if ('function' === typeof obj.didUnwatchProperty) {
                    obj.didUnwatchProperty(keyName);
                }

                if (MANDATORY_SETTER && keyName in obj) {
                    o_defineProperty(obj, keyName, {
                        configurable: true,
                        enumerable: obj.propertyIsEnumerable(keyName),
                        set: function(val) {
                            // redefine to set as enumerable
                            o_defineProperty(obj, keyName, {
                                configurable: true,
                                writable: true,
                                enumerable: true,
                                value: val
                            });
                            delete m.values[keyName];
                        },
                        get: Ember.DEFAULT_GETTER_FUNCTION(keyName)
                    });
                }
            } else if (watching[keyName] > 1) {
                watching[keyName]--;
            }
        }

        __exports__.unwatchKey = unwatchKey;
    });
    define("ember-metal/watch_path",
    ["ember-metal/utils", "ember-metal/chains", "exports"],
    function(__dependency1__, __dependency2__, __exports__) {
        "use strict";
        var meta = __dependency1__.meta;
        var typeOf = __dependency1__.typeOf;
        var ChainNode = __dependency2__.ChainNode;

        var metaFor = meta;

        // get the chains for the current object. If the current object has
        // chains inherited from the proto they will be cloned and reconfigured for
        // the current object.
        function chainsFor(obj, meta) {
            var m = meta || metaFor(obj), ret = m.chains;
            if (!ret) {
                ret = m.chains = new ChainNode(null, null, obj);
            } else if (ret.value() !== obj) {
                ret = m.chains = ret.copy(obj);
            }
            return ret;
        }

        function watchPath(obj, keyPath, meta) {
            // can't watch length on Array - it is special...
            if (keyPath === 'length' && typeOf(obj) === 'array') {
                return;
            }

            var m = meta || metaFor(obj), watching = m.watching;

            if (!watching[keyPath]) {
                // activate watching first time
                watching[keyPath] = 1;
                chainsFor(obj, m).add(keyPath);
            } else {
                watching[keyPath] = (watching[keyPath] || 0) + 1;
            }
        }

        __exports__.watchPath = watchPath;
        function unwatchPath(obj, keyPath, meta) {
            var m = meta || metaFor(obj), watching = m.watching;

            if (watching[keyPath] === 1) {
                watching[keyPath] = 0;
                chainsFor(obj, m).remove(keyPath);
            } else if (watching[keyPath] > 1) {
                watching[keyPath]--;
            }
        }

        __exports__.unwatchPath = unwatchPath;
    });
    define("ember-metal/watching",
    ["ember-metal/utils", "ember-metal/chains", "ember-metal/watch_key", "ember-metal/watch_path", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
        "use strict";
        /**
            @module ember-metal
            */

        var meta = __dependency1__.meta;
        var META_KEY = __dependency1__.META_KEY;
        var GUID_KEY = __dependency1__.GUID_KEY;
        var typeOf = __dependency1__.typeOf;
        var generateGuid = __dependency1__.generateGuid;
        var removeChainWatcher = __dependency2__.removeChainWatcher;
        var flushPendingChains = __dependency2__.flushPendingChains;
        var watchKey = __dependency3__.watchKey;
        var unwatchKey = __dependency3__.unwatchKey;
        var watchPath = __dependency4__.watchPath;
        var unwatchPath = __dependency4__.unwatchPath;

        var metaFor = meta; // utils.js

        // returns true if the passed path is just a keyName
        function isKeyName(path) {
            return path.indexOf('.') === -1;
        }

        /**
              Starts watching a property on an object. Whenever the property changes,
              invokes `Ember.propertyWillChange` and `Ember.propertyDidChange`. This is the
              primitive used by observers and dependent keys; usually you will never call
              this method directly but instead use higher level methods like
              `Ember.addObserver()`

              @private
              @method watch
              @for Ember
              @param obj
              @param {String} keyName
            */
        function watch(obj, _keyPath, m) {
            // can't watch length on Array - it is special...
            if (_keyPath === 'length' && typeOf(obj) === 'array') {
                return;
            }

            if (isKeyName(_keyPath)) {
                watchKey(obj, _keyPath, m);
            } else {
                watchPath(obj, _keyPath, m);
            }
        }

        __exports__.watch = watch;

        function isWatching(obj, key) {
            var meta = obj[META_KEY];
            return (meta && meta.watching[key]) > 0;
        }

        __exports__.isWatching = isWatching;
        watch.flushPending = flushPendingChains;

        function unwatch(obj, _keyPath, m) {
            // can't watch length on Array - it is special...
            if (_keyPath === 'length' && typeOf(obj) === 'array') {
                return;
            }

            if (isKeyName(_keyPath)) {
                unwatchKey(obj, _keyPath, m);
            } else {
                unwatchPath(obj, _keyPath, m);
            }
        }

        __exports__.unwatch = unwatch; /**
              Call on an object when you first beget it from another object. This will
              setup any chained watchers on the object instance as needed. This method is
              safe to call multiple times.

              @private
              @method rewatch
              @for Ember
              @param obj
            */
        function rewatch(obj) {
            var m = obj[META_KEY], chains = m && m.chains;

            // make sure the object has its own guid.
            if (GUID_KEY in obj && !obj.hasOwnProperty(GUID_KEY)) {
                generateGuid(obj);
            }

            // make sure any chained watchers update.
            if (chains && chains.value() !== obj) {
                m.chains = chains.copy(obj);
            }
        }

        __exports__.rewatch = rewatch;
        var NODE_STACK = [];

        /**
              Tears down the meta on an object so that it can be garbage collected.
              Multiple calls will have no effect.

              @method destroy
              @for Ember
              @param {Object} obj  the object to destroy
              @return {void}
            */
        function destroy(obj) {
            var meta = obj[META_KEY], node, nodes, key, nodeObject;
            if (meta) {
                obj[META_KEY] = null;
                // remove chainWatchers to remove circular references that would prevent GC
                node = meta.chains;
                if (node) {
                    NODE_STACK.push(node);
                    // process tree
                    while (NODE_STACK.length > 0) {
                        node = NODE_STACK.pop();
                        // push children
                        nodes = node._chains;
                        if (nodes) {
                            for (key in nodes) {
                                if (nodes.hasOwnProperty(key)) {
                                    NODE_STACK.push(nodes[key]);
                                }
                            }
                        }
                        // remove chainWatcher in node object
                        if (node._watching) {
                            nodeObject = node._object;
                            if (nodeObject) {
                                removeChainWatcher(nodeObject, node._key, node);
                            }
                        }
                    }
                }
            }
        }

        __exports__.destroy = destroy;
    });
    define("ember-routing-handlebars",
    ["ember-metal/core", "ember-handlebars", "ember-routing/system/router", "ember-routing-handlebars/helpers/shared", "ember-routing-handlebars/helpers/link_to", "ember-routing-handlebars/helpers/outlet", "ember-routing-handlebars/helpers/render", "ember-routing-handlebars/helpers/action", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
        "use strict";
        /**
            Ember Routing Handlebars

            @module ember
            @submodule ember-routing-handlebars
            @requires ember-views
            */

        var Ember = __dependency1__["default"];
        var EmberHandlebars = __dependency2__["default"];
        var Router = __dependency3__["default"];

        var resolvePaths = __dependency4__.resolvePaths;
        var resolveParams = __dependency4__.resolveParams;

        var deprecatedLinkToHelper = __dependency5__.deprecatedLinkToHelper;
        var linkToHelper = __dependency5__.linkToHelper;
        var LinkView = __dependency5__.LinkView;

        var outletHelper = __dependency6__.outletHelper;
        var OutletView = __dependency6__.OutletView;

        var renderHelper = __dependency7__["default"];

        var ActionHelper = __dependency8__.ActionHelper;
        var actionHelper = __dependency8__.actionHelper;

        Router.resolveParams = resolveParams;
        Router.resolvePaths = resolvePaths;

        Ember.LinkView = LinkView;
        EmberHandlebars.ActionHelper = ActionHelper;
        EmberHandlebars.OutletView = OutletView;

        EmberHandlebars.registerHelper('render', renderHelper);
        EmberHandlebars.registerHelper('action', actionHelper);
        EmberHandlebars.registerHelper('outlet', outletHelper);
        EmberHandlebars.registerHelper('link-to', linkToHelper);
        EmberHandlebars.registerHelper('linkTo', deprecatedLinkToHelper);

        __exports__["default"] = Ember;
    });
    define("ember-routing-handlebars/helpers/action",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/array", "ember-metal/utils", "ember-metal/run_loop", "ember-views/system/utils", "ember-routing/system/router", "ember-handlebars", "ember-handlebars/ext", "ember-handlebars/helpers/view", "ember-routing-handlebars/helpers/shared", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // Handlebars, uuid, FEATURES, assert, deprecate
        var get = __dependency2__.get;
        var forEach = __dependency3__.forEach;
        var uuid = __dependency4__.uuid;
        var run = __dependency5__["default"];

        var isSimpleClick = __dependency6__.isSimpleClick;
        var EmberRouter = __dependency7__["default"];

        var EmberHandlebars = __dependency8__["default"];
        var handlebarsGet = __dependency9__.handlebarsGet;
        var viewHelper = __dependency10__.viewHelper;
        var resolveParams = __dependency11__.resolveParams;
        var resolvePath = __dependency11__.resolvePath;

        /**
            @module ember
            @submodule ember-routing
            */

        var SafeString = EmberHandlebars.SafeString;
        var a_slice = Array.prototype.slice;

        function args(options, actionName) {
            var ret = [];
            if (actionName) {
                ret.push(actionName);
            }

            var types = options.options.types.slice(1),
            data = options.options.data;

            return ret.concat(resolveParams(options.context, options.params, {
                types: types,
                data: data 
            }));
        }

        var ActionHelper = {
            registeredActions: {}
        };

        __exports__.ActionHelper = ActionHelper;

        var keys = ["alt", "shift", "meta", "ctrl"];

        var POINTER_EVENT_TYPE_REGEX = /^click|mouse|touch/;

        var isAllowedEvent = function(event, allowedKeys) {
            if (typeof allowedKeys === "undefined") {
                if (POINTER_EVENT_TYPE_REGEX.test(event.type)) {
                    return isSimpleClick(event);
                } else {
                    allowedKeys = '';
                }
            }

            if (allowedKeys.indexOf("any") >= 0) {
                return true;
            }

            var allowed = true;

            forEach.call(keys, function(key) {
                if (event[key + "Key"] && allowedKeys.indexOf(key) === -1) {
                    allowed = false;
                }
            });

            return allowed;
        };

        ActionHelper.registerAction = function(actionNameOrPath, options, allowedKeys) {
            var actionId = uuid();

            ActionHelper.registeredActions[actionId] = {
                eventName: options.eventName,
                handler: function handleRegisteredAction(event) {
                    if (!isAllowedEvent(event, allowedKeys)) {
                        return true;
                    }

                    if (options.preventDefault !== false) {
                        event.preventDefault();
                    }

                    if (options.bubbles === false) {
                        event.stopPropagation();
                    }

                    var target = options.target,
                    parameters = options.parameters,
                    actionName;

                    if (target.target) {
                        target = handlebarsGet(target.root, target.target, target.options);
                    } else {
                        target = target.root;
                    }

                    if (options.boundProperty) {
                        actionName = resolveParams(parameters.context, [actionNameOrPath], {
                            types: ['ID'],
                            data: parameters.options.data 
                        })[0];

                        if (typeof actionName === 'undefined' || typeof actionName === 'function') {
                            Ember.assert("You specified a quoteless path to the {{action}} helper '" + actionNameOrPath + "' which did not resolve to an actionName. Perhaps you meant to use a quoted actionName? (e.g. {{action '" + actionNameOrPath + "'}}).", true);
                            actionName = actionNameOrPath;
                        }
                    }

                    if (!actionName) {
                        actionName = actionNameOrPath;
                    }

                    run(function runRegisteredAction() {
                        if (target.send) {
                            target.send.apply(target, args(parameters, actionName));
                        } else {
                            Ember.assert("The action '" + actionName + "' did not exist on " + target, typeof target[actionName] === 'function');
                            target[actionName].apply(target, args(parameters));
                        }
                    });
                }
            };

            options.view.on('willClearRender', function() {
                delete ActionHelper.registeredActions[actionId];
            });

            return actionId;
        };

        /**
              The `{{action}}` helper registers an HTML element within a template for DOM
              event handling and forwards that interaction to the templates's controller
              or supplied `target` option (see 'Specifying a Target').

              If the controller does not implement the event, the event is sent
              to the current route, and it bubbles up the route hierarchy from there.

              User interaction with that element will invoke the supplied action name on
              the appropriate target. Specifying a non-quoted action name will result in
              a bound property lookup at the time the event will be triggered.

              Given the following application Handlebars template on the page

              ```handlebars
              <div {{action 'anActionName'}}>
                click me
              </div>
              ```

              And application code

              ```javascript
              App.ApplicationController = Ember.Controller.extend({
                actions: {
                  anActionName: function() {
                  }
                }
              });
              ```

              Will result in the following rendered HTML

              ```html
              <div class="ember-view">
                <div data-ember-action="1">
                  click me
                </div>
              </div>
              ```

              Clicking "click me" will trigger the `anActionName` action of the
              `App.ApplicationController`. In this case, no additional parameters will be passed.

              If you provide additional parameters to the helper:

              ```handlebars
              <button {{action 'edit' post}}>Edit</button>
              ```

              Those parameters will be passed along as arguments to the JavaScript
              function implementing the action.

              ### Event Propagation

              Events triggered through the action helper will automatically have
              `.preventDefault()` called on them. You do not need to do so in your event
              handlers. If you need to allow event propagation (to handle file inputs for
              example) you can supply the `preventDefault=false` option to the `{{action}}` helper:

              ```handlebars
              <div {{action "sayHello" preventDefault=false}}>
                <input type="file" />
                <input type="checkbox" />
              </div>
              ```

              To disable bubbling, pass `bubbles=false` to the helper:

              ```handlebars
              <button {{action 'edit' post bubbles=false}}>Edit</button>
              ```

              If you need the default handler to trigger you should either register your
              own event handler, or use event methods on your view class. See [Ember.View](/api/classes/Ember.View.html)
              'Responding to Browser Events' for more information.

              ### Specifying DOM event type

              By default the `{{action}}` helper registers for DOM `click` events. You can
              supply an `on` option to the helper to specify a different DOM event name:

              ```handlebars
              <div {{action "anActionName" on="doubleClick"}}>
                click me
              </div>
              ```

              See `Ember.View` 'Responding to Browser Events' for a list of
              acceptable DOM event names.

              NOTE: Because `{{action}}` depends on Ember's event dispatch system it will
              only function if an `Ember.EventDispatcher` instance is available. An
              `Ember.EventDispatcher` instance will be created when a new `Ember.Application`
              is created. Having an instance of `Ember.Application` will satisfy this
              requirement.

              ### Specifying whitelisted modifier keys

              By default the `{{action}}` helper will ignore click event with pressed modifier
              keys. You can supply an `allowedKeys` option to specify which keys should not be ignored.

              ```handlebars
              <div {{action "anActionName" allowedKeys="alt"}}>
                click me
              </div>
              ```

              This way the `{{action}}` will fire when clicking with the alt key pressed down.

              Alternatively, supply "any" to the `allowedKeys` option to accept any combination of modifier keys.

              ```handlebars
              <div {{action "anActionName" allowedKeys="any"}}>
                click me with any key pressed
              </div>
              ```

              ### Specifying a Target

              There are several possible target objects for `{{action}}` helpers:

              In a typical Ember application, where views are managed through use of the
              `{{outlet}}` helper, actions will bubble to the current controller, then
              to the current route, and then up the route hierarchy.

              Alternatively, a `target` option can be provided to the helper to change
              which object will receive the method call. This option must be a path
              to an object, accessible in the current context:

              ```handlebars
              {{! the application template }}
              <div {{action "anActionName" target=view}}>
                click me
              </div>
              ```

              ```javascript
              App.ApplicationView = Ember.View.extend({
                actions: {
                  anActionName: function(){}
                }
              });

              ```

              ### Additional Parameters

              You may specify additional parameters to the `{{action}}` helper. These
              parameters are passed along as the arguments to the JavaScript function
              implementing the action.

              ```handlebars
              {{#each person in people}}
                <div {{action "edit" person}}>
                  click me
                </div>
              {{/each}}
              ```

              Clicking "click me" will trigger the `edit` method on the current controller
              with the value of `person` as a parameter.

              @method action
              @for Ember.Handlebars.helpers
              @param {String} actionName
              @param {Object} [context]*
              @param {Hash} options
            */
        function actionHelper(actionName) {
            var options = arguments[arguments.length - 1],
            contexts = a_slice.call(arguments, 1, -1);

            var hash = options.hash,
            controller = options.data.keywords.controller;

            // create a hash to pass along to registerAction
            var action = {
                eventName: hash.on || "click",
                parameters: {
                    context: this,
                    options: options,
                    params: contexts
                },
                view: options.data.view,
                bubbles: hash.bubbles,
                preventDefault: hash.preventDefault,
                target: {
                    options: options 
                },
                boundProperty: options.types[0] === "ID"
            };

            if (hash.target) {
                action.target.root = this;
                action.target.target = hash.target;
            } else if (controller) {
                action.target.root = controller;
            }

            var actionId = ActionHelper.registerAction(actionName, action, hash.allowedKeys);
            return new SafeString('data-ember-action="' + actionId + '"');
        }

        __exports__.actionHelper = actionHelper;
    });
    define("ember-routing-handlebars/helpers/link_to",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/merge", "ember-metal/run_loop", "ember-metal/computed", "ember-runtime/system/lazy_load", "ember-runtime/system/string", "ember-runtime/system/object", "ember-runtime/keys", "ember-views/system/utils", "ember-views/views/component", "ember-handlebars", "ember-handlebars/helpers/view", "ember-routing/system/router", "ember-routing-handlebars/helpers/shared", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // FEATURES, Logger, Handlebars, warn, assert
        var get = __dependency2__.get;
        var set = __dependency3__.set;
        var merge = __dependency4__["default"];
        var run = __dependency5__["default"];
        var computed = __dependency6__.computed;

        var onLoad = __dependency7__.onLoad;
        var fmt = __dependency8__.fmt;
        var EmberObject = __dependency9__["default"];
        var keys = __dependency10__["default"];
        var isSimpleClick = __dependency11__.isSimpleClick;
        var EmberComponent = __dependency12__["default"];
        var EmberHandlebars = __dependency13__["default"];
        var viewHelper = __dependency14__.viewHelper;
        var EmberRouter = __dependency15__["default"];
        var resolveParams = __dependency16__.resolveParams;
        var resolvePaths = __dependency16__.resolvePaths;
        var routeArgs = __dependency16__.routeArgs;

        /**
            @module ember
            @submodule ember-routing
            */

        var slice = [].slice;

        requireModule('ember-handlebars');

        var numberOfContextsAcceptedByHandler = function(handler, handlerInfos) {
            var req = 0;
            for (var i = 0, l = handlerInfos.length; i < l; i++) {
                req = req + handlerInfos[i].names.length;
                if (handlerInfos[i].handler === handler)
                    break;
            }

            return req;
        };

        var QueryParams = EmberObject.extend({
            values: null
        });

        function getResolvedPaths(options) {

            var types = options.options.types,
            data = options.options.data;

            return resolvePaths(options.context, options.params, {
                types: types,
                data: data 
            });
        }

        /**
              `Ember.LinkView` renders an element whose `click` event triggers a
              transition of the application's instance of `Ember.Router` to
              a supplied route by name.

              Instances of `LinkView` will most likely be created through
              the `link-to` Handlebars helper, but properties of this class
              can be overridden to customize application-wide behavior.

              @class LinkView
              @namespace Ember
              @extends Ember.View
              @see {Handlebars.helpers.link-to}
            **/
        var LinkView = Ember.LinkView = EmberComponent.extend({
            tagName: 'a',
            currentWhen: null,

            /**
                    Sets the `title` attribute of the `LinkView`'s HTML element.

                    @property title
                    @default null
                  **/
            title: null,

            /**
                    Sets the `rel` attribute of the `LinkView`'s HTML element.

                    @property rel
                    @default null
                  **/
            rel: null,

            /**
                    The CSS class to apply to `LinkView`'s element when its `active`
                    property is `true`.

                    @property activeClass
                    @type String
                    @default active
                  **/
            activeClass: 'active',

            /**
                    The CSS class to apply to `LinkView`'s element when its `loading`
                    property is `true`.

                    @property loadingClass
                    @type String
                    @default loading
                  **/
            loadingClass: 'loading',

            /**
                    The CSS class to apply to a `LinkView`'s element when its `disabled`
                    property is `true`.

                    @property disabledClass
                    @type String
                    @default disabled
                  **/
            disabledClass: 'disabled',
            _isDisabled: false,

            /**
                    Determines whether the `LinkView` will trigger routing via
                    the `replaceWith` routing strategy.

                    @property replace
                    @type Boolean
                    @default false
                  **/
            replace: false,

            /**
                    By default the `{{link-to}}` helper will bind to the `href` and
                    `title` attributes. It's discourage that you override these defaults,
                    however you can push onto the array if needed.

                    @property attributeBindings
                    @type Array | String
                    @default ['href', 'title', 'rel']
                   **/
            attributeBindings: ['href', 'title', 'rel'],

            /**
                    By default the `{{link-to}}` helper will bind to the `active`, `loading`, and
                    `disabled` classes. It is discouraged to override these directly.

                    @property classNameBindings
                    @type Array
                    @default ['active', 'loading', 'disabled']
                   **/
            classNameBindings: ['active', 'loading', 'disabled'],

            /**
                    By default the `{{link-to}}` helper responds to the `click` event. You
                    can override this globally by setting this property to your custom
                    event name.

                    This is particularly useful on mobile when one wants to avoid the 300ms
                    click delay using some sort of custom `tap` event.

                    @property eventName
                    @type String
                    @default click
                  */
            eventName: 'click',

            // this is doc'ed here so it shows up in the events
            // section of the API documentation, which is where
            // people will likely go looking for it.
            /**
                    Triggers the `LinkView`'s routing behavior. If
                    `eventName` is changed to a value other than `click`
                    the routing behavior will trigger on that custom event
                    instead.

                    @event click
                  **/

            /**
                    An overridable method called when LinkView objects are instantiated.

                    Example:

                    ```javascript
                    App.MyLinkView = Ember.LinkView.extend({
                      init: function() {
                        this._super();
                        Ember.Logger.log('Event is ' + this.get('eventName'));
                      }
                    });
                    ```

                    NOTE: If you do override `init` for a framework class like `Ember.View` or
                    `Ember.ArrayController`, be sure to call `this._super()` in your
                    `init` declaration! If you don't, Ember may not have an opportunity to
                    do important setup work, and you'll see strange behavior in your
                    application.

                    @method init
                  */
            init: function() {
                this._super.apply(this, arguments);

                // Map desired event name to invoke function
                var eventName = get(this, 'eventName');
                this.on(eventName, this, this._invoke);
            },

            /**
                    This method is invoked by observers installed during `init` that fire
                    whenever the params change

                    @private
                    @method _paramsChanged
                    @since 1.3.0
                   */
            _paramsChanged: function() {
                this.notifyPropertyChange('resolvedParams');
            },

            /**
                   This is called to setup observers that will trigger a rerender.

                   @private
                   @method _setupPathObservers
                   @since 1.3.0
                  **/
            _setupPathObservers: function() {
                var helperParameters = this.parameters,
                linkTextPath = helperParameters.options.linkTextPath,
                paths = getResolvedPaths(helperParameters),
                length = paths.length,
                path, i, normalizedPath;

                if (linkTextPath) {
                    normalizedPath = getNormalizedPath(linkTextPath, helperParameters);
                    this.registerObserver(normalizedPath.root, normalizedPath.path, this, this.rerender);
                }

                for (i = 0; i < length; i++) {
                    path = paths[i];
                    if (null === path) {
                        // A literal value was provided, not a path, so nothing to observe.
                        continue;
                    }

                    normalizedPath = getNormalizedPath(path, helperParameters);
                    this.registerObserver(normalizedPath.root, normalizedPath.path, this, this._paramsChanged);
                }

                var queryParamsObject = this.queryParamsObject;
                if (queryParamsObject) {
                    var values = queryParamsObject.values;

                    // Install observers for all of the hash options
                    // provided in the (query-params) subexpression.
                    for (var k in values) {
                        if (!values.hasOwnProperty(k)) {
                            continue;
                        }

                        if (queryParamsObject.types[k] === 'ID') {
                            normalizedPath = getNormalizedPath(values[k], helperParameters);
                            this.registerObserver(normalizedPath.root, normalizedPath.path, this, this._paramsChanged);
                        }
                    }
                }
            },

            afterRender: function() {
                this._super.apply(this, arguments);
                this._setupPathObservers();
            },

            /**

                    Accessed as a classname binding to apply the `LinkView`'s `disabledClass`
                    CSS `class` to the element when the link is disabled.

                    When `true` interactions with the element will not trigger route changes.
                    @property disabled
                  */
            disabled: computed(function computeLinkViewDisabled(key, value) {
                if (value !== undefined) {
                    this.set('_isDisabled', value);
                }

                return value ? get(this, 'disabledClass') : false;
            }),

            /**
                    Accessed as a classname binding to apply the `LinkView`'s `activeClass`
                    CSS `class` to the element when the link is active.

                    A `LinkView` is considered active when its `currentWhen` property is `true`
                    or the application's current route is the route the `LinkView` would trigger
                    transitions into.

                    @property active
                  **/
            active: computed('loadedParams', function computeLinkViewActive() {
                if (get(this, 'loading')) {
                    return false;
                }

                var router = get(this, 'router'),
                loadedParams = get(this, 'loadedParams'),
                contexts = loadedParams.models,
                currentWhen = this.currentWhen || loadedParams.targetRouteName,
                handlers = router.router.recognizer.handlersFor(currentWhen),
                leafName = handlers[handlers.length-1].handler,
                maximumContexts = numberOfContextsAcceptedByHandler(currentWhen, handlers);

                // NOTE: any ugliness in the calculation of activeness is largely
                // due to the fact that we support automatic normalizing of
                // `resource` -> `resource.index`, even though there might be
                // dynamic segments / query params defined on `resource.index`
                // which complicates (and makes somewhat ambiguous) the calculation
                // of activeness for links that link to `resource` instead of
                // directly to `resource.index`.

                // if we don't have enough contexts revert back to full route name
                // this is because the leaf route will use one of the contexts
                if (contexts.length > maximumContexts) {
                    currentWhen = leafName;
                }

                var args = routeArgs(currentWhen, contexts, null);
                var isActive = router.isActive.apply(router, args);
                if (!isActive) {
                    return false;
                }


                if (!this.currentWhen && leafName === loadedParams.targetRouteName) {
                    var visibleQueryParams = {};
                    merge(visibleQueryParams, loadedParams.queryParams);
                    router._prepareQueryParams(loadedParams.targetRouteName, loadedParams.models, visibleQueryParams);
                    isActive = shallowEqual(visibleQueryParams, router.router.state.queryParams);
                }


                if (isActive) {
                    return get(this, 'activeClass');
                }
            }),

            /**
                    Accessed as a classname binding to apply the `LinkView`'s `loadingClass`
                    CSS `class` to the element when the link is loading.

                    A `LinkView` is considered loading when it has at least one
                    parameter whose value is currently null or undefined. During
                    this time, clicking the link will perform no transition and
                    emit a warning that the link is still in a loading state.

                    @property loading
                  **/
            loading: computed('loadedParams', function computeLinkViewLoading() {
                if (!get(this, 'loadedParams')) {
                    return get(this, 'loadingClass');
                }
            }),

            /**
                    Returns the application's main router from the container.

                    @private
                    @property router
                  **/
            router: computed(function() {
                return get(this, 'controller').container.lookup('router:main');
            }),

            /**
                    Event handler that invokes the link, activating the associated route.

                    @private
                    @method _invoke
                    @param {Event} event
                  */
            _invoke: function(event) {
                if (!isSimpleClick(event)) {
                    return true;
                }

                if (this.preventDefault !== false) {

                    event.preventDefault();

                }

                if (this.bubbles === false) {
                    event.stopPropagation();
                }

                if (get(this, '_isDisabled')) {
                    return false;
                }

                if (get(this, 'loading')) {
                    Ember.Logger.warn("This link-to is in an inactive loading state because at least one of its parameters presently has a null/undefined value, or the provided route name is invalid.");
                    return false;
                }

                var router = get(this, 'router'),
                loadedParams = get(this, 'loadedParams');

                var transition = router._doTransition(loadedParams.targetRouteName, loadedParams.models, loadedParams.queryParams);
                if (get(this, 'replace')) {
                    transition.method('replace');
                }

                // Schedule eager URL update, but after we've given the transition
                // a chance to synchronously redirect.
                // We need to always generate the URL instead of using the href because
                // the href will include any rootURL set, but the router expects a URL
                // without it! Note that we don't use the first level router because it
                // calls location.formatURL(), which also would add the rootURL!
                var args = routeArgs(loadedParams.targetRouteName, loadedParams.models, transition.state.queryParams);
                var url = router.router.generate.apply(router.router, args);

                run.scheduleOnce('routerTransitions', this, this._eagerUpdateUrl, transition, url);
            },

            /**
                    @private
                    @method _eagerUpdateUrl
                    @param transition
                    @param href
                   */
            _eagerUpdateUrl: function(transition, href) {
                if (!transition.isActive || !transition.urlMethod) {
                    // transition was aborted, already ran to completion,
                    // or it has a null url-updated method.
                    return;
                }

                if (href.indexOf('#') === 0) {
                    href = href.slice(1);
                }

                // Re-use the routerjs hooks set up by the Ember router.
                var routerjs = get(this, 'router.router');
                if (transition.urlMethod === 'update') {
                    routerjs.updateURL(href);
                } else if (transition.urlMethod === 'replace') {
                    routerjs.replaceURL(href);
                }

                // Prevent later update url refire.
                transition.method(null);
            },

            /**
                    Computed property that returns an array of the
                    resolved parameters passed to the `link-to` helper,
                    e.g.:

                    ```hbs
                    {{link-to a b '123' c}}
                    ```

                    will generate a `resolvedParams` of:

                    ```js
                    [aObject, bObject, '123', cObject]
                    ```

                    @private
                    @property
                    @return {Array}
                   */
            resolvedParams: computed('router.url', function() {
                var parameters = this.parameters,
                options = parameters.options,
                types = options.types,
                data = options.data,
                targetRouteName, models;

                var onlyQueryParamsSupplied = (parameters.params.length === 0);
                if (onlyQueryParamsSupplied) {
                    var appController = this.container.lookup('controller:application');
                    targetRouteName = get(appController, 'currentRouteName');
                    models = [];
                } else {
                    models = resolveParams(parameters.context, parameters.params, {
                        types: types,
                        data: data 
                    });
                    targetRouteName = models.shift();
                }

                var suppliedQueryParams = getResolvedQueryParams(this, targetRouteName);

                return {
                    targetRouteName: targetRouteName,
                    models: models,
                    queryParams: suppliedQueryParams
                };
            }),

            /**
                    Computed property that returns the current route name,
                    dynamic segments, and query params. Returns falsy if
                    for null/undefined params to indicate that the link view
                    is still in a loading state.

                    @private
                    @property
                    @return {Array} An array with the route name and any dynamic segments
                  **/
            loadedParams: computed('resolvedParams', function computeLinkViewRouteArgs() {
                var resolvedParams = get(this, 'resolvedParams'),
                router = get(this, 'router'),
                namedRoute = resolvedParams.targetRouteName;

                if (!namedRoute) {
                    return;
                }

                Ember.assert(fmt("The attempt to link-to route '%@' failed. " +
                "The router did not find '%@' in its possible routes: '%@'",
                [namedRoute, namedRoute, keys(router.router.recognizer.names).join("', '")]),
                router.hasRoute(namedRoute));

                if (!paramsAreLoaded(resolvedParams.models)) {
                    return;
                }

                return resolvedParams;
            }),

            queryParamsObject: null,

            /**
                    Sets the element's `href` attribute to the url for
                    the `LinkView`'s targeted route.

                    If the `LinkView`'s `tagName` is changed to a value other
                    than `a`, this property will be ignored.

                    @property href
                  **/
            href: computed('loadedParams', function computeLinkViewHref() {
                if (get(this, 'tagName') !== 'a') {
                    return;
                }

                var router = get(this, 'router'),
                loadedParams = get(this, 'loadedParams');

                if (!loadedParams) {
                    return get(this, 'loadingHref');
                }

                var visibleQueryParams = {};

                merge(visibleQueryParams, loadedParams.queryParams);
                router._prepareQueryParams(loadedParams.targetRouteName, loadedParams.models, visibleQueryParams);


                var args = routeArgs(loadedParams.targetRouteName, loadedParams.models, visibleQueryParams);
                var result = router.generate.apply(router, args);
                return result;
            }),

            /**
                    The default href value to use while a link-to is loading.
                    Only applies when tagName is 'a'

                    @property loadingHref
                    @type String
                    @default #
                  */
            loadingHref: '#'
        });

        LinkView.toString = function() {
            return "LinkView";
        };


        /**
              The `{{link-to}}` helper renders a link to the supplied
              `routeName` passing an optionally supplied model to the
              route as its `model` context of the route. The block
              for `{{link-to}}` becomes the innerHTML of the rendered
              element:

              ```handlebars
              {{#link-to 'photoGallery'}}
                Great Hamster Photos
              {{/link-to}}
              ```

              ```html
              <a href="/hamster-photos">
                Great Hamster Photos
              </a>
              ```

              ### Supplying a tagName
              By default `{{link-to}}` renders an `<a>` element. This can
              be overridden for a single use of `{{link-to}}` by supplying
              a `tagName` option:

              ```handlebars
              {{#link-to 'photoGallery' tagName="li"}}
                Great Hamster Photos
              {{/link-to}}
              ```

              ```html
              <li>
                Great Hamster Photos
              </li>
              ```

              To override this option for your entire application, see
              "Overriding Application-wide Defaults".

              ### Disabling the `link-to` helper
              By default `{{link-to}}` is enabled.
              any passed value to `disabled` helper property will disable the `link-to` helper.

              static use: the `disabled` option:

              ```handlebars
              {{#link-to 'photoGallery' disabled=true}}
                Great Hamster Photos
              {{/link-to}}
              ```

              dynamic use: the `disabledWhen` option:

              ```handlebars
              {{#link-to 'photoGallery' disabledWhen=controller.someProperty}}
                Great Hamster Photos
              {{/link-to}}
              ```

              any passed value to `disabled` will disable it except `undefined`.
              to ensure that only `true` disable the `link-to` helper you can
              override the global behaviour of `Ember.LinkView`.

              ```javascript
              Ember.LinkView.reopen({
                disabled: Ember.computed(function(key, value) {
                  if (value !== undefined) {
                    this.set('_isDisabled', value === true);
                  }
                  return value === true ? get(this, 'disabledClass') : false;
                })
              });
              ```

              see "Overriding Application-wide Defaults" for more.

              ### Handling `href`
              `{{link-to}}` will use your application's Router to
              fill the element's `href` property with a url that
              matches the path to the supplied `routeName` for your
              routers's configured `Location` scheme, which defaults
              to Ember.HashLocation.

              ### Handling current route
              `{{link-to}}` will apply a CSS class name of 'active'
              when the application's current route matches
              the supplied routeName. For example, if the application's
              current route is 'photoGallery.recent' the following
              use of `{{link-to}}`:

              ```handlebars
              {{#link-to 'photoGallery.recent'}}
                Great Hamster Photos from the last week
              {{/link-to}}
              ```

              will result in

              ```html
              <a href="/hamster-photos/this-week" class="active">
                Great Hamster Photos
              </a>
              ```

              The CSS class name used for active classes can be customized
              for a single use of `{{link-to}}` by passing an `activeClass`
              option:

              ```handlebars
              {{#link-to 'photoGallery.recent' activeClass="current-url"}}
                Great Hamster Photos from the last week
              {{/link-to}}
              ```

              ```html
              <a href="/hamster-photos/this-week" class="current-url">
                Great Hamster Photos
              </a>
              ```

              To override this option for your entire application, see
              "Overriding Application-wide Defaults".

              ### Supplying a model
              An optional model argument can be used for routes whose
              paths contain dynamic segments. This argument will become
              the model context of the linked route:

              ```javascript
              App.Router.map(function() {
                this.resource("photoGallery", {path: "hamster-photos/:photo_id"});
              });
              ```

              ```handlebars
              {{#link-to 'photoGallery' aPhoto}}
                {{aPhoto.title}}
              {{/link-to}}
              ```

              ```html
              <a href="/hamster-photos/42">
                Tomster
              </a>
              ```

              ### Supplying multiple models
              For deep-linking to route paths that contain multiple
              dynamic segments, multiple model arguments can be used.
              As the router transitions through the route path, each
              supplied model argument will become the context for the
              route with the dynamic segments:

              ```javascript
              App.Router.map(function() {
                this.resource("photoGallery", {path: "hamster-photos/:photo_id"}, function() {
                  this.route("comment", {path: "comments/:comment_id"});
                });
              });
              ```
              This argument will become the model context of the linked route:

              ```handlebars
              {{#link-to 'photoGallery.comment' aPhoto comment}}
                {{comment.body}}
              {{/link-to}}
              ```

              ```html
              <a href="/hamster-photos/42/comment/718">
                A+++ would snuggle again.
              </a>
              ```

              ### Supplying an explicit dynamic segment value
              If you don't have a model object available to pass to `{{link-to}}`,
              an optional string or integer argument can be passed for routes whose
              paths contain dynamic segments. This argument will become the value
              of the dynamic segment:

              ```javascript
              App.Router.map(function() {
                this.resource("photoGallery", {path: "hamster-photos/:photo_id"});
              });
              ```

              ```handlebars
              {{#link-to 'photoGallery' aPhotoId}}
                {{aPhoto.title}}
              {{/link-to}}
              ```

              ```html
              <a href="/hamster-photos/42">
                Tomster
              </a>
              ```

              When transitioning into the linked route, the `model` hook will
              be triggered with parameters including this passed identifier.

              ### Allowing Default Action

             By default the `{{link-to}}` helper prevents the default browser action
             by calling `preventDefault()` as this sort of action bubbling is normally
             handled internally and we do not want to take the browser to a new URL (for
             example).

             If you need to override this behavior specify `preventDefault=false` in
             your template:

              ```handlebars
              {{#link-to 'photoGallery' aPhotoId preventDefault=false}}
                {{aPhotoId.title}}
              {{/link-to}}
              ```

              ### Overriding attributes
              You can override any given property of the Ember.LinkView
              that is generated by the `{{link-to}}` helper by passing
              key/value pairs, like so:

              ```handlebars
              {{#link-to  aPhoto tagName='li' title='Following this link will change your life' classNames='pic sweet'}}
                Uh-mazing!
              {{/link-to}}
              ```

              See [Ember.LinkView](/api/classes/Ember.LinkView.html) for a
              complete list of overrideable properties. Be sure to also
              check out inherited properties of `LinkView`.

              ### Overriding Application-wide Defaults
              ``{{link-to}}`` creates an instance of Ember.LinkView
              for rendering. To override options for your entire
              application, reopen Ember.LinkView and supply the
              desired values:

              ``` javascript
              Ember.LinkView.reopen({
                activeClass: "is-active",
                tagName: 'li'
              })
              ```

              It is also possible to override the default event in
              this manner:

              ``` javascript
              Ember.LinkView.reopen({
                eventName: 'customEventName'
              });
              ```

              @method link-to
              @for Ember.Handlebars.helpers
              @param {String} routeName
              @param {Object} [context]*
              @param [options] {Object} Handlebars key/value pairs of options, you can override any property of Ember.LinkView
              @return {String} HTML string
              @see {Ember.LinkView}
            */
        function linkToHelper(name) {
            var options = slice.call(arguments, -1)[0],
            params = slice.call(arguments, 0, -1),
            hash = options.hash;

            Ember.assert("You must provide one or more parameters to the link-to helper.", params.length);

            if (params[params.length - 1] instanceof QueryParams) {
                hash.queryParamsObject = params.pop();
            }

            hash.disabledBinding = hash.disabledWhen;

            if (!options.fn) {
                var linkTitle = params.shift();
                var linkType = options.types.shift();
                var context = this;
                if (linkType === 'ID') {
                    options.linkTextPath = linkTitle;
                    options.fn = function() {
                        return EmberHandlebars.getEscaped(context, linkTitle, options);
                    };
                } else {
                    options.fn = function() {
                        return linkTitle;
                    };
                }
            }

            hash.parameters = {
                context: this,
                options: options,
                params: params
            };

            options.helperName = options.helperName || 'link-to';

            return viewHelper.call(this, LinkView, options);
        }



        EmberHandlebars.registerHelper('query-params', function queryParamsHelper(options) {
            Ember.assert(fmt("The `query-params` helper only accepts hash parameters, e.g. (query-params queryParamPropertyName='%@') as opposed to just (query-params '%@')", [options, options]), arguments.length === 1);

            return QueryParams.create({
                values: options.hash,
                types: options.hashTypes
            });
        });


        /**
              See [link-to](/api/classes/Ember.Handlebars.helpers.html#method_link-to)

              @method linkTo
              @for Ember.Handlebars.helpers
              @deprecated
              @param {String} routeName
              @param {Object} [context]*
              @return {String} HTML string
            */
        function deprecatedLinkToHelper() {
            Ember.warn("The 'linkTo' view helper is deprecated in favor of 'link-to'");
            return linkToHelper.apply(this, arguments);
        }

        function getResolvedQueryParams(linkView, targetRouteName) {
            var helperParameters = linkView.parameters,
            queryParamsObject = linkView.queryParamsObject,
            resolvedQueryParams = {};

            if (!queryParamsObject) {
                return resolvedQueryParams;
            }
            var rawParams = queryParamsObject.values;

            for (var key in rawParams) {
                if (!rawParams.hasOwnProperty(key)) {
                    continue;
                }

                var value = rawParams[key],
                type = queryParamsObject.types[key];

                if (type === 'ID') {
                    var normalizedPath = getNormalizedPath(value, helperParameters);
                    value = EmberHandlebars.get(normalizedPath.root, normalizedPath.path, helperParameters.options);
                }
                resolvedQueryParams[key] = value;
            }
            return resolvedQueryParams;
        }

        function getNormalizedPath(path, helperParameters) {
            return EmberHandlebars.normalizePath(helperParameters.context, path, helperParameters.options.data);
        }

        function paramsAreLoaded(params) {
            for (var i = 0, len = params.length; i < len; ++i) {
                var param = params[i];
                if (param === null || typeof param === 'undefined') {
                    return false;
                }
            }
            return true;
        }

        function shallowEqual(a, b) {
            var k;
            for (k in a) {
                if (a.hasOwnProperty(k) && a[k] !== b[k]) {
                    return false;
                }
            }
            for (k in b) {
                if (b.hasOwnProperty(k) && a[k] !== b[k]) {
                    return false;
                }
            }
            return true;
        }

        __exports__.LinkView = LinkView;
        __exports__.deprecatedLinkToHelper = deprecatedLinkToHelper;
        __exports__.linkToHelper = linkToHelper;
    });
    define("ember-routing-handlebars/helpers/outlet",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/property_set", "ember-runtime/system/lazy_load", "ember-views/views/container_view", "ember-handlebars/views/metamorph_view", "ember-handlebars/helpers/view", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // assert
        var get = __dependency2__.get;
        var set = __dependency3__.set;
        var onLoad = __dependency4__.onLoad;
        var ContainerView = __dependency5__["default"];
        var _Metamorph = __dependency6__._Metamorph;
        var viewHelper = __dependency7__.viewHelper;

        /**
            @module ember
            @submodule ember-routing
            */

        /**
              @module ember
              @submodule ember-routing
              */

        var OutletView = ContainerView.extend(_Metamorph);
        __exports__.OutletView = OutletView;
        /**
              The `outlet` helper is a placeholder that the router will fill in with
              the appropriate template based on the current state of the application.

              ``` handlebars
              {{outlet}}
              ```

              By default, a template based on Ember's naming conventions will be rendered
              into the `outlet` (e.g. `App.PostsRoute` will render the `posts` template).

              You can render a different template by using the `render()` method in the
              route's `renderTemplate` hook. The following will render the `favoritePost`
              template into the `outlet`.

              ``` javascript
              App.PostsRoute = Ember.Route.extend({
                renderTemplate: function() {
                  this.render('favoritePost');
                }
              });
              ```

              You can create custom named outlets for more control.

              ``` handlebars
              {{outlet 'favoritePost'}}
              {{outlet 'posts'}}
              ```

              Then you can define what template is rendered into each outlet in your
              route.


              ``` javascript
              App.PostsRoute = Ember.Route.extend({
                renderTemplate: function() {
                  this.render('favoritePost', { outlet: 'favoritePost' });
                  this.render('posts', { outlet: 'posts' });
                }
              });
              ```

              You can specify the view that the outlet uses to contain and manage the
              templates rendered into it.

              ``` handlebars
              {{outlet view='sectionContainer'}}
              ```

              ``` javascript
              App.SectionContainer = Ember.ContainerView.extend({
                tagName: 'section',
                classNames: ['special']
              });
              ```

              @method outlet
              @for Ember.Handlebars.helpers
              @param {String} property the property on the controller
                that holds the view for this outlet
              @return {String} HTML string
            */
        function outletHelper(property, options) {
            var outletSource;
            var container;
            var viewName;
            var viewClass;
            var viewFullName;

            if (property && property.data && property.data.isRenderData) {
                options = property;
                property = 'main';
            }

            container = options.data.view.container;

            outletSource = options.data.view;
            while (!outletSource.get('template.isTop')) {
                outletSource = outletSource.get('_parentView');
            }

            // provide controller override
            viewName = options.hash.view;

            if (viewName) {
                viewFullName = 'view:' + viewName;
                Ember.assert("Using a quoteless view parameter with {{outlet}} is not supported. Please update to quoted usage '{{outlet \"" + viewName + "\"}}.", options.hashTypes.view !== 'ID');
                Ember.assert("The view name you supplied '" + viewName + "' did not resolve to a view.", container.has(viewFullName));
            }

            viewClass = viewName ? container.lookupFactory(viewFullName) : options.hash.viewClass || OutletView;

            options.data.view.set('outletSource', outletSource);
            options.hash.currentViewBinding = '_view.outletSource._outlets.' + property;

            options.helperName = options.helperName || 'outlet';

            return viewHelper.call(this, viewClass, options);
        }

        __exports__.outletHelper = outletHelper;
    });
    define("ember-routing-handlebars/helpers/render",
    ["ember-metal/core", "ember-metal/error", "ember-metal/property_get", "ember-metal/property_set", "ember-runtime/system/string", "ember-routing/system/generate_controller", "ember-handlebars/ext", "ember-handlebars/helpers/view", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // assert, deprecate
        var EmberError = __dependency2__["default"];
        var get = __dependency3__.get;
        var set = __dependency4__.set;
        var camelize = __dependency5__.camelize;
        var generateControllerFactory = __dependency6__.generateControllerFactory;
        var generateController = __dependency6__["default"];
        var handlebarsGet = __dependency7__.handlebarsGet;
        var viewHelper = __dependency8__.viewHelper;


        /**
            @module ember
            @submodule ember-routing
            */

        /**
              Calling ``{{render}}`` from within a template will insert another
              template that matches the provided name. The inserted template will
              access its properties on its own controller (rather than the controller
              of the parent template).

              If a view class with the same name exists, the view class also will be used.

              Note: A given controller may only be used *once* in your app in this manner.
              A singleton instance of the controller will be created for you.

              Example:

              ```javascript
              App.NavigationController = Ember.Controller.extend({
                who: "world"
              });
              ```

              ```handlebars
              <!-- navigation.hbs -->
              Hello, {{who}}.
              ```

              ```handelbars
              <!-- application.hbs -->
              <h1>My great app</h1>
              {{render "navigation"}}
              ```

              ```html
              <h1>My great app</h1>
              <div class='ember-view'>
                Hello, world.
              </div>
              ```

              Optionally you may provide a second argument: a property path
              that will be bound to the `model` property of the controller.

              If a `model` property path is specified, then a new instance of the
              controller will be created and `{{render}}` can be used multiple times
              with the same name.

             For example if you had this `author` template.

             ```handlebars
            <div class="author">
            Written by {{firstName}} {{lastName}}.
            Total Posts: {{postCount}}
            </div>
            ```

            You could render it inside the `post` template using the `render` helper.

            ```handlebars
            <div class="post">
            <h1>{{title}}</h1>
            <div>{{body}}</div>
            {{render "author" author}}
            </div>
             ```

              @method render
              @for Ember.Handlebars.helpers
              @param {String} name
              @param {Object?} contextString
              @param {Hash} options
              @return {String} HTML string
            */
        __exports__["default"] = function renderHelper(name, contextString, options) {
            var length = arguments.length;

            var contextProvided = length === 3,
            container, router, controller, view, context, lookupOptions;

            container = (options || contextString).data.keywords.controller.container;
            router = container.lookup('router:main');

            if (length === 2) {
                // use the singleton controller
                options = contextString;
                contextString = undefined;
                Ember.assert("You can only use the {{render}} helper once without a model object as its second argument, as in {{render \"post\" post}}.", !router || !router._lookupActiveView(name));
            } else if (length === 3) {
                // create a new controller
                context = handlebarsGet(options.contexts[1], contextString, options);
            } else {
                throw new EmberError("You must pass a templateName to render");
            }

            Ember.deprecate("Using a quoteless parameter with {{render}} is deprecated. Please update to quoted usage '{{render \"" + name + "\"}}.", options.types[0] !== 'ID');

            // # legacy namespace
            name = name.replace(/\//g, '.');
            // \ legacy slash as namespace support


            view = container.lookup('view:' + name) || container.lookup('view:default');

            // provide controller override
            var controllerName = options.hash.controller || name;
            var controllerFullName = 'controller:' + controllerName;

            if (options.hash.controller) {
                Ember.assert("The controller name you supplied '" + controllerName + "' did not resolve to a controller.", container.has(controllerFullName));
            }

            var parentController = options.data.keywords.controller;

            // choose name
            if (length > 2) {
                var factory = container.lookupFactory(controllerFullName) ||
                generateControllerFactory(container, controllerName, context);

                controller = factory.create({
                    model: context,
                    parentController: parentController,
                    target: parentController
                });

                view.one('willDestroyElement', function() {
                    controller.destroy();
                });
            } else {
                controller = container.lookup(controllerFullName) ||
                generateController(container, controllerName);

                controller.setProperties({
                    target: parentController,
                    parentController: parentController
                });
            }

            var root = options.contexts[1];

            if (root) {
                view.registerObserver(root, contextString, function() {
                    controller.set('model', handlebarsGet(root, contextString, options));
                });
            }

            options.hash.viewName = camelize(name);

            var templateName = 'template:' + name;
            Ember.assert("You used `{{render '" + name + "'}}`, but '" + name + "' can not be found as either a template or a view.", container.has("view:" + name) || container.has(templateName) || options.fn);
            options.hash.template = container.lookup(templateName);

            options.hash.controller = controller;

            if (router && !context) {
                router._connectActiveView(name, view);
            }

            options.helperName = options.helperName || ('render "' + name + '"');

            viewHelper.call(this, view, options);
        }
    });
    define("ember-routing-handlebars/helpers/shared",
    ["ember-metal/property_get", "ember-metal/array", "ember-runtime/mixins/controller", "ember-handlebars/ext", "ember-metal/utils", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
        "use strict";
        var get = __dependency1__.get;
        var map = __dependency2__.map;
        var ControllerMixin = __dependency3__["default"];
        var handlebarsResolve = __dependency4__.resolveParams;
        var handlebarsGet = __dependency4__.handlebarsGet;
        var typeOf = __dependency5__.typeOf;
        var get = __dependency1__.get;

        function routeArgs(targetRouteName, models, queryParams) {
            var args = [];
            if (typeOf(targetRouteName) === 'string') {
                args.push('' + targetRouteName);
            }
            args.push.apply(args, models);
            args.push({
                queryParams: queryParams 
            });
            return args;
        }

        __exports__.routeArgs = routeArgs;
        function getActiveTargetName(router) {
            var handlerInfos = router.activeTransition ?
            router.activeTransition.state.handlerInfos :
            router.state.handlerInfos;
            return handlerInfos[handlerInfos.length - 1].name;
        }

        __exports__.getActiveTargetName = getActiveTargetName;
        function resolveParams(context, params, options) {
            return map.call(resolvePaths(context, params, options), function(path, i) {
                if (null === path) {
                    // Param was string/number, not a path, so just return raw string/number.
                    return params[i];
                } else {
                    return handlebarsGet(context, path, options);
                }
            });
        }

        __exports__.resolveParams = resolveParams;
        function stashParamNames(router, handlerInfos) {
            if (handlerInfos._namesStashed) {
                return;
            }

            // This helper exists because router.js/route-recognizer.js awkwardly
            // keeps separate a handlerInfo's list of parameter names depending
            // on whether a URL transition or named transition is happening.
            // Hopefully we can remove this in the future.
            var targetRouteName = handlerInfos[handlerInfos.length-1].name;
            var recogHandlers = router.router.recognizer.handlersFor(targetRouteName);
            var dynamicParent = null;

            for (var i = 0, len = handlerInfos.length; i < len; ++i) {
                var handlerInfo = handlerInfos[i];
                var names = recogHandlers[i].names;

                if (names.length) {
                    dynamicParent = handlerInfo;
                }

                handlerInfo._names = names;

                var route = handlerInfo.handler;
                route._stashNames(handlerInfo, dynamicParent);
            }

            handlerInfos._namesStashed = true;
        }

        __exports__.stashParamNames = stashParamNames;
        function resolvePaths(context, params, options) {
            var resolved = handlebarsResolve(context, params, options),
            types = options.types;

            return map.call(resolved, function(object, i) {
                if (types[i] === 'ID') {
                    return unwrap(object, params[i]);
                } else {
                    return null;
                }
            });

            function unwrap(object, path) {
                if (path === 'controller') {
                    return path;
                }

                if (ControllerMixin.detect(object)) {
                    return unwrap(get(object, 'model'), path ? path + '.model' : 'model');
                } else {
                    return path;
                }
            }
        }

        __exports__.resolvePaths = resolvePaths;
    });
    define("ember-routing",
    ["ember-handlebars", "ember-metal/core", "ember-routing/ext/run_loop", "ember-routing/ext/controller", "ember-routing/ext/view", "ember-routing/location/api", "ember-routing/location/none_location", "ember-routing/location/hash_location", "ember-routing/location/history_location", "ember-routing/location/auto_location", "ember-routing/system/generate_controller", "ember-routing/system/controller_for", "ember-routing/system/dsl", "ember-routing/system/router", "ember-routing/system/route", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __exports__) {
        "use strict";
        /**
            Ember Routing

            @module ember
            @submodule ember-routing
            @requires ember-views
            */

        var EmberHandlebars = __dependency1__["default"];
        var Ember = __dependency2__["default"];

        // ES6TODO: Cleanup modules with side-effects below

        var EmberLocation = __dependency6__["default"];
        var NoneLocation = __dependency7__["default"];
        var HashLocation = __dependency8__["default"];
        var HistoryLocation = __dependency9__["default"];
        var AutoLocation = __dependency10__["default"];

        var generateControllerFactory = __dependency11__.generateControllerFactory;
        var generateController = __dependency11__["default"];
        var controllerFor = __dependency12__["default"];
        var RouterDSL = __dependency13__["default"];
        var Router = __dependency14__["default"];
        var Route = __dependency15__["default"];

        Ember.Location = EmberLocation;
        Ember.AutoLocation = AutoLocation;
        Ember.HashLocation = HashLocation;
        Ember.HistoryLocation = HistoryLocation;
        Ember.NoneLocation = NoneLocation;

        Ember.controllerFor = controllerFor;
        Ember.generateControllerFactory = generateControllerFactory;
        Ember.generateController = generateController;
        Ember.RouterDSL = RouterDSL;
        Ember.Router = Router;
        Ember.Route = Route;

        __exports__["default"] = Ember;
    });
    define("ember-routing/ext/controller",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/computed", "ember-metal/utils", "ember-metal/merge", "ember-metal/enumerable_utils", "ember-runtime/mixins/controller", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // FEATURES, deprecate
        var get = __dependency2__.get;
        var set = __dependency3__.set;
        var computed = __dependency4__.computed;
        var typeOf = __dependency5__.typeOf;
        var meta = __dependency5__.meta;
        var merge = __dependency6__["default"];
        var map = __dependency7__.map;

        var ControllerMixin = __dependency8__["default"];

        /**
            @module ember
            @submodule ember-routing
            */

        ControllerMixin.reopen({
            /**
                    Transition the application into another route. The route may
                    be either a single route or route path:

                    ```javascript
                    aController.transitionToRoute('blogPosts');
                    aController.transitionToRoute('blogPosts.recentEntries');
                    ```

                    Optionally supply a model for the route in question. The model
                    will be serialized into the URL using the `serialize` hook of
                    the route:

                    ```javascript
                    aController.transitionToRoute('blogPost', aPost);
                    ```

                    If a literal is passed (such as a number or a string), it will
                    be treated as an identifier instead. In this case, the `model`
                    hook of the route will be triggered:

                    ```javascript
                    aController.transitionToRoute('blogPost', 1);
                    ```

                    Multiple models will be applied last to first recursively up the
                    resource tree.

                    ```javascript
                    App.Router.map(function() {
                      this.resource('blogPost', {path:':blogPostId'}, function(){
                        this.resource('blogComment', {path: ':blogCommentId'});
                      });
                    });

                    aController.transitionToRoute('blogComment', aPost, aComment);
                    aController.transitionToRoute('blogComment', 1, 13);
                    ```

                    It is also possible to pass a URL (a string that starts with a
                    `/`). This is intended for testing and debugging purposes and
                    should rarely be used in production code.

                    ```javascript
                    aController.transitionToRoute('/');
                    aController.transitionToRoute('/blog/post/1/comment/13');
                    ```

                    See also [replaceRoute](/api/classes/Ember.ControllerMixin.html#method_replaceRoute).

                    @param {String} name the name of the route or a URL
                    @param {...Object} models the model(s) or identifier(s) to be used
                    while transitioning to the route.
                    @for Ember.ControllerMixin
                    @method transitionToRoute
                  */
            transitionToRoute: function() {
                // target may be either another controller or a router
                var target = get(this, 'target');
                var method = target.transitionToRoute || target.transitionTo;
                return method.apply(target, arguments);
            },

            /**
                    @deprecated
                    @for Ember.ControllerMixin
                    @method transitionTo
                  */
            transitionTo: function() {
                Ember.deprecate("transitionTo is deprecated. Please use transitionToRoute.");
                return this.transitionToRoute.apply(this, arguments);
            },

            /**
                    Transition into another route while replacing the current URL, if possible.
                    This will replace the current history entry instead of adding a new one.
                    Beside that, it is identical to `transitionToRoute` in all other respects.

                    ```javascript
                    aController.replaceRoute('blogPosts');
                    aController.replaceRoute('blogPosts.recentEntries');
                    ```

                    Optionally supply a model for the route in question. The model
                    will be serialized into the URL using the `serialize` hook of
                    the route:

                    ```javascript
                    aController.replaceRoute('blogPost', aPost);
                    ```

                    If a literal is passed (such as a number or a string), it will
                    be treated as an identifier instead. In this case, the `model`
                    hook of the route will be triggered:

                    ```javascript
                    aController.replaceRoute('blogPost', 1);
                    ```

                    Multiple models will be applied last to first recursively up the
                    resource tree.

                    ```javascript
                    App.Router.map(function() {
                      this.resource('blogPost', {path:':blogPostId'}, function(){
                        this.resource('blogComment', {path: ':blogCommentId'});
                      });
                    });

                    aController.replaceRoute('blogComment', aPost, aComment);
                    aController.replaceRoute('blogComment', 1, 13);
                    ```

                    It is also possible to pass a URL (a string that starts with a
                    `/`). This is intended for testing and debugging purposes and
                    should rarely be used in production code.

                    ```javascript
                    aController.replaceRoute('/');
                    aController.replaceRoute('/blog/post/1/comment/13');
                    ```

                    @param {String} name the name of the route or a URL
                    @param {...Object} models the model(s) or identifier(s) to be used
                    while transitioning to the route.
                    @for Ember.ControllerMixin
                    @method replaceRoute
                  */
            replaceRoute: function() {
                // target may be either another controller or a router
                var target = get(this, 'target');
                var method = target.replaceRoute || target.replaceWith;
                return method.apply(target, arguments);
            },

            /**
                    @deprecated
                    @for Ember.ControllerMixin
                    @method replaceWith
                  */
            replaceWith: function() {
                Ember.deprecate("replaceWith is deprecated. Please use replaceRoute.");
                return this.replaceRoute.apply(this, arguments);
            }
        });

        var ALL_PERIODS_REGEX = /\./g;


        ControllerMixin.reopen({
            init: function() {
                this._super.apply(this, arguments);
                listenForQueryParamChanges(this);
            },

            concatenatedProperties: ['queryParams', '_pCacheMeta'],
            queryParams: null,

            _qpDelegate: null,
            _normalizedQueryParams: computed(function() {
                var m = meta(this);
                if (m.proto !== this) {
                    return get(m.proto, '_normalizedQueryParams');
                }

                var queryParams = this.queryParams;
                if (queryParams._qpMap) {
                    return queryParams._qpMap;
                }

                var qpMap = queryParams._qpMap = {};

                for (var i = 0, len = queryParams.length; i < len; ++i) {
                    accumulateQueryParamDescriptors(queryParams[i], qpMap);
                }

                return qpMap;
            }),

            _cacheMeta: computed(function() {
                var m = meta(this);
                if (m.proto !== this) {
                    return get(m.proto, '_cacheMeta');
                }

                var cacheMeta = {};
                var qpMap = get(this, '_normalizedQueryParams');
                for (var prop in qpMap) {
                    if (!qpMap.hasOwnProperty(prop)) {
                        continue;
                    }

                    var qp = qpMap[prop];
                    var scope = qp.scope;
                    var parts;

                    if (scope === 'controller') {
                        parts = [];
                    }

                    cacheMeta[prop] = {
                        parts: parts,
                        // provided by route if 'model' scope
                        values: null,
                        // provided by route
                        scope: scope,
                        prefix: "",
                        def: get(this, prop)
                    };
                }

                return cacheMeta;
            }),

            _updateCacheParams: function(params) {
                var cacheMeta = get(this, '_cacheMeta');
                for (var prop in cacheMeta) {
                    if (!cacheMeta.hasOwnProperty(prop)) {
                        continue;
                    }
                    var propMeta = cacheMeta[prop];
                    propMeta.values = params;

                    var cacheKey = this._calculateCacheKey(propMeta.prefix, propMeta.parts, propMeta.values);
                    var cache = this._bucketCache;
                    var value = cache.lookup(cacheKey, prop, propMeta.def);

                    set(this, prop, value);
                }
            },

            _qpChanged: function(controller, _prop) {
                var prop = _prop.substr(0, _prop.length-3);
                var cacheMeta = get(controller, '_cacheMeta');
                var propCache = cacheMeta[prop];
                var cacheKey = controller._calculateCacheKey(propCache.prefix || "", propCache.parts, propCache.values);
                var value = get(controller, prop);

                // 1. Update model-dep cache
                controller._bucketCache.stash(cacheKey, prop, value);

                // 2. Notify a delegate (e.g. to fire a qp transition)
                var delegate = controller._qpDelegate;
                if (delegate) {
                    delegate(controller, prop);
                }
            },

            _calculateCacheKey: function(prefix, _parts, values) {
                var parts = _parts || [], suffixes = "";
                for (var i = 0, len = parts.length; i < len; ++i) {
                    var part = parts[i];
                    var value = get(values, part);
                    suffixes += "::" + part + ":" + value;
                }
                return prefix + suffixes.replace(ALL_PERIODS_REGEX, '-');
            }
        });


        function accumulateQueryParamDescriptors(_desc, accum) {
            var desc = _desc, tmp;
            if (typeOf(desc) === 'string') {
                tmp = {};
                tmp[desc] = {
                    as: null 
                };
                desc = tmp;
            }

            for (var key in desc) {
                if (!desc.hasOwnProperty(key)) {
                    return;
                }

                var singleDesc = desc[key];
                if (typeOf(singleDesc) === 'string') {
                    singleDesc = {
                        as: singleDesc 
                    };
                }

                tmp = accum[key] || {
                    as: null,
                    scope: 'model' 
                };
                merge(tmp, singleDesc);

                accum[key] = tmp;
            }
        }

        function listenForQueryParamChanges(controller) {
            var qpMap = get(controller, '_normalizedQueryParams');
            for (var prop in qpMap) {
                if (!qpMap.hasOwnProperty(prop)) {
                    continue;
                }
                controller.addObserver(prop + '.[]', controller, controller._qpChanged);
            }
        }


        __exports__["default"] = ControllerMixin;
    });
    define("ember-routing/ext/run_loop",
    ["ember-metal/run_loop"],
    function(__dependency1__) {
        "use strict";
        var run = __dependency1__["default"];

        /**
            @module ember
            @submodule ember-views
            */

        // Add a new named queue after the 'actions' queue (where RSVP promises
        // resolve), which is used in router transitions to prevent unnecessary
        // loading state entry if all context promises resolve on the
        // 'actions' queue first.

        var queues = run.queues;
        run._addQueue('routerTransitions', 'actions');
    });
    define("ember-routing/ext/view",
    ["ember-metal/property_get", "ember-metal/property_set", "ember-metal/run_loop", "ember-views/views/view", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
        "use strict";
        var get = __dependency1__.get;
        var set = __dependency2__.set;
        var run = __dependency3__["default"];
        var EmberView = __dependency4__["default"];

        /**
            @module ember
            @submodule ember-routing
            */

        EmberView.reopen({

            /**
                    Sets the private `_outlets` object on the view.

                    @method init
                   */
            init: function() {
                set(this, '_outlets', {});
                this._super();
            },

            /**
                    Manually fill any of a view's `{{outlet}}` areas with the
                    supplied view.

                    Example

                    ```javascript
                    var MyView = Ember.View.extend({
                      template: Ember.Handlebars.compile('Child view: {{outlet "main"}} ')
                    });
                    var myView = MyView.create();
                    myView.appendTo('body');
                    // The html for myView now looks like:
                    // <div id="ember228" class="ember-view">Child view: </div>

                    var FooView = Ember.View.extend({
                      template: Ember.Handlebars.compile('<h1>Foo</h1> ')
                    });
                    var fooView = FooView.create();
                    myView.connectOutlet('main', fooView);
                    // The html for myView now looks like:
                    // <div id="ember228" class="ember-view">Child view:
                    //   <div id="ember234" class="ember-view"><h1>Foo</h1> </div>
                    // </div>
                    ```
                    @method connectOutlet
                    @param  {String} outletName A unique name for the outlet
                    @param  {Object} view       An Ember.View
                   */
            connectOutlet: function(outletName, view) {
                if (this._pendingDisconnections) {
                    delete this._pendingDisconnections[outletName];
                }

                if (this._hasEquivalentView(outletName, view)) {
                    view.destroy();
                    return;
                }

                var outlets = get(this, '_outlets');
                var container = get(this, 'container');
                var router = container && container.lookup('router:main');
                var renderedName = get(view, 'renderedName');

                set(outlets, outletName, view);

                if (router && renderedName) {
                    router._connectActiveView(renderedName, view);
                }
            },

            /**
                    Determines if the view has already been created by checking if
                    the view has the same constructor, template, and context as the
                    view in the `_outlets` object.

                    @private
                    @method _hasEquivalentView
                    @param  {String} outletName The name of the outlet we are checking
                    @param  {Object} view       An Ember.View
                    @return {Boolean}
                   */
            _hasEquivalentView: function(outletName, view) {
                var existingView = get(this, '_outlets.' + outletName);
                return existingView &&
                existingView.constructor === view.constructor &&
                existingView.get('template') === view.get('template') &&
                existingView.get('context') === view.get('context');
            },

            /**
                    Removes an outlet from the view.

                    Example

                    ```javascript
                    var MyView = Ember.View.extend({
                      template: Ember.Handlebars.compile('Child view: {{outlet "main"}} ')
                    });
                    var myView = MyView.create();
                    myView.appendTo('body');
                    // myView's html:
                    // <div id="ember228" class="ember-view">Child view: </div>

                    var FooView = Ember.View.extend({
                      template: Ember.Handlebars.compile('<h1>Foo</h1> ')
                    });
                    var fooView = FooView.create();
                    myView.connectOutlet('main', fooView);
                    // myView's html:
                    // <div id="ember228" class="ember-view">Child view:
                    //   <div id="ember234" class="ember-view"><h1>Foo</h1> </div>
                    // </div>

                    myView.disconnectOutlet('main');
                    // myView's html:
                    // <div id="ember228" class="ember-view">Child view: </div>
                    ```

                    @method disconnectOutlet
                    @param  {String} outletName The name of the outlet to be removed
                   */
            disconnectOutlet: function(outletName) {
                if (!this._pendingDisconnections) {
                    this._pendingDisconnections = {};
                }
                this._pendingDisconnections[outletName] = true;
                run.once(this, '_finishDisconnections');
            },

            /**
                    Gets an outlet that is pending disconnection and then
                    nullifys the object on the `_outlet` object.

                    @private
                    @method _finishDisconnections
                   */
            _finishDisconnections: function() {
                if (this.isDestroyed) 
                    return; // _outlets will be gone anyway
                var outlets = get(this, '_outlets');
                var pendingDisconnections = this._pendingDisconnections;
                this._pendingDisconnections = null;

                for (var outletName in pendingDisconnections) {
                    set(outlets, outletName, null);
                }
            }
        });

        __exports__["default"] = EmberView;
    });
    define("ember-routing/location/api",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/property_set", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // deprecate, assert
        var get = __dependency2__.get;
        var set = __dependency3__.set;

        /**
            @module ember
            @submodule ember-routing
            */

        /**
              Ember.Location returns an instance of the correct implementation of
              the `location` API.

              ## Implementations

              You can pass an implementation name (`hash`, `history`, `none`) to force a
              particular implementation to be used in your application.

              ### HashLocation

              Using `HashLocation` results in URLs with a `#` (hash sign) separating the
              server side URL portion of the URL from the portion that is used by Ember.
              This relies upon the `hashchange` event existing in the browser.

              Example:

              ```javascript
              App.Router.map(function() {
                this.resource('posts', function() {
                  this.route('new');
                });
              });

              App.Router.reopen({
                location: 'hash'
              });
              ```

              This will result in a posts.new url of `/#/posts/new`.

              ### HistoryLocation

              Using `HistoryLocation` results in URLs that are indistinguishable from a
              standard URL. This relies upon the browser's `history` API.

              Example:

              ```javascript
              App.Router.map(function() {
                this.resource('posts', function() {
                  this.route('new');
                });
              });

              App.Router.reopen({
                location: 'history'
              });
              ```

              This will result in a posts.new url of `/posts/new`.

              Keep in mind that your server must serve the Ember app at all the routes you
              define.

              ### AutoLocation

              Using `AutoLocation`, the router will use the best Location class supported by
              the browser it is running in.

              Browsers that support the `history` API will use `HistoryLocation`, those that
              do not, but still support the `hashchange` event will use `HashLocation`, and
              in the rare case neither is supported will use `NoneLocation`.

              Example:

              ```javascript
              App.Router.map(function() {
                this.resource('posts', function() {
                  this.route('new');
                });
              });

              App.Router.reopen({
                location: 'auto'
              });
              ```

              This will result in a posts.new url of `/posts/new` for modern browsers that
              support the `history` api or `/#/posts/new` for older ones, like Internet
              Explorer 9 and below.

              When a user visits a link to your application, they will be automatically
              upgraded or downgraded to the appropriate `Location` class, with the URL
              transformed accordingly, if needed.

              Keep in mind that since some of your users will use `HistoryLocation`, your
              server must serve the Ember app at all the routes you define.

              ### NoneLocation

              Using `NoneLocation` causes Ember to not store the applications URL state
              in the actual URL. This is generally used for testing purposes, and is one
              of the changes made when calling `App.setupForTesting()`.

              ## Location API

              Each location implementation must provide the following methods:

              * implementation: returns the string name used to reference the implementation.
              * getURL: returns the current URL.
              * setURL(path): sets the current URL.
              * replaceURL(path): replace the current URL (optional).
              * onUpdateURL(callback): triggers the callback when the URL changes.
              * formatURL(url): formats `url` to be placed into `href` attribute.

              Calling setURL or replaceURL will not trigger onUpdateURL callbacks.

              @class Location
              @namespace Ember
              @static
            */
        __exports__["default"] = {
            /**
                   This is deprecated in favor of using the container to lookup the location
                   implementation as desired.

                   For example:

                   ```javascript
                   // Given a location registered as follows:
                   container.register('location:history-test', HistoryTestLocation);

                   // You could create a new instance via:
                   container.lookup('location:history-test');
                   ```

                    @method create
                    @param {Object} options
                    @return {Object} an instance of an implementation of the `location` API
                    @deprecated Use the container to lookup the location implementation that you
                    need.
                  */
            create: function(options) {
                var implementation = options && options.implementation;
                Ember.assert("Ember.Location.create: you must specify a 'implementation' option", !!implementation);

                var implementationClass = this.implementations[implementation];
                Ember.assert("Ember.Location.create: " + implementation + " is not a valid implementation", !!implementationClass);

                return implementationClass.create.apply(implementationClass, arguments);
            },

            /**
                   This is deprecated in favor of using the container to register the
                   location implementation as desired.

                   Example:

                   ```javascript
                   Application.initializer({
                    name: "history-test-location",

                    initialize: function(container, application) {
                      application.register('location:history-test', HistoryTestLocation);
                    }
                   });
                   ```

                   @method registerImplementation
                   @param {String} name
                   @param {Object} implementation of the `location` API
                   @deprecated Register your custom location implementation with the
                   container directly.
                  */
            registerImplementation: function(name, implementation) {
                Ember.deprecate('Using the Ember.Location.registerImplementation is no longer supported. Register your custom location implementation with the container instead.', false);

                this.implementations[name] = implementation;
            },

            implementations: {},
            _location: window.location,

            /**
                    Returns the current `location.hash` by parsing location.href since browsers
                    inconsistently URL-decode `location.hash`.

                    https://bugzilla.mozilla.org/show_bug.cgi?id=483304

                    @private
                    @method getHash
                    @since 1.4.0
                  */
            _getHash: function () {
                // AutoLocation has it at _location, HashLocation at .location.
                // Being nice and not changing
                var href = (this._location || this.location).href;
                var hashIndex = href.indexOf('#');

                if (hashIndex === -1) {
                    return '';
                } else {
                    return href.substr(hashIndex);
                }
            }
        };
    });
    define("ember-routing/location/auto_location",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/property_set", "ember-routing/location/api", "ember-routing/location/history_location", "ember-routing/location/hash_location", "ember-routing/location/none_location", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // FEATURES
        var get = __dependency2__.get;
        var set = __dependency3__.set;

        var EmberLocation = __dependency4__["default"];
        var HistoryLocation = __dependency5__["default"];
        var HashLocation = __dependency6__["default"];
        var NoneLocation = __dependency7__["default"];

        /**
            @module ember
            @submodule ember-routing
            */

        /**
              Ember.AutoLocation will select the best location option based off browser
              support with the priority order: history, hash, none.

              Clean pushState paths accessed by hashchange-only browsers will be redirected
              to the hash-equivalent and vice versa so future transitions are consistent.

              Keep in mind that since some of your users will use `HistoryLocation`, your
              server must serve the Ember app at all the routes you define.

              @class AutoLocation
              @namespace Ember
              @static
            */
        __exports__["default"] = {

            /**
                    @private

                    This property is used by router:main to know whether to cancel the routing
                    setup process, which is needed while we redirect the browser.

                    @since 1.5.1
                    @property cancelRouterSetup
                    @default false
                  */
            cancelRouterSetup: false,

            /**
                    @private

                    Will be pre-pended to path upon state change.

                    @since 1.5.1
                    @property rootURL
                    @default '/'
                  */
            rootURL: '/',

            /**
                    @private

                    Attached for mocking in tests

                    @since 1.5.1
                    @property _window
                    @default window
                  */
            _window: window,

            /**
                    @private

                    Attached for mocking in tests

                    @property location
                    @default window.location
                  */
            _location: window.location,

            /**
                    @private

                    Attached for mocking in tests

                    @since 1.5.1
                    @property _history
                    @default window.history
                  */
            _history: window.history,

            /**
                    @private

                    Attached for mocking in tests

                    @since 1.5.1
                    @property _HistoryLocation
                    @default Ember.HistoryLocation
                  */
            _HistoryLocation: HistoryLocation,

            /**
                    @private

                    Attached for mocking in tests

                    @since 1.5.1
                    @property _HashLocation
                    @default Ember.HashLocation
                  */
            _HashLocation: HashLocation,

            /**
                    @private

                    Attached for mocking in tests

                    @since 1.5.1
                    @property _NoneLocation
                    @default Ember.NoneLocation
                  */
            _NoneLocation: NoneLocation,

            /**
                    @private

                    Returns location.origin or builds it if device doesn't support it.

                    @method _getOrigin
                  */
            _getOrigin: function () {
                var location = this._location;
                var origin = location.origin;

                // Older browsers, especially IE, don't have origin
                if (!origin) {
                    origin = location.protocol + '//' + location.hostname;

                    if (location.port) {
                        origin += ':' + location.port;
                    }
                }

                return origin;
            },

            /**
                    @private

                    We assume that if the history object has a pushState method, the host should
                    support HistoryLocation.

                    @method _getSupportsHistory
                  */
            _getSupportsHistory: function () {
                // Boosted from Modernizr: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/history.js
                // The stock browser on Android 2.2 & 2.3 returns positive on history support
                // Unfortunately support is really buggy and there is no clean way to detect
                // these bugs, so we fall back to a user agent sniff :(
                var userAgent = this._window.navigator.userAgent;

                // We only want Android 2, stock browser, and not Chrome which identifies
                // itself as 'Mobile Safari' as well
                if (userAgent.indexOf('Android 2') !== -1 &&
                userAgent.indexOf('Mobile Safari') !== -1 &&
                userAgent.indexOf('Chrome') === -1) {
                    return false;
                }

                return !!(this._history && 'pushState' in this._history);
            },

            /**
                    @private

                    IE8 running in IE7 compatibility mode gives false positive, so we must also
                    check documentMode.

                    @method _getSupportsHashChange
                  */
            _getSupportsHashChange: function () {
                var _window = this._window;
                var documentMode = _window.document.documentMode;

                return ('onhashchange' in _window && (documentMode === undefined || documentMode > 7 ));
            },

            /**
                    @private

                    Redirects the browser using location.replace, prepending the locatin.origin
                    to prevent phishing attempts

                    @method _replacePath
                  */
            _replacePath: function (path) {
                this._location.replace(this._getOrigin() + path);
            },

            /**
                    @since 1.5.1
                    @private
                    @method _getRootURL
                  */
            _getRootURL: function () {
                return this.rootURL;
            },

            /**
                    @private

                    Returns the current `location.pathname`, normalized for IE inconsistencies.

                    @method _getPath
                  */
            _getPath: function () {
                var pathname = this._location.pathname;
                // Various versions of IE/Opera don't always return a leading slash
                if (pathname.charAt(0) !== '/') {
                    pathname = '/' + pathname;
                }

                return pathname;
            },

            /**
                    @private

                    Returns normalized location.hash as an alias to Ember.Location._getHash

                    @since 1.5.1
                    @method _getHash
                  */
            _getHash: EmberLocation._getHash,

            /**
                    @private

                    Returns location.search

                    @since 1.5.1
                    @method _getQuery
                  */
            _getQuery: function () {
                return this._location.search;
            },

            /**
                    @private

                    Returns the full pathname including query and hash

                    @method _getFullPath
                  */
            _getFullPath: function () {
                return this._getPath() + this._getQuery() + this._getHash();
            },

            /**
                    @private

                    Returns the current path as it should appear for HistoryLocation supported
                    browsers. This may very well differ from the real current path (e.g. if it
                    starts off as a hashed URL)

                    @method _getHistoryPath
                  */
            _getHistoryPath: function () {
                var rootURL = this._getRootURL();
                var path = this._getPath();
                var hash = this._getHash();
                var query = this._getQuery();
                var rootURLIndex = path.indexOf(rootURL);
                var routeHash, hashParts;

                Ember.assert('Path ' + path + ' does not start with the provided rootURL ' + rootURL, rootURLIndex === 0);

                // By convention, Ember.js routes using HashLocation are required to start
                // with `#/`. Anything else should NOT be considered a route and should
                // be passed straight through, without transformation.
                if (hash.substr(0, 2) === '#/') {
                    // There could be extra hash segments after the route
                    hashParts = hash.substr(1).split('#');
                    // The first one is always the route url
                    routeHash = hashParts.shift();

                    // If the path already has a trailing slash, remove the one
                    // from the hashed route so we don't double up.
                    if (path.slice(-1) === '/') {
                        routeHash = routeHash.substr(1);
                    }

                    // This is the "expected" final order
                    path += routeHash;
                    path += query;

                    if (hashParts.length) {
                        path += '#' + hashParts.join('#');
                    }
                } else {
                    path += query;
                    path += hash;
                }

                return path;
            },

            /**
                    @private

                    Returns the current path as it should appear for HashLocation supported
                    browsers. This may very well differ from the real current path.

                    @method _getHashPath
                  */
            _getHashPath: function () {
                var rootURL = this._getRootURL();
                var path = rootURL;
                var historyPath = this._getHistoryPath();
                var routePath = historyPath.substr(rootURL.length);

                if (routePath !== '') {
                    if (routePath.charAt(0) !== '/') {
                        routePath = '/' + routePath;
                    }

                    path += '#' + routePath;
                }

                return path;
            },

            /**
                    Selects the best location option based off browser support and returns an
                    instance of that Location class.

                    @see Ember.AutoLocation
                    @method create
                  */
            create: function (options) {
                if (options && options.rootURL) {
                    Ember.assert('rootURL must end with a trailing forward slash e.g. "/app/"', options.rootURL.charAt(options.rootURL.length-1) === '/');
                    this.rootURL = options.rootURL;
                }

                var historyPath, hashPath;
                var cancelRouterSetup = false;
                var implementationClass = this._NoneLocation;
                var currentPath = this._getFullPath();

                if (this._getSupportsHistory()) {
                    historyPath = this._getHistoryPath();

                    // Since we support history paths, let's be sure we're using them else
                    // switch the location over to it.
                    if (currentPath === historyPath) {
                        implementationClass = this._HistoryLocation;
                    } else {
                        cancelRouterSetup = true;
                        this._replacePath(historyPath);
                    }

                } else if (this._getSupportsHashChange()) {
                    hashPath = this._getHashPath();

                    // Be sure we're using a hashed path, otherwise let's switch over it to so
                    // we start off clean and consistent. We'll count an index path with no
                    // hash as "good enough" as well.
                    if (currentPath === hashPath || (currentPath === '/' && hashPath === '/#/')) {
                        implementationClass = this._HashLocation;
                    } else {
                        // Our URL isn't in the expected hash-supported format, so we want to
                        // cancel the router setup and replace the URL to start off clean
                        cancelRouterSetup = true;
                        this._replacePath(hashPath);
                    }
                }

                var implementation = implementationClass.create.apply(implementationClass, arguments);

                if (cancelRouterSetup) {
                    set(implementation, 'cancelRouterSetup', true);
                }

                return implementation;
            }
        };
    });
    define("ember-routing/location/hash_location",
    ["ember-metal/property_get", "ember-metal/property_set", "ember-metal/run_loop", "ember-metal/utils", "ember-runtime/system/object", "ember-routing/location/api", "ember-views/system/jquery", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
        "use strict";
        var get = __dependency1__.get;
        var set = __dependency2__.set;
        var run = __dependency3__["default"];
        var guidFor = __dependency4__.guidFor;

        var EmberObject = __dependency5__["default"];
        var EmberLocation = __dependency6__["default"];
        var jQuery = __dependency7__["default"];

        /**
            @module ember
            @submodule ember-routing
            */

        /**
              `Ember.HashLocation` implements the location API using the browser's
              hash. At present, it relies on a `hashchange` event existing in the
              browser.

              @class HashLocation
              @namespace Ember
              @extends Ember.Object
            */
        __exports__["default"] = EmberObject.extend({
            implementation: 'hash',

            init: function() {
                set(this, 'location', get(this, '_location') || window.location);
            },

            /**
                    @private

                    Returns normalized location.hash

                    @since 1.5.1
                    @method getHash
                  */
            getHash: EmberLocation._getHash,

            /**
                    Returns the current `location.hash`, minus the '#' at the front.

                    @private
                    @method getURL
                  */
            getURL: function() {
                return this.getHash().substr(1);
            },

            /**
                    Set the `location.hash` and remembers what was set. This prevents
                    `onUpdateURL` callbacks from triggering when the hash was set by
                    `HashLocation`.

                    @private
                    @method setURL
                    @param path {String}
                  */
            setURL: function(path) {
                get(this, 'location').hash = path;
                set(this, 'lastSetURL', path);
            },

            /**
                    Uses location.replace to update the url without a page reload
                    or history modification.

                    @private
                    @method replaceURL
                    @param path {String}
                  */
            replaceURL: function(path) {
                get(this, 'location').replace('#' + path);
                set(this, 'lastSetURL', path);
            },

            /**
                    Register a callback to be invoked when the hash changes. These
                    callbacks will execute when the user presses the back or forward
                    button, but not after `setURL` is invoked.

                    @private
                    @method onUpdateURL
                    @param callback {Function}
                  */
            onUpdateURL: function(callback) {
                var self = this;
                var guid = guidFor(this);

                jQuery(window).on('hashchange.ember-location-' + guid, function() {
                    run(function() {
                        var path = self.getURL();
                        if (get(self, 'lastSetURL') === path) {
                            return;
                        }

                        set(self, 'lastSetURL', null);

                        callback(path);
                    });
                });
            },

            /**
                    Given a URL, formats it to be placed into the page as part
                    of an element's `href` attribute.

                    This is used, for example, when using the {{action}} helper
                    to generate a URL based on an event.

                    @private
                    @method formatURL
                    @param url {String}
                  */
            formatURL: function(url) {
                return '#' + url;
            },

            /**
                    Cleans up the HashLocation event listener.

                    @private
                    @method willDestroy
                  */
            willDestroy: function() {
                var guid = guidFor(this);

                jQuery(window).off('hashchange.ember-location-' + guid);
            }
        });
    });
    define("ember-routing/location/history_location",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/utils", "ember-runtime/system/object", "ember-views/system/jquery", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // FEATURES
        var get = __dependency2__.get;
        var set = __dependency3__.set;
        var guidFor = __dependency4__.guidFor;

        var EmberObject = __dependency5__["default"];
        var jQuery = __dependency6__["default"];

        /**
            @module ember
            @submodule ember-routing
            */

        var popstateFired = false;
        var supportsHistoryState = window.history && 'state' in window.history;

        /**
              Ember.HistoryLocation implements the location API using the browser's
              history.pushState API.

              @class HistoryLocation
              @namespace Ember
              @extends Ember.Object
            */
        __exports__["default"] = EmberObject.extend({
            implementation: 'history',

            init: function() {
                set(this, 'location', get(this, 'location') || window.location);
                set(this, 'baseURL', jQuery('base').attr('href') || '');
            },

            /**
                    Used to set state on first call to setURL

                    @private
                    @method initState
                  */
            initState: function() {
                set(this, 'history', get(this, 'history') || window.history);
                this.replaceState(this.formatURL(this.getURL()));
            },

            /**
                    Will be pre-pended to path upon state change

                    @property rootURL
                    @default '/'
                  */
            rootURL: '/',

            /**
                    Returns the current `location.pathname` without `rootURL` or `baseURL`

                    @private
                    @method getURL
                    @return url {String}
                  */
            getURL: function() {
                var rootURL = get(this, 'rootURL');
                var location = get(this, 'location');
                var path = location.pathname;
                var baseURL = get(this, 'baseURL');

                rootURL = rootURL.replace(/\/$/, '');
                baseURL = baseURL.replace(/\/$/, '');

                var url = path.replace(baseURL, '').replace(rootURL, '');


                var search = location.search || '';
                url += search;


                return url;
            },

            /**
                    Uses `history.pushState` to update the url without a page reload.

                    @private
                    @method setURL
                    @param path {String}
                  */
            setURL: function(path) {
                var state = this.getState();
                path = this.formatURL(path);

                if (!state || state.path !== path) {
                    this.pushState(path);
                }
            },

            /**
                    Uses `history.replaceState` to update the url without a page reload
                    or history modification.

                    @private
                    @method replaceURL
                    @param path {String}
                  */
            replaceURL: function(path) {
                var state = this.getState();
                path = this.formatURL(path);

                if (!state || state.path !== path) {
                    this.replaceState(path);
                }
            },

            /**
                   Get the current `history.state`. Checks for if a polyfill is
                   required and if so fetches this._historyState. The state returned
                   from getState may be null if an iframe has changed a window's
                   history.

                   @private
                   @method getState
                   @return state {Object}
                  */
            getState: function() {
                return supportsHistoryState ? get(this, 'history').state : this._historyState;
            },

            /**
                   Pushes a new state.

                   @private
                   @method pushState
                   @param path {String}
                  */
            pushState: function(path) {
                var state = {
                    path: path 
                };

                get(this, 'history').pushState(state, null, path);

                // store state if browser doesn't support `history.state`
                if (!supportsHistoryState) {
                    this._historyState = state;
                }

                // used for webkit workaround
                this._previousURL = this.getURL();
            },

            /**
                   Replaces the current state.

                   @private
                   @method replaceState
                   @param path {String}
                  */
            replaceState: function(path) {
                var state = {
                    path: path 
                };

                get(this, 'history').replaceState(state, null, path);

                // store state if browser doesn't support `history.state`
                if (!supportsHistoryState) {
                    this._historyState = state;
                }

                // used for webkit workaround
                this._previousURL = this.getURL();
            },

            /**
                    Register a callback to be invoked whenever the browser
                    history changes, including using forward and back buttons.

                    @private
                    @method onUpdateURL
                    @param callback {Function}
                  */
            onUpdateURL: function(callback) {
                var guid = guidFor(this);
                var self = this;

                jQuery(window).on('popstate.ember-location-' + guid, function(e) {
                    // Ignore initial page load popstate event in Chrome
                    if (!popstateFired) {
                        popstateFired = true;
                        if (self.getURL() === self._previousURL) {
                            return;
                        }
                    }
                    callback(self.getURL());
                });
            },

            /**
                    Used when using `{{action}}` helper.  The url is always appended to the rootURL.

                    @private
                    @method formatURL
                    @param url {String}
                    @return formatted url {String}
                  */
            formatURL: function(url) {
                var rootURL = get(this, 'rootURL');
                var baseURL = get(this, 'baseURL');

                if (url !== '') {
                    rootURL = rootURL.replace(/\/$/, '');
                    baseURL = baseURL.replace(/\/$/, '');
                } else if (baseURL.match(/^\//) && rootURL.match(/^\//)) {
                    baseURL = baseURL.replace(/\/$/, '');
                }

                return baseURL + rootURL + url;
            },

            /**
                    Cleans up the HistoryLocation event listener.

                    @private
                    @method willDestroy
                  */
            willDestroy: function() {
                var guid = guidFor(this);

                jQuery(window).off('popstate.ember-location-' + guid);
            }
        });
    });
    define("ember-routing/location/none_location",
    ["ember-metal/property_get", "ember-metal/property_set", "ember-runtime/system/object", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        var get = __dependency1__.get;
        var set = __dependency2__.set;
        var EmberObject = __dependency3__["default"];

        /**
            @module ember
            @submodule ember-routing
            */

        /**
              Ember.NoneLocation does not interact with the browser. It is useful for
              testing, or when you need to manage state with your Router, but temporarily
              don't want it to muck with the URL (for example when you embed your
              application in a larger page).

              @class NoneLocation
              @namespace Ember
              @extends Ember.Object
            */
        __exports__["default"] = EmberObject.extend({
            implementation: 'none',
            path: '',

            /**
                    Returns the current path.

                    @private
                    @method getURL
                    @return {String} path
                  */
            getURL: function() {
                return get(this, 'path');
            },

            /**
                    Set the path and remembers what was set. Using this method
                    to change the path will not invoke the `updateURL` callback.

                    @private
                    @method setURL
                    @param path {String}
                  */
            setURL: function(path) {
                set(this, 'path', path);
            },

            /**
                    Register a callback to be invoked when the path changes. These
                    callbacks will execute when the user presses the back or forward
                    button, but not after `setURL` is invoked.

                    @private
                    @method onUpdateURL
                    @param callback {Function}
                  */
            onUpdateURL: function(callback) {
                this.updateCallback = callback;
            },

            /**
                    Sets the path and calls the `updateURL` callback.

                    @private
                    @method handleURL
                    @param callback {Function}
                  */
            handleURL: function(url) {
                set(this, 'path', url);
                this.updateCallback(url);
            },

            /**
                    Given a URL, formats it to be placed into the page as part
                    of an element's `href` attribute.

                    This is used, for example, when using the {{action}} helper
                    to generate a URL based on an event.

                    @private
                    @method formatURL
                    @param url {String}
                    @return {String} url
                  */
            formatURL: function(url) {
                // The return value is not overly meaningful, but we do not want to throw
                // errors when test code renders templates containing {{action href=true}}
                // helpers.
                return url;
            }
        });
    });
    define("ember-routing/system/cache",
    ["ember-runtime/system/object", "exports"],
    function(__dependency1__, __exports__) {
        "use strict";
        var EmberObject = __dependency1__["default"];

        __exports__["default"] = EmberObject.extend({
            init: function() {
                this.cache = {};
            },
            has: function(bucketKey) {
                return bucketKey in this.cache;
            },
            stash: function(bucketKey, key, value) {
                var bucket = this.cache[bucketKey];
                if (!bucket) {
                    bucket = this.cache[bucketKey] = {};
                }
                bucket[key] = value;
            },
            lookup: function(bucketKey, prop, defaultValue) {
                var cache = this.cache;
                if (!(bucketKey in cache)) {
                    return defaultValue;
                }
                var bucket = cache[bucketKey];
                if (prop in bucket) {
                    return bucket[prop];
                } else {
                    return defaultValue;
                }
            },
            cache: null
        });
    });
    define("ember-routing/system/controller_for",
    ["exports"],
    function(__exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-routing
            */

        /**

              Finds a controller instance.

              @for Ember
              @method controllerFor
              @private
            */
        __exports__["default"] = function controllerFor(container, controllerName, lookupOptions) {
            return container.lookup('controller:' + controllerName, lookupOptions);
        }
    });
    define("ember-routing/system/dsl",
    ["ember-metal/core", "exports"],
    function(__dependency1__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // FEATURES, assert

        /**
            @module ember
            @submodule ember-routing
            */

        function DSL(name) {
            this.parent = name;
            this.matches = [];
        }
        __exports__["default"] = DSL;

        DSL.prototype = {
            route: function(name, options, callback) {
                if (arguments.length === 2 && typeof options === 'function') {
                    callback = options;
                    options = {};
                }

                if (arguments.length === 1) {
                    options = {};
                }

                var type = options.resetNamespace === true ? 'resource' : 'route';
                Ember.assert("'basic' cannot be used as a " + type + " name.", name !== 'basic');


                if (typeof options.path !== 'string') {
                    options.path = "/" + name;
                }

                if (canNest(this) && options.resetNamespace !== true) {
                    name = this.parent + "." + name;
                }

                if (callback) {
                    var dsl = new DSL(name);
                    route(dsl, 'loading');
                    route(dsl, 'error', {
                        path: "/_unused_dummy_error_path_route_" + name + "/:error" 
                    });

                    if (callback) {
                        callback.call(dsl);
                    }

                    this.push(options.path, name, dsl.generate());
                } else {
                    this.push(options.path, name, null);
                }

            },

            push: function(url, name, callback) {
                var parts = name.split('.');
                if (url === "" || url === "/" || parts[parts.length-1] === "index") {
                    this.explicitIndex = true;
                }

                this.matches.push([url, name, callback]);
            },

            resource: function(name, options, callback) {
                if (arguments.length === 2 && typeof options === 'function') {
                    callback = options;
                    options = {};
                }

                if (arguments.length === 1) {
                    options = {};
                }

                options.resetNamespace = true;
                this.route(name, options, callback);
            },

            generate: function() {
                var dslMatches = this.matches;

                if (!this.explicitIndex) {
                    route(this, "index", {
                        path: "/" 
                    });
                }

                return function(match) {
                    for (var i = 0, l = dslMatches.length; i < l; i++) {
                        var dslMatch = dslMatches[i];
                        var matchObj = match(dslMatch[0]).to(dslMatch[1], dslMatch[2]);
                    }
                };
            }
        };

        function canNest(dsl) {
            return dsl.parent && dsl.parent !== 'application';
        }

        function route(dsl, name, options) {
            Ember.assert("You must use `this.resource` to nest", typeof options !== 'function');

            options = options || {};

            if (typeof options.path !== 'string') {
                options.path = "/" + name;
            }

            if (canNest(dsl) && options.resetNamespace !== true) {
                name = dsl.parent + "." + name;
            }

            dsl.push(options.path, name, null);
        }

        DSL.map = function(callback) {
            var dsl = new DSL();
            callback.call(dsl);
            return dsl;
        };
    });
    define("ember-routing/system/generate_controller",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/utils", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // Logger
        var get = __dependency2__.get;
        var isArray = __dependency3__.isArray;

        /**
            @module ember
            @submodule ember-routing
            */

        /**
              Generates a controller factory

              The type of the generated controller factory is derived
              from the context. If the context is an array an array controller
              is generated, if an object, an object controller otherwise, a basic
              controller is generated.

              You can customize your generated controllers by defining
              `App.ObjectController` or `App.ArrayController`.

              @for Ember
              @method generateControllerFactory
              @private
            */

        function generateControllerFactory(container, controllerName, context) {
            var Factory, fullName, instance, name, factoryName, controllerType;

            if (context && isArray(context)) {
                controllerType = 'array';
            } else if (context) {
                controllerType = 'object';
            } else {
                controllerType = 'basic';
            }

            factoryName = 'controller:' + controllerType;

            Factory = container.lookupFactory(factoryName).extend({
                isGenerated: true,
                toString: function() {
                    return "(generated " + controllerName + " controller)";
                }
            });

            fullName = 'controller:' + controllerName;

            container.register(fullName, Factory);

            return Factory;
        }

        __exports__.generateControllerFactory = generateControllerFactory; /**
              Generates and instantiates a controller.

              The type of the generated controller factory is derived
              from the context. If the context is an array an array controller
              is generated, if an object, an object controller otherwise, a basic
              controller is generated.

              @for Ember
              @method generateController
              @private
              @since 1.3.0
            */
        __exports__["default"] = function generateController(container, controllerName, context) {
            generateControllerFactory(container, controllerName, context);
            var fullName = 'controller:' + controllerName;
            var instance = container.lookup(fullName);

            if (get(instance, 'namespace.LOG_ACTIVE_GENERATION')) {
                Ember.Logger.info("generated -> " + fullName, {
                    fullName: fullName 
                });
            }

            return instance;
        }
    });
    define("ember-routing/system/route",
    ["ember-metal/core", "ember-metal/error", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/get_properties", "ember-metal/enumerable_utils", "ember-metal/is_none", "ember-metal/computed", "ember-metal/merge", "ember-metal/utils", "ember-metal/run_loop", "ember-runtime/keys", "ember-runtime/copy", "ember-runtime/system/string", "ember-runtime/system/object", "ember-runtime/mixins/action_handler", "ember-routing/system/generate_controller", "ember-routing-handlebars/helpers/shared", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // FEATURES, K, A, deprecate, assert, Logger
        var EmberError = __dependency2__["default"];
        var get = __dependency3__.get;
        var set = __dependency4__.set;
        var getProperties = __dependency5__["default"];
        var forEach = __dependency6__.forEach;
        var replace = __dependency6__.replace;
        var isNone = __dependency7__.isNone;
        var computed = __dependency8__.computed;
        var merge = __dependency9__["default"];
        var isArray = __dependency10__.isArray;
        var typeOf = __dependency10__.typeOf;
        var run = __dependency11__["default"];
        var keys = __dependency12__["default"];
        var copy = __dependency13__["default"];
        var classify = __dependency14__.classify;
        var fmt = __dependency14__.fmt;
        var EmberObject = __dependency15__["default"];
        var ActionHandler = __dependency16__["default"];
        var generateController = __dependency17__["default"];
        var stashParamNames = __dependency18__.stashParamNames;

        /**
            @module ember
            @submodule ember-routing
            */

        /**
              The `Ember.Route` class is used to define individual routes. Refer to
              the [routing guide](http://emberjs.com/guides/routing/) for documentation.

              @class Route
              @namespace Ember
              @extends Ember.Object
              @uses Ember.ActionHandler
            */
        var Route = EmberObject.extend(ActionHandler, {

            /**
                    @private

                    @method exit
                  */
            exit: function() {
                this.deactivate();
                this.teardownViews();
            },

            /**
                    @private

                    @method reset
                  */
            reset: function(isExiting, transition) {

                var controller = this.controller;
                controller._qpDelegate = get(this, '_qp.states.inactive');
                this.resetController(this.controller, isExiting, transition);

            },

            /**
                    @private

                    @method enter
                  */
            enter: function() {
                this.activate();
            },

            /**
                    The name of the view to use by default when rendering this routes template.

                    When rendering a template, the route will, by default, determine the
                    template and view to use from the name of the route itself. If you need to
                    define a specific view, set this property.

                    This is useful when multiple routes would benefit from using the same view
                    because it doesn't require a custom `renderTemplate` method. For example,
                    the following routes will all render using the `App.PostsListView` view:

                    ```js
                    var PostsList = Ember.Route.extend({
                      viewName: 'postsList'
                    });

                    App.PostsIndexRoute = PostsList.extend();
                    App.PostsArchivedRoute = PostsList.extend();
                    ```

                    @property viewName
                    @type String
                    @default null
                    @since 1.4.0
                  */
            viewName: null,

            /**
                    The name of the template to use by default when rendering this routes
                    template.

                    This is similar with `viewName`, but is useful when you just want a custom
                    template without a view.

                    ```js
                    var PostsList = Ember.Route.extend({
                      templateName: 'posts/list'
                    });

                    App.PostsIndexRoute = PostsList.extend();
                    App.PostsArchivedRoute = PostsList.extend();
                    ```

                    @property templateName
                    @type String
                    @default null
                    @since 1.4.0
                  */
            templateName: null,

            /**
                    The name of the controller to associate with this route.

                    By default, Ember will lookup a route's controller that matches the name
                    of the route (i.e. `App.PostController` for `App.PostRoute`). However,
                    if you would like to define a specific controller to use, you can do so
                    using this property.

                    This is useful in many ways, as the controller specified will be:

                    * passed to the `setupController` method.
                    * used as the controller for the view being rendered by the route.
                    * returned from a call to `controllerFor` for the route.

                    @property controllerName
                    @type String
                    @default null
                    @since 1.4.0
                  */
            controllerName: null,

            /**
                    The `willTransition` action is fired at the beginning of any
                    attempted transition with a `Transition` object as the sole
                    argument. This action can be used for aborting, redirecting,
                    or decorating the transition from the currently active routes.

                    A good example is preventing navigation when a form is
                    half-filled out:

                    ```js
                    App.ContactFormRoute = Ember.Route.extend({
                      actions: {
                        willTransition: function(transition) {
                          if (this.controller.get('userHasEnteredData')) {
                            this.controller.displayNavigationConfirm();
                            transition.abort();
                          }
                        }
                      }
                    });
                    ```

                    You can also redirect elsewhere by calling
                    `this.transitionTo('elsewhere')` from within `willTransition`.
                    Note that `willTransition` will not be fired for the
                    redirecting `transitionTo`, since `willTransition` doesn't
                    fire when there is already a transition underway. If you want
                    subsequent `willTransition` actions to fire for the redirecting
                    transition, you must first explicitly call
                    `transition.abort()`.

                    @event willTransition
                    @param {Transition} transition
                  */

            /**
                    The `didTransition` action is fired after a transition has
                    successfully been completed. This occurs after the normal model
                    hooks (`beforeModel`, `model`, `afterModel`, `setupController`)
                    have resolved. The `didTransition` action has no arguments,
                    however, it can be useful for tracking page views or resetting
                    state on the controller.

                    ```js
                    App.LoginRoute = Ember.Route.extend({
                      actions: {
                        didTransition: function() {
                          this.controller.get('errors.base').clear();
                          return true; // Bubble the didTransition event
                        }
                      }
                    });
                    ```

                    @event didTransition
                    @since 1.2.0
                  */

            /**
                    The `loading` action is fired on the route when a route's `model`
                    hook returns a promise that is not already resolved. The current
                    `Transition` object is the first parameter and the route that
                    triggered the loading event is the second parameter.

                    ```js
                    App.ApplicationRoute = Ember.Route.extend({
                      actions: {
                        loading: function(transition, route) {
                          var view = Ember.View.create({
                            classNames: ['app-loading']
                          })
                          .append();

                          this.router.one('didTransition', function () {
                            view.destroy();
                          });
                          return true; // Bubble the loading event
                        }
                      }
                    });
                    ```

                    @event loading
                    @param {Transition} transition
                    @param {Ember.Route} route The route that triggered the loading event
                    @since 1.2.0
                  */

            /**
                    When attempting to transition into a route, any of the hooks
                    may return a promise that rejects, at which point an `error`
                    action will be fired on the partially-entered routes, allowing
                    for per-route error handling logic, or shared error handling
                    logic defined on a parent route.

                    Here is an example of an error handler that will be invoked
                    for rejected promises from the various hooks on the route,
                    as well as any unhandled errors from child routes:

                    ```js
                    App.AdminRoute = Ember.Route.extend({
                      beforeModel: function() {
                        return Ember.RSVP.reject("bad things!");
                      },

                      actions: {
                        error: function(error, transition) {
                          // Assuming we got here due to the error in `beforeModel`,
                          // we can expect that error === "bad things!",
                          // but a promise model rejecting would also
                          // call this hook, as would any errors encountered
                          // in `afterModel`.

                          // The `error` hook is also provided the failed
                          // `transition`, which can be stored and later
                          // `.retry()`d if desired.

                          this.transitionTo('login');
                        }
                      }
                    });
                    ```

                    `error` actions that bubble up all the way to `ApplicationRoute`
                    will fire a default error handler that logs the error. You can
                    specify your own global default error handler by overriding the
                    `error` handler on `ApplicationRoute`:

                    ```js
                    App.ApplicationRoute = Ember.Route.extend({
                      actions: {
                        error: function(error, transition) {
                          this.controllerFor('banner').displayError(error.message);
                        }
                      }
                    });
                    ```
                    @event error
                    @param {Error} error
                    @param {Transition} transition
                  */

            /**
                    The controller associated with this route.

                    Example

                    ```javascript
                    App.FormRoute = Ember.Route.extend({
                      actions: {
                        willTransition: function(transition) {
                          if (this.controller.get('userHasEnteredData') &&
                              !confirm("Are you sure you want to abandon progress?")) {
                            transition.abort();
                          } else {
                            // Bubble the `willTransition` action so that
                            // parent routes can decide whether or not to abort.
                            return true;
                          }
                        }
                      }
                    });
                    ```

                    @property controller
                    @type Ember.Controller
                    @since 1.6.0
                  */

            _actions: {

                queryParamsDidChange: function(changed, totalPresent, removed) {

                    var totalChanged = keys(changed).concat(keys(removed));
                    for (var i = 0, len = totalChanged.length; i < len; ++i) {
                        var urlKey = totalChanged[i],
                        options = get(this.queryParams, urlKey) || {};
                        if (get(options, 'refreshModel')) {
                            this.refresh();
                        }
                    }
                    return true;

                },

                finalizeQueryParamChange: function(params, finalParams, transition) {

                    if (this.routeName !== 'application') {
                        return true;
                    }

                    // Transition object is absent for intermediate transitions.
                    if (!transition) {
                        return;
                    }

                    var handlerInfos = transition.state.handlerInfos;
                    var router = this.router;
                    var qpMeta = router._queryParamsFor(handlerInfos[handlerInfos.length-1].name);
                    var changes = router._qpUpdates;
                    var replaceUrl;

                    stashParamNames(router, handlerInfos);

                    for (var i = 0, len = qpMeta.qps.length; i < len; ++i) {
                        var qp = qpMeta.qps[i];
                        var route = qp.route;
                        var controller = route.controller;
                        var presentKey = qp.urlKey in params && qp.urlKey;

                        // Do a reverse lookup to see if the changed query
                        // param URL key corresponds to a QP property on
                        // this controller.
                        var value, svalue;
                        if (changes && qp.urlKey in changes) {
                            // Controller overrode this value in setupController
                            value = get(controller, qp.prop);
                            svalue = route.serializeQueryParam(value, qp.urlKey, qp.type);
                        } else {
                            if (presentKey) {
                                svalue = params[presentKey];
                                value = route.deserializeQueryParam(svalue, qp.urlKey, qp.type);
                            } else {
                                // No QP provided; use default value.
                                svalue = qp.sdef;
                                value = qp.def;
                                if (isArray(value)) {
                                    value = Ember.A(value.slice());
                                }
                            }
                        }

                        controller._qpDelegate = get(this, '_qp.states.inactive');

                        var thisQueryParamChanged = (svalue !== qp.svalue);
                        if (thisQueryParamChanged) {
                            var options = get(route, 'queryParams.' + qp.urlKey) || {};

                            if (transition.queryParamsOnly && replaceUrl !== false) {
                                var replaceConfigValue = get(options, 'replace');
                                if (replaceConfigValue) {
                                    replaceUrl = true;
                                } else if (replaceConfigValue === false) {
                                    // Explicit pushState wins over any other replaceStates.
                                    replaceUrl = false;
                                }
                            }

                            set(controller, qp.prop, value);
                        }

                        // Stash current serialized value of controller.
                        qp.svalue = svalue;

                        var thisQueryParamHasDefaultValue = (qp.sdef === svalue);
                        if (!thisQueryParamHasDefaultValue) {
                            finalParams.push({
                                value: svalue,
                                visible: true,
                                key: presentKey || qp.urlKey
                            });
                        }
                    }

                    if (replaceUrl) {
                        transition.method('replace');
                    }

                    forEach(qpMeta.qps, function(qp) {
                        var routeQpMeta = get(qp.route, '_qp');
                        var finalizedController = qp.route.controller;
                        finalizedController._qpDelegate = get(routeQpMeta, 'states.active');
                    });
                    router._qpUpdates = null;

                }
            },

            /**
                    @deprecated

                    Please use `actions` instead.
                    @method events
                  */
            events: null,

            mergedProperties: ['events'],

            /**
                    This hook is executed when the router completely exits this route. It is
                    not executed when the model for the route changes.

                    @method deactivate
                  */
            deactivate: Ember.K,

            /**
                    This hook is executed when the router enters the route. It is not executed
                    when the model for the route changes.

                    @method activate
                  */
            activate: Ember.K,

            /**
                    Transition the application into another route. The route may
                    be either a single route or route path:

                    ```javascript
                    this.transitionTo('blogPosts');
                    this.transitionTo('blogPosts.recentEntries');
                    ```

                    Optionally supply a model for the route in question. The model
                    will be serialized into the URL using the `serialize` hook of
                    the route:

                    ```javascript
                    this.transitionTo('blogPost', aPost);
                    ```

                    If a literal is passed (such as a number or a string), it will
                    be treated as an identifier instead. In this case, the `model`
                    hook of the route will be triggered:

                    ```javascript
                    this.transitionTo('blogPost', 1);
                    ```

                    Multiple models will be applied last to first recursively up the
                    resource tree.

                    ```javascript
                    App.Router.map(function() {
                      this.resource('blogPost', {path:':blogPostId'}, function(){
                        this.resource('blogComment', {path: ':blogCommentId'});
                      });
                    });

                    this.transitionTo('blogComment', aPost, aComment);
                    this.transitionTo('blogComment', 1, 13);
                    ```

                    It is also possible to pass a URL (a string that starts with a
                    `/`). This is intended for testing and debugging purposes and
                    should rarely be used in production code.

                    ```javascript
                    this.transitionTo('/');
                    this.transitionTo('/blog/post/1/comment/13');
                    ```

                    See also 'replaceWith'.

                    Simple Transition Example

                    ```javascript
                    App.Router.map(function() {
                      this.route("index");
                      this.route("secret");
                      this.route("fourOhFour", { path: "*:"});
                    });

                    App.IndexRoute = Ember.Route.extend({
                      actions: {
                        moveToSecret: function(context){
                          if (authorized()){
                            this.transitionTo('secret', context);
                          }
                            this.transitionTo('fourOhFour');
                        }
                      }
                    });
                    ```

                    Transition to a nested route

                    ```javascript
                    App.Router.map(function() {
                      this.resource('articles', { path: '/articles' }, function() {
                        this.route('new');
                      });
                    });

                    App.IndexRoute = Ember.Route.extend({
                      actions: {
                        transitionToNewArticle: function() {
                          this.transitionTo('articles.new');
                        }
                      }
                    });
                    ```

                    Multiple Models Example

                    ```javascript
                    App.Router.map(function() {
                      this.route("index");
                      this.resource('breakfast', {path:':breakfastId'}, function(){
                        this.resource('cereal', {path: ':cerealId'});
                      });
                    });

                    App.IndexRoute = Ember.Route.extend({
                      actions: {
                        moveToChocolateCereal: function(){
                          var cereal = { cerealId: "ChocolateYumminess"},
                              breakfast = {breakfastId: "CerealAndMilk"};

                          this.transitionTo('cereal', breakfast, cereal);
                        }
                      }
                    });
                    ```

                    @method transitionTo
                    @param {String} name the name of the route or a URL
                    @param {...Object} models the model(s) or identifier(s) to be used while
                      transitioning to the route.
                    @return {Transition} the transition object associated with this
                      attempted transition
                  */
            transitionTo: function(name, context) {
                var router = this.router;
                return router.transitionTo.apply(router, arguments);
            },

            /**
                    Perform a synchronous transition into another route without attempting
                    to resolve promises, update the URL, or abort any currently active
                    asynchronous transitions (i.e. regular transitions caused by
                    `transitionTo` or URL changes).

                    This method is handy for performing intermediate transitions on the
                    way to a final destination route, and is called internally by the
                    default implementations of the `error` and `loading` handlers.

                    @method intermediateTransitionTo
                    @param {String} name the name of the route
                    @param {...Object} models the model(s) to be used while transitioning
                    to the route.
                    @since 1.2.0
                   */
            intermediateTransitionTo: function() {
                var router = this.router;
                router.intermediateTransitionTo.apply(router, arguments);
            },

            /**
                    Refresh the model on this route and any child routes, firing the
                    `beforeModel`, `model`, and `afterModel` hooks in a similar fashion
                    to how routes are entered when transitioning in from other route.
                    The current route params (e.g. `article_id`) will be passed in
                    to the respective model hooks, and if a different model is returned,
                    `setupController` and associated route hooks will re-fire as well.

                    An example usage of this method is re-querying the server for the
                    latest information using the same parameters as when the route
                    was first entered.

                    Note that this will cause `model` hooks to fire even on routes
                    that were provided a model object when the route was initially
                    entered.

                    @method refresh
                    @return {Transition} the transition object associated with this
                      attempted transition
                    @since 1.4.0
                   */
            refresh: function() {
                return this.router.router.refresh(this);
            },

            /**
                    Transition into another route while replacing the current URL, if possible.
                    This will replace the current history entry instead of adding a new one.
                    Beside that, it is identical to `transitionTo` in all other respects. See
                    'transitionTo' for additional information regarding multiple models.

                    Example

                    ```javascript
                    App.Router.map(function() {
                      this.route("index");
                      this.route("secret");
                    });

                    App.SecretRoute = Ember.Route.extend({
                      afterModel: function() {
                        if (!authorized()){
                          this.replaceWith('index');
                        }
                      }
                    });
                    ```

                    @method replaceWith
                    @param {String} name the name of the route or a URL
                    @param {...Object} models the model(s) or identifier(s) to be used while
                      transitioning to the route.
                    @return {Transition} the transition object associated with this
                      attempted transition
                  */
            replaceWith: function() {
                var router = this.router;
                return router.replaceWith.apply(router, arguments);
            },

            /**
                    Sends an action to the router, which will delegate it to the currently
                    active route hierarchy per the bubbling rules explained under `actions`.

                    Example

                    ```javascript
                    App.Router.map(function() {
                      this.route("index");
                    });

                    App.ApplicationRoute = Ember.Route.extend({
                      actions: {
                        track: function(arg) {
                          console.log(arg, 'was clicked');
                        }
                      }
                    });

                    App.IndexRoute = Ember.Route.extend({
                      actions: {
                        trackIfDebug: function(arg) {
                          if (debug) {
                            this.send('track', arg);
                          }
                        }
                      }
                    });
                    ```

                    @method send
                    @param {String} name the name of the action to trigger
                    @param {...*} args
                  */
            send: function() {
                return this.router.send.apply(this.router, arguments);
            },

            /**
                    This hook is the entry point for router.js

                    @private
                    @method setup
                  */
            setup: function(context, transition) {
                var controllerName = this.controllerName || this.routeName;
                var controller = this.controllerFor(controllerName, true);

                if (!controller) {
                    controller = this.generateController(controllerName, context);
                }

                // Assign the route's controller so that it can more easily be
                // referenced in action handlers
                this.controller = controller;

                if (this.setupControllers) {
                    Ember.deprecate("Ember.Route.setupControllers is deprecated. Please use Ember.Route.setupController(controller, model) instead.");
                    this.setupControllers(controller, context);
                } else {

                    var states = get(this, '_qp.states');
                    if (transition) {
                        // Update the model dep values used to calculate cache keys.
                        controller._qpDelegate = states.changingKeys;
                        controller._updateCacheParams(transition.params);
                    }
                    controller._qpDelegate = states.allowOverrides;

                    this.setupController(controller, context, transition);
                }

                if (this.renderTemplates) {
                    Ember.deprecate("Ember.Route.renderTemplates is deprecated. Please use Ember.Route.renderTemplate(controller, model) instead.");
                    this.renderTemplates(context);
                } else {
                    this.renderTemplate(controller, context);
                }
            },

            /**
                    This hook is the first of the route entry validation hooks
                    called when an attempt is made to transition into a route
                    or one of its children. It is called before `model` and
                    `afterModel`, and is appropriate for cases when:

                    1) A decision can be made to redirect elsewhere without
                       needing to resolve the model first.
                    2) Any async operations need to occur first before the
                       model is attempted to be resolved.

                    This hook is provided the current `transition` attempt
                    as a parameter, which can be used to `.abort()` the transition,
                    save it for a later `.retry()`, or retrieve values set
                    on it from a previous hook. You can also just call
                    `this.transitionTo` to another route to implicitly
                    abort the `transition`.

                    You can return a promise from this hook to pause the
                    transition until the promise resolves (or rejects). This could
                    be useful, for instance, for retrieving async code from
                    the server that is required to enter a route.

                    ```js
                    App.PostRoute = Ember.Route.extend({
                      beforeModel: function(transition) {
                        if (!App.Post) {
                          return Ember.$.getScript('/models/post.js');
                        }
                      }
                    });
                    ```

                    If `App.Post` doesn't exist in the above example,
                    `beforeModel` will use jQuery's `getScript`, which
                    returns a promise that resolves after the server has
                    successfully retrieved and executed the code from the
                    server. Note that if an error were to occur, it would
                    be passed to the `error` hook on `Ember.Route`, but
                    it's also possible to handle errors specific to
                    `beforeModel` right from within the hook (to distinguish
                    from the shared error handling behavior of the `error`
                    hook):

                    ```js
                    App.PostRoute = Ember.Route.extend({
                      beforeModel: function(transition) {
                        if (!App.Post) {
                          var self = this;
                          return Ember.$.getScript('post.js').then(null, function(e) {
                            self.transitionTo('help');

                            // Note that the above transitionTo will implicitly
                            // halt the transition. If you were to return
                            // nothing from this promise reject handler,
                            // according to promise semantics, that would
                            // convert the reject into a resolve and the
                            // transition would continue. To propagate the
                            // error so that it'd be handled by the `error`
                            // hook, you would have to either
                            return Ember.RSVP.reject(e);
                          });
                        }
                      }
                    });
                    ```

                    @method beforeModel
                    @param {Transition} transition
                    @param {Object} queryParams the active query params for this route
                    @return {Promise} if the value returned from this hook is
                      a promise, the transition will pause until the transition
                      resolves. Otherwise, non-promise return values are not
                      utilized in any way.
                  */
            beforeModel: Ember.K,

            /**
                    This hook is called after this route's model has resolved.
                    It follows identical async/promise semantics to `beforeModel`
                    but is provided the route's resolved model in addition to
                    the `transition`, and is therefore suited to performing
                    logic that can only take place after the model has already
                    resolved.

                    ```js
                    App.PostsRoute = Ember.Route.extend({
                      afterModel: function(posts, transition) {
                        if (posts.get('length') === 1) {
                          this.transitionTo('post.show', posts.get('firstObject'));
                        }
                      }
                    });
                    ```

                    Refer to documentation for `beforeModel` for a description
                    of transition-pausing semantics when a promise is returned
                    from this hook.

                    @method afterModel
                    @param {Object} resolvedModel the value returned from `model`,
                      or its resolved value if it was a promise
                    @param {Transition} transition
                    @param {Object} queryParams the active query params for this handler
                    @return {Promise} if the value returned from this hook is
                      a promise, the transition will pause until the transition
                      resolves. Otherwise, non-promise return values are not
                      utilized in any way.
                   */
            afterModel: Ember.K,

            /**
                    A hook you can implement to optionally redirect to another route.

                    If you call `this.transitionTo` from inside of this hook, this route
                    will not be entered in favor of the other hook.

                    `redirect` and `afterModel` behave very similarly and are
                    called almost at the same time, but they have an important
                    distinction in the case that, from one of these hooks, a
                    redirect into a child route of this route occurs: redirects
                    from `afterModel` essentially invalidate the current attempt
                    to enter this route, and will result in this route's `beforeModel`,
                    `model`, and `afterModel` hooks being fired again within
                    the new, redirecting transition. Redirects that occur within
                    the `redirect` hook, on the other hand, will _not_ cause
                    these hooks to be fired again the second time around; in
                    other words, by the time the `redirect` hook has been called,
                    both the resolved model and attempted entry into this route
                    are considered to be fully validated.

                    @method redirect
                    @param {Object} model the model for this route
                  */
            redirect: Ember.K,

            /**
                    Called when the context is changed by router.js.

                    @private
                    @method contextDidChange
                  */
            contextDidChange: function() {
                this.currentModel = this.context;
            },

            /**
                    A hook you can implement to convert the URL into the model for
                    this route.

                    ```js
                    App.Router.map(function() {
                      this.resource('post', {path: '/posts/:post_id'});
                    });
                    ```

                    The model for the `post` route is `App.Post.find(params.post_id)`.

                    By default, if your route has a dynamic segment ending in `_id`:

                    * The model class is determined from the segment (`post_id`'s
                      class is `App.Post`)
                    * The find method is called on the model class with the value of
                      the dynamic segment.

                    Note that for routes with dynamic segments, this hook is only
                    executed when entered via the URL. If the route is entered
                    through a transition (e.g. when using the `link-to` Handlebars
                    helper), then a model context is already provided and this hook
                    is not called. Routes without dynamic segments will always
                    execute the model hook.

                    This hook follows the asynchronous/promise semantics
                    described in the documentation for `beforeModel`. In particular,
                    if a promise returned from `model` fails, the error will be
                    handled by the `error` hook on `Ember.Route`.

                    Example

                    ```js
                    App.PostRoute = Ember.Route.extend({
                      model: function(params) {
                        return App.Post.find(params.post_id);
                      }
                    });
                    ```

                    @method model
                    @param {Object} params the parameters extracted from the URL
                    @param {Transition} transition
                    @param {Object} queryParams the query params for this route
                    @return {Object|Promise} the model for this route. If
                      a promise is returned, the transition will pause until
                      the promise resolves, and the resolved value of the promise
                      will be used as the model for this route.
                  */
            model: function(params, transition) {
                var match, name, sawParams, value;

                var queryParams;

                queryParams = get(this, '_qp.map');


                for (var prop in params) {
                    if (prop === 'queryParams' || (queryParams && prop in queryParams)) {
                        continue;
                    }

                    if (match = prop.match(/^(.*)_id$/)) {
                        name = match[1];
                        value = params[prop];
                    }
                    sawParams = true;
                }

                if (!name && sawParams) {
                    return copy(params);
                } else if (!name) {
                    if (transition.resolveIndex !== transition.state.handlerInfos.length-1) {
                        return;
                    }

                    var parentModel = transition.state.handlerInfos[transition.resolveIndex-1].context;

                    return parentModel;
                }

                return this.findModel(name, value);
            },

            /**
                    @private
                    @method deserialize
                    @param {Object} params the parameters extracted from the URL
                    @param {Transition} transition
                    @return {Object|Promise} the model for this route.

                    Router.js hook.
                   */
            deserialize: function(params, transition) {

                return this.model(this.paramsFor(this.routeName), transition);
            },

            /**

                    @method findModel
                    @param {String} type the model type
                    @param {Object} value the value passed to find
                  */
            findModel: function() {
                var store = get(this, 'store');
                return store.find.apply(store, arguments);
            },

            /**
                    Store property provides a hook for data persistence libraries to inject themselves.

                    By default, this store property provides the exact same functionality previously
                    in the model hook.

                    Currently, the required interface is:

                    `store.find(modelName, findArguments)`

                    @method store
                    @param {Object} store
                  */
            store: computed(function() {
                var container = this.container;
                var routeName = this.routeName;
                var namespace = get(this, 'router.namespace');

                return {
                    find: function(name, value) {
                        var modelClass = container.lookupFactory('model:' + name);

                        Ember.assert("You used the dynamic segment " + name + "_id in your route " +
                        routeName + ", but " + namespace + "." + classify(name) +
                        " did not exist and you did not override your route's `model` " +
                        "hook.", modelClass);

                        if (!modelClass) {
                            return;
                        }

                        Ember.assert(classify(name) + ' has no method `find`.', typeof modelClass.find === 'function');

                        return modelClass.find(value);
                    }
                };
            }),

            /**
                    A hook you can implement to convert the route's model into parameters
                    for the URL.

                    ```js
                    App.Router.map(function() {
                      this.resource('post', {path: '/posts/:post_id'});
                    });

                    App.PostRoute = Ember.Route.extend({
                      model: function(params) {
                        // the server returns `{ id: 12 }`
                        return jQuery.getJSON("/posts/" + params.post_id);
                      },

                      serialize: function(model) {
                        // this will make the URL `/posts/12`
                        return { post_id: model.id };
                      }
                    });
                    ```

                    The default `serialize` method will insert the model's `id` into the
                    route's dynamic segment (in this case, `:post_id`) if the segment contains '_id'.
                    If the route has multiple dynamic segments or does not contain '_id', `serialize`
                    will return `Ember.getProperties(model, params)`

                    This method is called when `transitionTo` is called with a context
                    in order to populate the URL.

                    @method serialize
                    @param {Object} model the route's model
                    @param {Array} params an Array of parameter names for the current
                      route (in the example, `['post_id']`.
                    @return {Object} the serialized parameters
                  */
            serialize: function(model, params) {
                if (params.length < 1) {
                    return;
                }
                if (!model) {
                    return;
                }

                var name = params[0], object = {};

                if (/_id$/.test(name) && params.length === 1) {
                    object[name] = get(model, "id");
                } else {
                    object = getProperties(model, params);
                }

                return object;
            },

            /**
                    A hook you can use to setup the controller for the current route.

                    This method is called with the controller for the current route and the
                    model supplied by the `model` hook.

                    By default, the `setupController` hook sets the `model` property of
                    the controller to the `model`.

                    If you implement the `setupController` hook in your Route, it will
                    prevent this default behavior. If you want to preserve that behavior
                    when implementing your `setupController` function, make sure to call
                    `_super`:

                    ```js
                    App.PhotosRoute = Ember.Route.extend({
                      model: function() {
                        return App.Photo.find();
                      },

                      setupController: function (controller, model) {
                        // Call _super for default behavior
                        this._super(controller, model);
                        // Implement your custom setup after
                        this.controllerFor('application').set('showingPhotos', true);
                      }
                    });
                    ```

                    This means that your template will get a proxy for the model as its
                    context, and you can act as though the model itself was the context.

                    The provided controller will be one resolved based on the name
                    of this route.

                    If no explicit controller is defined, Ember will automatically create
                    an appropriate controller for the model.

                    * if the model is an `Ember.Array` (including record arrays from Ember
                      Data), the controller is an `Ember.ArrayController`.
                    * otherwise, the controller is an `Ember.ObjectController`.

                    As an example, consider the router:

                    ```js
                    App.Router.map(function() {
                      this.resource('post', {path: '/posts/:post_id'});
                    });
                    ```

                    For the `post` route, a controller named `App.PostController` would
                    be used if it is defined. If it is not defined, an `Ember.ObjectController`
                    instance would be used.

                    Example

                    ```js
                    App.PostRoute = Ember.Route.extend({
                      setupController: function(controller, model) {
                        controller.set('model', model);
                      }
                    });
                    ```

                    @method setupController
                    @param {Controller} controller instance
                    @param {Object} model
                  */
            setupController: function(controller, context, transition) {
                if (controller && (context !== undefined)) {
                    set(controller, 'model', context);
                }
            },

            /**
                    Returns the controller for a particular route or name.

                    The controller instance must already have been created, either through entering the
                    associated route or using `generateController`.

                    ```js
                    App.PostRoute = Ember.Route.extend({
                      setupController: function(controller, post) {
                        this._super(controller, post);
                        this.controllerFor('posts').set('currentPost', post);
                      }
                    });
                    ```

                    @method controllerFor
                    @param {String} name the name of the route or controller
                    @return {Ember.Controller}
                  */
            controllerFor: function(name, _skipAssert) {
                var container = this.container;
                var route = container.lookup('route:' + name);
                var controller;

                if (route && route.controllerName) {
                    name = route.controllerName;
                }

                controller = container.lookup('controller:' + name);

                // NOTE: We're specifically checking that skipAssert is true, because according
                //   to the old API the second parameter was model. We do not want people who
                //   passed a model to skip the assertion.
                Ember.assert("The controller named '" + name + "' could not be found. Make sure " +
                "that this route exists and has already been entered at least " +
                "once. If you are accessing a controller not associated with a " +
                "route, make sure the controller class is explicitly defined.",
                controller || _skipAssert === true);

                return controller;
            },

            /**
                    Generates a controller for a route.

                    If the optional model is passed then the controller type is determined automatically,
                    e.g., an ArrayController for arrays.

                    Example

                    ```js
                    App.PostRoute = Ember.Route.extend({
                      setupController: function(controller, post) {
                        this._super(controller, post);
                        this.generateController('posts', post);
                      }
                    });
                    ```

                    @method generateController
                    @param {String} name the name of the controller
                    @param {Object} model the model to infer the type of the controller (optional)
                  */
            generateController: function(name, model) {
                var container = this.container;

                model = model || this.modelFor(name);

                return generateController(container, name, model);
            },

            /**
                    Returns the model of a parent (or any ancestor) route
                    in a route hierarchy.  During a transition, all routes
                    must resolve a model object, and if a route
                    needs access to a parent route's model in order to
                    resolve a model (or just reuse the model from a parent),
                    it can call `this.modelFor(theNameOfParentRoute)` to
                    retrieve it.

                    Example

                    ```js
                    App.Router.map(function() {
                        this.resource('post', { path: '/post/:post_id' }, function() {
                            this.resource('comments');
                        });
                    });

                    App.CommentsRoute = Ember.Route.extend({
                        afterModel: function() {
                            this.set('post', this.modelFor('post'));
                        }
                    });
                    ```

                    @method modelFor
                    @param {String} name the name of the route
                    @return {Object} the model object
                  */
            modelFor: function(name) {
                var route = this.container.lookup('route:' + name);
                var transition = this.router ? this.router.router.activeTransition : null;

                // If we are mid-transition, we want to try and look up
                // resolved parent contexts on the current transitionEvent.
                if (transition) {
                    var modelLookupName = (route && route.routeName) || name;
                    if (transition.resolvedModels.hasOwnProperty(modelLookupName)) {
                        return transition.resolvedModels[modelLookupName];
                    }
                }

                return route && route.currentModel;
            },

            /**
                    A hook you can use to render the template for the current route.

                    This method is called with the controller for the current route and the
                    model supplied by the `model` hook. By default, it renders the route's
                    template, configured with the controller for the route.

                    This method can be overridden to set up and render additional or
                    alternative templates.

                    ```js
                    App.PostsRoute = Ember.Route.extend({
                      renderTemplate: function(controller, model) {
                        var favController = this.controllerFor('favoritePost');

                        // Render the `favoritePost` template into
                        // the outlet `posts`, and display the `favoritePost`
                        // controller.
                        this.render('favoritePost', {
                          outlet: 'posts',
                          controller: favController
                        });
                      }
                    });
                    ```

                    @method renderTemplate
                    @param {Object} controller the route's controller
                    @param {Object} model the route's model
                  */
            renderTemplate: function(controller, model) {
                this.render();
            },

            /**
                    `render` is used to render a template into a region of another template
                    (indicated by an `{{outlet}}`). `render` is used both during the entry
                    phase of routing (via the `renderTemplate` hook) and later in response to
                    user interaction.

                    For example, given the following minimal router and templates:

                    ```js
                    Router.map(function() {
                      this.resource('photos');
                    });
                    ```

                    ```handlebars
                    <!-- application.hbs -->
                    <div class='something-in-the-app-hbs'>
                      {{outlet "anOutletName"}}
                    </div>
                    ```

                    ```handlebars
                    <!-- photos.hbs -->
                    <h1>Photos</h1>
                    ```

                    You can render `photos.hbs` into the `"anOutletName"` outlet of
                    `application.hbs` by calling `render`:

                    ```js
                    // posts route
                    Ember.Route.extend({
                      renderTemplate: function(){
                        this.render('posts', {
                          into: 'application',
                          outlet: 'anOutletName'
                        })
                      }
                    });
                    ```

                    `render` additionally allows you to supply which `view`, `controller`, and
                    `model` objects should be loaded and associated with the rendered template.


                    ```js
                    // posts route
                    Ember.Route.extend({
                      renderTemplate: function(controller, model){
                        this.render('posts', {    // the template to render, referenced by name
                          into: 'application',    // the template to render into, referenced by name
                          outlet: 'anOutletName', // the outlet inside `options.template` to render into.
                          view: 'aViewName',      // the view to use for this template, referenced by name
                          controller: 'someControllerName', // the controller to use for this template, referenced by name
                          model: model            // the model to set on `options.controller`.
                        })
                      }
                    });
                    ```

                    The string values provided for the template name, view, and controller
                    will eventually pass through to the resolver for lookup. See
                    Ember.Resolver for how these are mapped to JavaScript objects in your
                    application.

                    Not all options need to be passed to `render`. Default values will be used
                    based on the name of the route specified in the router or the Route's
                    `controllerName`, `viewName` and and `templateName` properties.

                    For example:

                    ```js
                    // router
                    Router.map(function() {
                      this.route('index');
                      this.resource('post', {path: '/posts/:post_id'});
                    });
                    ```

                    ```js
                    // post route
                    PostRoute = App.Route.extend({
                      renderTemplate: function() {
                        this.render(); // all defaults apply
                      }
                    });
                    ```

                    The name of the `PostRoute`, defined by the router, is `post`.

                    The following equivalent default options will be applied when
                    the Route calls `render`:

                    ```js
                    //
                    this.render('post', {  // the template name associated with 'post' Route
                      into: 'application', // the parent route to 'post' Route
                      outlet: 'main',      // {{outlet}} and {{outlet 'main' are synonymous}},
                      view: 'post',        // the view associated with the 'post' Route
                      controller: 'post',  // the controller associated with the 'post' Route
                    })
                    ```

                    By default the controller's `model` will be the route's model, so it does not
                    need to be passed unless you wish to change which model is being used.

                    @method render
                    @param {String} name the name of the template to render
                    @param {Object} options the options
                    @param {String} options.into the template to render into,
                                    referenced by name. Defaults to the parent template
                    @param {String} options.outlet the outlet inside `options.template` to render into.
                                    Defaults to 'main'
                    @param {String} options.controller the controller to use for this template,
                                    referenced by name. Defaults to the Route's paired controller
                    @param {String} options.model the model object to set on `options.controller`
                                    Defaults to the return value of the Route's model hook
                  */
            render: function(name, options) {
                Ember.assert("The name in the given arguments is undefined", arguments.length > 0 ? !isNone(arguments[0]) : true);

                var namePassed = typeof name === 'string' && !!name;

                if (typeof name === 'object' && !options) {
                    options = name;
                    name = this.routeName;
                }

                options = options || {};
                options.namePassed = namePassed;

                var templateName;

                if (name) {
                    name = name.replace(/\//g, '.');
                    templateName = name;
                } else {
                    name = this.routeName;
                    templateName = this.templateName || name;
                }

                var viewName = options.view || namePassed && name || this.viewName || name;

                var container = this.container;
                var view = container.lookup('view:' + viewName);
                var template = view ? view.get('template') : null;

                if (!template) {
                    template = container.lookup('template:' + templateName);
                }

                if (!view && !template) {
                    Ember.assert("Could not find \"" + name + "\" template or view.", Ember.isEmpty(arguments[0]));
                    if (get(this.router, 'namespace.LOG_VIEW_LOOKUPS')) {
                        Ember.Logger.info("Could not find \"" + name + "\" template or view. Nothing will be rendered", {
                            fullName: 'template:' + name 
                        });
                    }
                    return;
                }

                options = normalizeOptions(this, name, template, options);
                view = setupView(view, container, options);

                if (options.outlet === 'main') {
                    this.lastRenderedTemplate = name;
                }

                appendView(this, view, options);
            },

            /**
                    Disconnects a view that has been rendered into an outlet.

                    You may pass any or all of the following options to `disconnectOutlet`:

                    * `outlet`: the name of the outlet to clear (default: 'main')
                    * `parentView`: the name of the view containing the outlet to clear
                       (default: the view rendered by the parent route)

                    Example:

                    ```js
                    App.ApplicationRoute = App.Route.extend({
                      actions: {
                        showModal: function(evt) {
                          this.render(evt.modalName, {
                            outlet: 'modal',
                            into: 'application'
                          });
                        },
                        hideModal: function(evt) {
                          this.disconnectOutlet({
                            outlet: 'modal',
                            parentView: 'application'
                          });
                        }
                      }
                    });
                    ```

                    Alternatively, you can pass the `outlet` name directly as a string.

                    Example:

                    ```js
                    hideModal: function(evt) {
                      this.disconnectOutlet('modal');
                    }
                    ```

                    @method disconnectOutlet
                    @param {Object|String} options the options hash or outlet name
                  */
            disconnectOutlet: function(options) {
                if (!options || typeof options === "string") {
                    var outletName = options;
                    options = {};
                    options.outlet = outletName;
                }
                options.parentView = options.parentView ? options.parentView.replace(/\//g, '.') : parentTemplate(this);
                options.outlet = options.outlet || 'main';

                var parentView = this.router._lookupActiveView(options.parentView);
                if (parentView) {
                    parentView.disconnectOutlet(options.outlet);
                }
            },

            willDestroy: function() {
                this.teardownViews();
            },

            /**
                    @private

                    @method teardownViews
                  */
            teardownViews: function() {
                // Tear down the top level view
                if (this.teardownTopLevelView) {
                    this.teardownTopLevelView();
                }

                // Tear down any outlets rendered with 'into'
                var teardownOutletViews = this.teardownOutletViews || [];
                forEach(teardownOutletViews, function(teardownOutletView) {
                    teardownOutletView();
                });

                delete this.teardownTopLevelView;
                delete this.teardownOutletViews;
                delete this.lastRenderedTemplate;
            }
        });

        var defaultQPMeta = {
            qps: [],
            map: {},
            states: {}
        };


        Route.reopen({
            /**
                      Configuration hash for this route's queryParams. The possible
                      configuration options and their defaults are as follows
                      (assuming a query param whose URL key is `page`):

                      ```js
                      queryParams: {
                        page: {
                          // By default, controller query param properties don't
                          // cause a full transition when they are changed, but
                          // rather only cause the URL to update. Setting
                          // `refreshModel` to true will cause an "in-place"
                          // transition to occur, whereby the model hooks for
                          // this route (and any child routes) will re-fire, allowing
                          // you to reload models (e.g., from the server) using the
                          // updated query param values.
                          refreshModel: false,

                          // By default, changes to controller query param properties
                          // cause the URL to update via `pushState`, which means an
                          // item will be added to the browser's history, allowing
                          // you to use the back button to restore the app to the
                          // previous state before the query param property was changed.
                          // Setting `replace` to true will use `replaceState` (or its
                          // hash location equivalent), which causes no browser history
                          // item to be added. This options name and default value are
                          // the same as the `link-to` helper's `replace` option.
                          replace: false
                        }
                      }
                      ```

                      @property queryParams
                      @for Ember.Route
                      @type Hash
                    */
            queryParams: {},

            _qp: computed(function() {
                var controllerName = this.controllerName || this.routeName;
                var fullName = this.container.normalize('controller:' + controllerName);
                var controllerClass = this.container.lookupFactory(fullName);

                if (!controllerClass) {
                    return defaultQPMeta;
                }

                var controllerProto = controllerClass.proto();
                var qpProps = get(controllerProto, '_normalizedQueryParams');
                var cacheMeta = get(controllerProto, '_cacheMeta');

                var qps = [], map = {}, self = this;
                for (var propName in qpProps) {
                    if (!qpProps.hasOwnProperty(propName)) {
                        continue;
                    }

                    var desc = qpProps[propName],
                    urlKey = desc.as || this.serializeQueryParamKey(propName),
                    defaultValue = get(controllerProto, propName);

                    if (isArray(defaultValue)) {
                        defaultValue = Ember.A(defaultValue.slice());
                    }

                    var type = typeOf(defaultValue),
                    defaultValueSerialized = this.serializeQueryParam(defaultValue, urlKey, type),
                    fprop = controllerName + ':' + propName,
                    qp = {
                        def: defaultValue,
                        sdef: defaultValueSerialized,
                        type: type,
                        urlKey: urlKey,
                        prop: propName,
                        fprop: fprop,
                        ctrl: controllerName,
                        cProto: controllerProto,
                        svalue: defaultValueSerialized,
                        cacheType: desc.scope,
                        route: this,
                        cacheMeta: cacheMeta[propName]
                    };

                    map[propName] = map[urlKey] = map[fprop] = qp;
                    qps.push(qp);
                }

                return {
                    qps: qps,
                    map: map,
                    states: {
                        active: function(controller, prop) {
                            return self._activeQPChanged(controller, map[prop]);
                        },
                        allowOverrides: function(controller, prop) {
                            return self._updatingQPChanged(controller, map[prop]);
                        },
                        changingKeys: function(controller, prop) {
                            return self._updateSerializedQPValue(controller, map[prop]);
                        }
                    }
                };
            }),

            _names: null,
            _stashNames: function(_handlerInfo, dynamicParent) {
                var handlerInfo = _handlerInfo;
                if (this._names) {
                    return;
                }
                var names = this._names = handlerInfo._names;

                if (!names.length) {
                    handlerInfo = dynamicParent;
                    names = handlerInfo && handlerInfo._names || [];
                }

                var qps = get(this, '_qp.qps');
                var len = qps.length;

                var namePaths = new Array(names.length);
                for (var a = 0, nlen = names.length; a < nlen; ++a) {
                    namePaths[a] = handlerInfo.name + '.' + names[a];
                }

                for (var i = 0; i < len; ++i) {
                    var qp = qps[i];
                    var cacheMeta = qp.cacheMeta;
                    if (cacheMeta.scope === 'model') {
                        cacheMeta.parts = namePaths;
                    }
                    cacheMeta.prefix = qp.ctrl;
                }
            },

            _updateSerializedQPValue: function(controller, qp) {
                var value = get(controller, qp.prop);
                qp.svalue = this.serializeQueryParam(value, qp.urlKey, qp.type);
            },

            _activeQPChanged: function(controller, qp) {
                var value = get(controller, qp.prop);
                this.router._queuedQPChanges[qp.fprop] = value;
                run.once(this, this._fireQueryParamTransition);
            },

            //_inactiveQPChanged: function(controller, qp) {
            //},

            _updatingQPChanged: function(controller, qp) {
                var router = this.router;
                if (!router._qpUpdates) {
                    router._qpUpdates = {};
                }
                router._qpUpdates[qp.urlKey] = true;
            },

            mergedProperties: ['queryParams'],

            paramsFor: function(name) {
                var route = this.container.lookup('route:' + name);

                if (!route) {
                    return {};
                }

                var transition = this.router.router.activeTransition;
                var state = transition ? transition.state : this.router.router.state;
                var params = {};

                merge(params, state.params[name]);

                if (!state.fullQueryParams) {
                    state.fullQueryParams = {};
                    merge(state.fullQueryParams, state.queryParams);

                    var targetRouteName = state.handlerInfos[state.handlerInfos.length-1].name;
                    this.router._deserializeQueryParams(targetRouteName, state.fullQueryParams);
                }

                var qpMeta = get(route, '_qp');

                if (!qpMeta) {
                    // No query params specified on the controller.
                    return params;
                }

                // Copy over all the query params for this route/controller into params hash.
                // TODO: is this correct? I think this won't do model dep state.
                var qps = qpMeta.qps;
                for (var i = 0, len = qps.length; i < len; ++i) {
                    // Put deserialized qp on params hash.
                    var qp = qps[i];
                    if (!(qp.prop in params)) {
                        params[qp.prop] = state.fullQueryParams[qp.prop] || qp.def;
                    }
                }

                return params;
            },

            serializeQueryParamKey: function(controllerPropertyName) {
                return controllerPropertyName;
            },

            serializeQueryParam: function(value, urlKey, defaultValueType) {
                // urlKey isn't used here, but anyone overriding
                // can use it to provide serialization specific
                // to a certain query param.
                if (defaultValueType === 'array') {
                    return JSON.stringify(value);
                }
                return '' + value;
            },

            deserializeQueryParam: function(value, urlKey, defaultValueType) {
                // urlKey isn't used here, but anyone overriding
                // can use it to provide deserialization specific
                // to a certain query param.

                // Use the defaultValueType of the default value (the initial value assigned to a
                // controller query param property), to intelligently deserialize and cast.
                if (defaultValueType === 'boolean') {
                    return (value === 'true') ? true : false;
                } else if (defaultValueType === 'number') {
                    return (Number(value)).valueOf();
                } else if (defaultValueType === 'array') {
                    return Ember.A(JSON.parse(value));
                }
                return value;
            },


            _fireQueryParamTransition: function() {
                this.transitionTo({
                    queryParams: this.router._queuedQPChanges 
                });
                this.router._queuedQPChanges = {};
            },

            /**
                      A hook you can use to reset controller values either when the model
                      changes or the route is exiting.

                      ```js
                      App.ArticlesRoute = Ember.Route.extend({
                        // ...

                        resetController: function (controller, isExiting, transition) {
                          if (isExiting) {
                            controller.set('page', 1);
                          }
                        }
                      });
                      ```

                      @method resetController
                      @param {Controller} controller instance
                      @param {Boolean} isExiting
                      @param {Object} transition
                    */
            resetController: Ember.K
        });


        function parentRoute(route) {
            var handlerInfo = handlerInfoFor(route, route.router.router.state.handlerInfos, -1);
            return handlerInfo && handlerInfo.handler;
        }

        function handlerInfoFor(route, handlerInfos, _offset) {
            if (!handlerInfos) {
                return;
            }

            var offset = _offset || 0, current;
            for (var i = 0, l = handlerInfos.length; i < l; i++) {
                current = handlerInfos[i].handler;
                if (current === route) {
                    return handlerInfos[i + offset];
                }
            }
        }

        function parentTemplate(route) {
            var parent = parentRoute(route), template;

            if (!parent) {
                return;
            }

            if (template = parent.lastRenderedTemplate) {
                return template;
            } else {
                return parentTemplate(parent);
            }
        }

        function normalizeOptions(route, name, template, options) {
            options = options || {};
            options.into = options.into ? options.into.replace(/\//g, '.') : parentTemplate(route);
            options.outlet = options.outlet || 'main';
            options.name = name;
            options.template = template;
            options.LOG_VIEW_LOOKUPS = get(route.router, 'namespace.LOG_VIEW_LOOKUPS');

            Ember.assert("An outlet (" + options.outlet + ") was specified but was not found.", options.outlet === 'main' || options.into);

            var controller = options.controller,
            model = options.model,
            namedController;

            if (options.controller) {
                controller = options.controller;
            } else if (options.namePassed) {
                controller = route.container.lookup('controller:' + name) || route.controllerName || route.routeName;
            } else {
                controller = route.controllerName || route.container.lookup('controller:' + name);
            }

            if (typeof controller === 'string') {
                var controllerName = controller;
                controller = route.container.lookup('controller:' + controllerName);
                if (!controller) {
                    throw new EmberError("You passed `controller: '" + controllerName + "'` into the `render` method, but no such controller could be found.");
                }
            }

            if (model) {
                controller.set('model', model);
            }

            options.controller = controller;

            return options;
        }

        function setupView(view, container, options) {
            if (view) {
                if (options.LOG_VIEW_LOOKUPS) {
                    Ember.Logger.info("Rendering " + options.name + " with " + view, {
                        fullName: 'view:' + options.name 
                    });
                }
            } else {
                var defaultView = options.into ? 'view:default' : 'view:toplevel';
                view = container.lookup(defaultView);
                if (options.LOG_VIEW_LOOKUPS) {
                    Ember.Logger.info("Rendering " + options.name + " with default view " + view, {
                        fullName: 'view:' + options.name 
                    });
                }
            }

            if (!get(view, 'templateName')) {
                set(view, 'template', options.template);

                set(view, '_debugTemplateName', options.name);
            }

            set(view, 'renderedName', options.name);
            set(view, 'controller', options.controller);

            return view;
        }

        function appendView(route, view, options) {
            if (options.into) {
                var parentView = route.router._lookupActiveView(options.into);
                var teardownOutletView = generateOutletTeardown(parentView, options.outlet);
                if (!route.teardownOutletViews) {
                    route.teardownOutletViews = [];
                }
                replace(route.teardownOutletViews, 0, 0, [teardownOutletView]);
                parentView.connectOutlet(options.outlet, view);
            } else {
                var rootElement = get(route, 'router.namespace.rootElement');
                // tear down view if one is already rendered
                if (route.teardownTopLevelView) {
                    route.teardownTopLevelView();
                }
                route.router._connectActiveView(options.name, view);
                route.teardownTopLevelView = generateTopLevelTeardown(view);
                view.appendTo(rootElement);
            }
        }

        function generateTopLevelTeardown(view) {
            return function() {
                view.destroy();
            };
        }

        function generateOutletTeardown(parentView, outlet) {
            return function() {
                parentView.disconnectOutlet(outlet);
            };
        }

        __exports__["default"] = Route;
    });
    define("ember-routing/system/router",
    ["ember-metal/core", "ember-metal/error", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/properties", "ember-metal/computed", "ember-metal/merge", "ember-metal/run_loop", "ember-metal/enumerable_utils", "ember-runtime/system/string", "ember-runtime/system/object", "ember-runtime/mixins/evented", "ember-routing/system/dsl", "ember-views/views/view", "ember-routing/location/api", "ember-handlebars/views/metamorph_view", "ember-routing-handlebars/helpers/shared", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // FEATURES, Logger, K, assert
        var EmberError = __dependency2__["default"];
        var get = __dependency3__.get;
        var set = __dependency4__.set;
        var defineProperty = __dependency5__.defineProperty;
        var computed = __dependency6__.computed;
        var merge = __dependency7__["default"];
        var run = __dependency8__["default"];
        var forEach = __dependency9__.forEach;

        var fmt = __dependency10__.fmt;
        var EmberObject = __dependency11__["default"];
        var Evented = __dependency12__["default"];
        var EmberRouterDSL = __dependency13__["default"];
        var EmberView = __dependency14__["default"];
        var EmberLocation = __dependency15__["default"];
        var _MetamorphView = __dependency16__["default"];
        var routeArgs = __dependency17__.routeArgs;
        var getActiveTargetName = __dependency17__.getActiveTargetName;
        var stashParamNames = __dependency17__.stashParamNames;

        // requireModule("ember-handlebars");
        // requireModule("ember-runtime");
        // requireModule("ember-views");

        /**
            @module ember
            @submodule ember-routing
            */

        // // side effect of loading some Ember globals, for now
        // requireModule("ember-handlebars");
        // requireModule("ember-runtime");
        // requireModule("ember-views");

        var Router = requireModule("router")['default'];
        var Transition = requireModule("router/transition").Transition;

        var slice = [].slice;

        /**
              The `Ember.Router` class manages the application state and URLs. Refer to
              the [routing guide](http://emberjs.com/guides/routing/) for documentation.

              @class Router
              @namespace Ember
              @extends Ember.Object
            */
        var EmberRouter = EmberObject.extend(Evented, {
            /**
                    The `location` property determines the type of URL's that your
                    application will use.

                    The following location types are currently available:

                    * `hash`
                    * `history`
                    * `none`

                    @property location
                    @default 'hash'
                    @see {Ember.Location}
                  */
            location: 'hash',

            /**
                   Represents the URL of the root of the application, often '/'. This prefix is
                   assumed on all routes defined on this router.

                   @property rootURL
                   @default '/'
                  */
            rootURL: '/',

            init: function() {
                this.router = this.constructor.router || this.constructor.map(Ember.K);
                this._activeViews = {};
                this._setupLocation();
                this._qpCache = {};
                this._queuedQPChanges = {};

                if (get(this, 'namespace.LOG_TRANSITIONS_INTERNAL')) {
                    this.router.log = Ember.Logger.debug;
                }
            },

            /**
                    Represents the current URL.

                    @method url
                    @return {String} The current URL.
                  */
            url: computed(function() {
                return get(this, 'location').getURL();
            }),

            /**
                    Initializes the current router instance and sets up the change handling
                    event listeners used by the instances `location` implementation.

                    A property named `initialURL` will be used to determine the initial URL.
                    If no value is found `/` will be used.

                    @method startRouting
                    @private
                  */
            startRouting: function() {
                this.router = this.router || this.constructor.map(Ember.K);

                var router = this.router;
                var location = get(this, 'location');
                var container = this.container;
                var self = this;
                var initialURL = get(this, 'initialURL');

                // Allow the Location class to cancel the router setup while it refreshes
                // the page
                if (get(location, 'cancelRouterSetup')) {
                    return;
                }

                this._setupRouter(router, location);

                container.register('view:default', _MetamorphView);
                container.register('view:toplevel', EmberView.extend());

                location.onUpdateURL(function(url) {
                    self.handleURL(url);
                });

                if (typeof initialURL === "undefined") {
                    initialURL = location.getURL();
                }

                this.handleURL(initialURL);
            },

            /**
                    Handles updating the paths and notifying any listeners of the URL
                    change.

                    Triggers the router level `didTransition` hook.

                    @method didTransition
                    @private
                    @since 1.2.0
                  */
            didTransition: function(infos) {
                updatePaths(this);

                this._cancelLoadingEvent();

                this.notifyPropertyChange('url');

                // Put this in the runloop so url will be accurate. Seems
                // less surprising than didTransition being out of sync.
                run.once(this, this.trigger, 'didTransition');

                if (get(this, 'namespace').LOG_TRANSITIONS) {
                    Ember.Logger.log("Transitioned into '" + EmberRouter._routePath(infos) + "'");
                }
            },

            handleURL: function(url) {
                return this._doURLTransition('handleURL', url);
            },

            _doURLTransition: function(routerJsMethod, url) {
                var transition = this.router[routerJsMethod](url || '/');
                listenForTransitionErrors(transition);
                return transition;
            },

            transitionTo: function() {
                var args = slice.call(arguments), queryParams;
                if (resemblesURL(args[0])) {
                    return this._doURLTransition('transitionTo', args[0]);
                }

                var possibleQueryParams = args[args.length-1];
                if (possibleQueryParams && possibleQueryParams.hasOwnProperty('queryParams')) {
                    queryParams = args.pop().queryParams;
                } else {
                    queryParams = {};
                }

                var targetRouteName = args.shift();
                return this._doTransition(targetRouteName, args, queryParams);
            },

            intermediateTransitionTo: function() {
                this.router.intermediateTransitionTo.apply(this.router, arguments);

                updatePaths(this);

                var infos = this.router.currentHandlerInfos;
                if (get(this, 'namespace').LOG_TRANSITIONS) {
                    Ember.Logger.log("Intermediate-transitioned into '" + EmberRouter._routePath(infos) + "'");
                }
            },

            replaceWith: function() {
                return this.transitionTo.apply(this, arguments).method('replace');
            },

            generate: function() {
                var url = this.router.generate.apply(this.router, arguments);
                return this.location.formatURL(url);
            },

            /**
                    Determines if the supplied route is currently active.

                    @method isActive
                    @param routeName
                    @return {Boolean}
                    @private
                  */
            isActive: function(routeName) {
                var router = this.router;
                return router.isActive.apply(router, arguments);
            },

            /**
                    An alternative form of `isActive` that doesn't require
                    manual concatenation of the arguments into a single
                    array.

                    @method isActive
                    @param routeName
                    @param models
                    @param queryParams
                    @return {Boolean}
                    @private
                  */
            isActiveIntent: function(routeName, models, queryParams) {
                var router = this.router;
                return router.isActive.apply(router, arguments);
            },

            send: function(name, context) {
                this.router.trigger.apply(this.router, arguments);
            },

            /**
                    Does this router instance have the given route.

                    @method hasRoute
                    @return {Boolean}
                    @private
                  */
            hasRoute: function(route) {
                return this.router.hasRoute(route);
            },

            /**
                    Resets the state of the router by clearing the current route
                    handlers and deactivating them.

                    @private
                    @method reset
                   */
            reset: function() {
                this.router.reset();
            },

            _lookupActiveView: function(templateName) {
                var active = this._activeViews[templateName];
                return active && active[0];
            },

            _connectActiveView: function(templateName, view) {
                var existing = this._activeViews[templateName];

                if (existing) {
                    existing[0].off('willDestroyElement', this, existing[1]);
                }

                function disconnectActiveView() {
                    delete this._activeViews[templateName];
                }

                this._activeViews[templateName] = [view, disconnectActiveView];
                view.one('willDestroyElement', this, disconnectActiveView);
            },

            _setupLocation: function() {
                var location = get(this, 'location');
                var rootURL = get(this, 'rootURL');

                if (rootURL && this.container && !this.container.has('-location-setting:root-url')) {
                    this.container.register('-location-setting:root-url', rootURL, {
                        instantiate: false 
                    });
                }

                if ('string' === typeof location && this.container) {
                    var resolvedLocation = this.container.lookup('location:' + location);

                    if ('undefined' !== typeof resolvedLocation) {
                        location = set(this, 'location', resolvedLocation);
                    } else {
                        // Allow for deprecated registration of custom location API's
                        var options = {
                            implementation: location
                        };

                        location = set(this, 'location', EmberLocation.create(options));
                    }
                }

                if (rootURL && typeof rootURL === 'string') {
                    location.rootURL = rootURL;
                }

                // ensure that initState is called AFTER the rootURL is set on
                // the location instance
                if (typeof location.initState === 'function') {
                    location.initState();
                }
            },

            _getHandlerFunction: function() {
                var seen = {}, container = this.container;
                var DefaultRoute = container.lookupFactory('route:basic');
                var self = this;

                return function(name) {
                    var routeName = 'route:' + name;
                    var handler = container.lookup(routeName);

                    if (seen[name]) {
                        return handler;
                    }

                    seen[name] = true;

                    if (!handler) {
                        container.register(routeName, DefaultRoute.extend());
                        handler = container.lookup(routeName);

                        if (get(self, 'namespace.LOG_ACTIVE_GENERATION')) {
                            Ember.Logger.info("generated -> " + routeName, {
                                fullName: routeName 
                            });
                        }
                    }

                    handler.routeName = name;
                    return handler;
                };
            },

            _setupRouter: function(router, location) {
                var lastURL, emberRouter = this;

                router.getHandler = this._getHandlerFunction();

                var doUpdateURL = function() {
                    location.setURL(lastURL);
                };

                router.updateURL = function(path) {
                    lastURL = path;
                    run.once(doUpdateURL);
                };

                if (location.replaceURL) {
                    var doReplaceURL = function() {
                        location.replaceURL(lastURL);
                    };

                    router.replaceURL = function(path) {
                        lastURL = path;
                        run.once(doReplaceURL);
                    };
                }

                router.didTransition = function(infos) {
                    emberRouter.didTransition(infos);
                };
            },

            _serializeQueryParams: function(targetRouteName, queryParams) {
                var groupedByUrlKey = {};

                forEachQueryParam(this, targetRouteName, queryParams, function(key, value, qp) {
                    var urlKey = qp.urlKey;
                    if (!groupedByUrlKey[urlKey]) {
                        groupedByUrlKey[urlKey] = [];
                    }
                    groupedByUrlKey[urlKey].push({
                        qp: qp,
                        value: value
                    });
                    delete queryParams[key];
                });

                for (var key in groupedByUrlKey) {
                    var qps = groupedByUrlKey[key];
                    if (qps.length > 1) {
                        var qp0 = qps[0].qp, qp1 = qps[1].qp;
                        Ember.assert(fmt("You're not allowed to have more than one controller property map to the same query param key, but both `%@` and `%@` map to `%@`. You can fix this by mapping one of the controller properties to a different query param key via the `as` config option, e.g. `%@: { as: 'other-%@' }`", [qp0.fprop, qp1.fprop, qp0.urlKey, qp0.prop, qp0.prop]), false);
                    }
                    var qp = qps[0].qp;
                    queryParams[qp.urlKey] = qp.route.serializeQueryParam(qps[0].value, qp.urlKey, qp.type);
                }
            },

            _deserializeQueryParams: function(targetRouteName, queryParams) {
                forEachQueryParam(this, targetRouteName, queryParams, function(key, value, qp) {
                    delete queryParams[key];
                    queryParams[qp.prop] = qp.route.deserializeQueryParam(value, qp.urlKey, qp.type);
                });
            },

            _pruneDefaultQueryParamValues: function(targetRouteName, queryParams) {
                var qps = this._queryParamsFor(targetRouteName);
                for (var key in queryParams) {
                    var qp = qps.map[key];
                    if (qp && qp.sdef === queryParams[key]) {
                        delete queryParams[key];
                    }
                }
            },

            _doTransition: function(_targetRouteName, models, _queryParams) {
                var targetRouteName = _targetRouteName || getActiveTargetName(this.router);
                Ember.assert("The route " + targetRouteName + " was not found", targetRouteName && this.router.hasRoute(targetRouteName));

                var queryParams = {};

                merge(queryParams, _queryParams);
                this._prepareQueryParams(targetRouteName, models, queryParams);


                var transitionArgs = routeArgs(targetRouteName, models, queryParams);
                var transitionPromise = this.router.transitionTo.apply(this.router, transitionArgs);

                listenForTransitionErrors(transitionPromise);

                return transitionPromise;
            },

            _prepareQueryParams: function(targetRouteName, models, queryParams) {
                this._hydrateUnsuppliedQueryParams(targetRouteName, models, queryParams);
                this._serializeQueryParams(targetRouteName, queryParams);
                this._pruneDefaultQueryParamValues(targetRouteName, queryParams);
            },

            /**
                    Returns a merged query params meta object for a given route.
                    Useful for asking a route what its known query params are.
                   */
            _queryParamsFor: function(leafRouteName) {
                if (this._qpCache[leafRouteName]) {
                    return this._qpCache[leafRouteName];
                }

                var map = {}, qps = [], qpCache = this._qpCache[leafRouteName] = {
                    map: map,
                    qps: qps
                };

                var routerjs = this.router,
                recogHandlerInfos = routerjs.recognizer.handlersFor(leafRouteName);

                for (var i = 0, len = recogHandlerInfos.length; i < len; ++i) {
                    var recogHandler = recogHandlerInfos[i];
                    var route = routerjs.getHandler(recogHandler.handler);
                    var qpMeta = get(route, '_qp');

                    if (!qpMeta) {
                        continue;
                    }

                    merge(map, qpMeta.map);
                    qps.push.apply(qps, qpMeta.qps);
                }

                return {
                    qps: qps,
                    map: map
                };
            },

            /*
                    becomeResolved: function(payload, resolvedContext) {
                      var params = this.serialize(resolvedContext);

                      if (payload) {
                        this.stashResolvedModel(payload, resolvedContext);
                        payload.params = payload.params || {};
                        payload.params[this.name] = params;
                      }

                      return this.factory('resolved', {
                        context: resolvedContext,
                        name: this.name,
                        handler: this.handler,
                        params: params
                      });
                    },
                  */

            _hydrateUnsuppliedQueryParams: function(leafRouteName, contexts, queryParams) {
                var state = calculatePostTransitionState(this, leafRouteName, contexts);
                var handlerInfos = state.handlerInfos;
                var appCache = this._bucketCache;

                stashParamNames(this, handlerInfos);

                for (var i = 0, len = handlerInfos.length; i < len; ++i) {
                    var route = handlerInfos[i].handler;
                    var qpMeta = get(route, '_qp');

                    for (var j = 0, qpLen = qpMeta.qps.length; j < qpLen; ++j) {
                        var qp = qpMeta.qps[j];
                        var presentProp = qp.prop in queryParams && qp.prop ||
                        qp.fprop in queryParams && qp.fprop;

                        if (presentProp) {
                            if (presentProp !== qp.fprop) {
                                queryParams[qp.fprop] = queryParams[presentProp];
                                delete queryParams[presentProp];
                            }
                        } else {
                            var controllerProto = qp.cProto;
                            var cacheMeta = get(controllerProto, '_cacheMeta');

                            var cacheKey = controllerProto._calculateCacheKey(qp.ctrl, cacheMeta[qp.prop].parts, state.params);
                            queryParams[qp.fprop] = appCache.lookup(cacheKey, qp.prop, qp.def);
                        }
                    }
                }
            },

            _scheduleLoadingEvent: function(transition, originRoute) {
                this._cancelLoadingEvent();
                this._loadingStateTimer = run.scheduleOnce('routerTransitions', this, '_fireLoadingEvent', transition, originRoute);
            },

            _fireLoadingEvent: function(transition, originRoute) {
                if (!this.router.activeTransition) {
                    // Don't fire an event if we've since moved on from
                    // the transition that put us in a loading state.
                    return;
                }

                transition.trigger(true, 'loading', transition, originRoute);
            },

            _cancelLoadingEvent: function () {
                if (this._loadingStateTimer) {
                    run.cancel(this._loadingStateTimer);
                }
                this._loadingStateTimer = null;
            }
        });

        /*
              Helper function for iterating root-ward, starting
              from (but not including) the provided `originRoute`.

              Returns true if the last callback fired requested
              to bubble upward.

              @private
             */
        function forEachRouteAbove(originRoute, transition, callback) {
            var handlerInfos = transition.state.handlerInfos;
            var originRouteFound = false;
            var handlerInfo, route;

            for (var i = handlerInfos.length - 1; i >= 0; --i) {
                handlerInfo = handlerInfos[i];
                route = handlerInfo.handler;

                if (!originRouteFound) {
                    if (originRoute === route) {
                        originRouteFound = true;
                    }
                    continue;
                }

                if (callback(route, handlerInfos[i + 1].handler) !== true) {
                    return false;
                }
            }
            return true;
        }

        // These get invoked when an action bubbles above ApplicationRoute
        // and are not meant to be overridable.
        var defaultActionHandlers = {

            willResolveModel: function(transition, originRoute) {
                originRoute.router._scheduleLoadingEvent(transition, originRoute);
            },

            error: function(error, transition, originRoute) {
                // Attempt to find an appropriate error substate to enter.
                var router = originRoute.router;

                var tryTopLevel = forEachRouteAbove(originRoute, transition, function(route, childRoute) {
                    var childErrorRouteName = findChildRouteName(route, childRoute, 'error');
                    if (childErrorRouteName) {
                        router.intermediateTransitionTo(childErrorRouteName, error);
                        return;
                    }
                    return true;
                });

                if (tryTopLevel) {
                    // Check for top-level error state to enter.
                    if (routeHasBeenDefined(originRoute.router, 'application_error')) {
                        router.intermediateTransitionTo('application_error', error);
                        return;
                    }
                } else {
                    // Don't fire an assertion if we found an error substate.
                    return;
                }

                logError(error, 'Error while processing route: ' + transition.targetName);
            },

            loading: function(transition, originRoute) {
                // Attempt to find an appropriate loading substate to enter.
                var router = originRoute.router;

                var tryTopLevel = forEachRouteAbove(originRoute, transition, function(route, childRoute) {
                    var childLoadingRouteName = findChildRouteName(route, childRoute, 'loading');

                    if (childLoadingRouteName) {
                        router.intermediateTransitionTo(childLoadingRouteName);
                        return;
                    }

                    // Don't bubble above pivot route.
                    if (transition.pivotHandler !== route) {
                        return true;
                    }
                });

                if (tryTopLevel) {
                    // Check for top-level loading state to enter.
                    if (routeHasBeenDefined(originRoute.router, 'application_loading')) {
                        router.intermediateTransitionTo('application_loading');
                        return;
                    }
                }
            }
        };

        function logError(error, initialMessage) {
            var errorArgs = [];

            if (initialMessage) {
                errorArgs.push(initialMessage);
            }

            if (error) {
                if (error.message) {
                    errorArgs.push(error.message);
                }
                if (error.stack) {
                    errorArgs.push(error.stack);
                }

                if (typeof error === "string") {
                    errorArgs.push(error);
                }
            }

            Ember.Logger.error.apply(this, errorArgs);
        }

        function findChildRouteName(parentRoute, originatingChildRoute, name) {
            var router = parentRoute.router;
            var childName;
            var targetChildRouteName = originatingChildRoute.routeName.split('.').pop();
            var namespace = parentRoute.routeName === 'application' ? '' : parentRoute.routeName + '.';


            // Second, try general loading state, e.g. 'loading'
            childName = namespace + name;
            if (routeHasBeenDefined(router, childName)) {
                return childName;
            }
        }

        function routeHasBeenDefined(router, name) {
            var container = router.container;
            return router.hasRoute(name) &&
            (container.has('template:' + name) || container.has('route:' + name));
        }

        function triggerEvent(handlerInfos, ignoreFailure, args) {
            var name = args.shift();

            if (!handlerInfos) {
                if (ignoreFailure) {
                    return;
                }
                throw new EmberError("Can't trigger action '" + name + "' because your app hasn't finished transitioning into its first route. To trigger an action on destination routes during a transition, you can call `.send()` on the `Transition` object passed to the `model/beforeModel/afterModel` hooks.");
            }

            var eventWasHandled = false;
            var handlerInfo, handler;

            for (var i = handlerInfos.length - 1; i >= 0; i--) {
                handlerInfo = handlerInfos[i];
                handler = handlerInfo.handler;

                if (handler._actions && handler._actions[name]) {
                    if (handler._actions[name].apply(handler, args) === true) {
                        eventWasHandled = true;
                    } else {
                        return;
                    }
                }
            }

            if (defaultActionHandlers[name]) {
                defaultActionHandlers[name].apply(null, args);
                return;
            }

            if (!eventWasHandled && !ignoreFailure) {
                throw new EmberError("Nothing handled the action '" + name + "'. If you did handle the action, this error can be caused by returning true from an action handler in a controller, causing the action to bubble.");
            }
        }

        function calculatePostTransitionState(emberRouter, leafRouteName, contexts) {
            var routerjs = emberRouter.router;
            var state = routerjs.applyIntent(leafRouteName, contexts);
            var handlerInfos = state.handlerInfos;
            var params = state.params;

            for (var i = 0, len = handlerInfos.length; i < len; ++i) {
                var handlerInfo = handlerInfos[i];
                if (!handlerInfo.isResolved) {
                    handlerInfo = handlerInfo.becomeResolved(null, handlerInfo.context);
                }
                params[handlerInfo.name] = handlerInfo.params;
            }
            return state;
        }

        function updatePaths(router) {
            var appController = router.container.lookup('controller:application');

            if (!appController) {
                // appController might not exist when top-level loading/error
                // substates have been entered since ApplicationRoute hasn't
                // actually been entered at that point.
                return;
            }

            var infos = router.router.currentHandlerInfos,
            path = EmberRouter._routePath(infos);

            if (!('currentPath' in appController)) {
                defineProperty(appController, 'currentPath');
            }

            set(appController, 'currentPath', path);

            if (!('currentRouteName' in appController)) {
                defineProperty(appController, 'currentRouteName');
            }

            set(appController, 'currentRouteName', infos[infos.length - 1].name);
        }

        EmberRouter.reopenClass({
            router: null,
            map: function(callback) {
                var router = this.router;
                if (!router) {
                    router = new Router();


                    router._triggerWillChangeContext = Ember.K;
                    router._triggerWillLeave = Ember.K;


                    router.callbacks = [];
                    router.triggerEvent = triggerEvent;
                    this.reopenClass({
                        router: router 
                    });
                }

                var dsl = EmberRouterDSL.map(function() {
                    this.resource('application', {
                        path: "/" 
                    }, function() {
                        for (var i = 0; i < router.callbacks.length; i++) {
                            router.callbacks[i].call(this);
                        }
                        callback.call(this);
                    });
                });

                router.callbacks.push(callback);
                router.map(dsl.generate());
                return router;
            },

            _routePath: function(handlerInfos) {
                var path = [];

                // We have to handle coalescing resource names that
                // are prefixed with their parent's names, e.g.
                // ['foo', 'foo.bar.baz'] => 'foo.bar.baz', not 'foo.foo.bar.baz'

                function intersectionMatches(a1, a2) {
                    for (var i = 0, len = a1.length; i < len; ++i) {
                        if (a1[i] !== a2[i]) {
                            return false;
                        }
                    }
                    return true;
                }

                var name, nameParts, oldNameParts;
                for (var i = 1, l = handlerInfos.length; i < l; i++) {
                    name = handlerInfos[i].name;
                    nameParts = name.split(".");
                    oldNameParts = slice.call(path);

                    while (oldNameParts.length) {
                        if (intersectionMatches(oldNameParts, nameParts)) {
                            break;
                        }
                        oldNameParts.shift();
                    }

                    path.push.apply(path, nameParts.slice(oldNameParts.length));
                }

                return path.join(".");
            }
        });

        function listenForTransitionErrors(transition) {
            transition.then(null, function(error) {
                if (!error || !error.name) {
                    return;
                }

                if (error.name === "UnrecognizedURLError") {
                    Ember.assert("The URL '" + error.message + "' did not match any routes in your application");
                } else if (error.name === 'TransitionAborted') {
                    // just ignore TransitionAborted here
                } else {
                    logError(error);
                }

                return error;
            }, 'Ember: Process errors from Router');
        }

        function resemblesURL(str) {
            return typeof str === 'string' && ( str === '' || str.charAt(0) === '/');
        }

        function forEachQueryParam(router, targetRouteName, queryParams, callback) {

            var qpCache = router._queryParamsFor(targetRouteName),
            qps = qpCache.qps;

            for (var key in queryParams) {
                if (!queryParams.hasOwnProperty(key)) {
                    continue;
                }
                var value = queryParams[key],
                qp = qpCache.map[key];

                if (qp) {
                    callback(key, value, qp);
                }
            }
        }

        __exports__["default"] = EmberRouter;
    });
    define("ember-runtime",
    ["ember-metal", "ember-runtime/core", "ember-runtime/keys", "ember-runtime/compare", "ember-runtime/copy", "ember-runtime/system/namespace", "ember-runtime/system/object", "ember-runtime/system/tracked_array", "ember-runtime/system/subarray", "ember-runtime/system/container", "ember-runtime/system/application", "ember-runtime/system/array_proxy", "ember-runtime/system/object_proxy", "ember-runtime/system/core_object", "ember-runtime/system/each_proxy", "ember-runtime/system/native_array", "ember-runtime/system/set", "ember-runtime/system/string", "ember-runtime/system/deferred", "ember-runtime/system/lazy_load", "ember-runtime/mixins/array", "ember-runtime/mixins/comparable", "ember-runtime/mixins/copyable", "ember-runtime/mixins/enumerable", "ember-runtime/mixins/freezable", "ember-runtime/mixins/observable", "ember-runtime/mixins/action_handler", "ember-runtime/mixins/deferred", "ember-runtime/mixins/mutable_enumerable", "ember-runtime/mixins/mutable_array", "ember-runtime/mixins/target_action_support", "ember-runtime/mixins/evented", "ember-runtime/mixins/promise_proxy", "ember-runtime/mixins/sortable", "ember-runtime/computed/array_computed", "ember-runtime/computed/reduce_computed", "ember-runtime/computed/reduce_computed_macros", "ember-runtime/controllers/array_controller", "ember-runtime/controllers/object_controller", "ember-runtime/controllers/controller", "ember-runtime/mixins/controller", "ember-runtime/ext/rsvp", "ember-runtime/ext/string", "ember-runtime/ext/function", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __dependency19__, __dependency20__, __dependency21__, __dependency22__, __dependency23__, __dependency24__, __dependency25__, __dependency26__, __dependency27__, __dependency28__, __dependency29__, __dependency30__, __dependency31__, __dependency32__, __dependency33__, __dependency34__, __dependency35__, __dependency36__, __dependency37__, __dependency38__, __dependency39__, __dependency40__, __dependency41__, __dependency42__, __dependency43__, __dependency44__, __exports__) {
        "use strict";
        /**
            Ember Runtime

            @module ember
            @submodule ember-runtime
            @requires ember-metal
            */

        // BEGIN IMPORTS
        var Ember = __dependency1__["default"];
        var isEqual = __dependency2__.isEqual;
        var keys = __dependency3__["default"];
        var compare = __dependency4__["default"];
        var copy = __dependency5__["default"];

        var Namespace = __dependency6__["default"];
        var EmberObject = __dependency7__["default"];
        var TrackedArray = __dependency8__["default"];
        var SubArray = __dependency9__["default"];
        var Container = __dependency10__["default"];
        var Application = __dependency11__["default"];
        var ArrayProxy = __dependency12__["default"];
        var ObjectProxy = __dependency13__["default"];
        var CoreObject = __dependency14__["default"];
        var EachArray = __dependency15__.EachArray;
        var EachProxy = __dependency15__.EachProxy;

        var NativeArray = __dependency16__["default"];
        var Set = __dependency17__["default"];
        var EmberStringUtils = __dependency18__["default"];
        var Deferred = __dependency19__["default"];
        var onLoad = __dependency20__.onLoad;
        var runLoadHooks = __dependency20__.runLoadHooks;

        var EmberArray = __dependency21__["default"];
        var Comparable = __dependency22__["default"];
        var Copyable = __dependency23__["default"];
        var Enumerable = __dependency24__["default"];
        var Freezable = __dependency25__.Freezable;
        var FROZEN_ERROR = __dependency25__.FROZEN_ERROR;

        var Observable = __dependency26__["default"];
        var ActionHandler = __dependency27__["default"];
        var DeferredMixin = __dependency28__["default"];
        var MutableEnumerable = __dependency29__["default"];
        var MutableArray = __dependency30__["default"];
        var TargetActionSupport = __dependency31__["default"];
        var Evented = __dependency32__["default"];
        var PromiseProxyMixin = __dependency33__["default"];
        var SortableMixin = __dependency34__["default"];
        var arrayComputed = __dependency35__.arrayComputed;
        var ArrayComputedProperty = __dependency35__.ArrayComputedProperty;

        var reduceComputed = __dependency36__.reduceComputed;
        var ReduceComputedProperty = __dependency36__.ReduceComputedProperty;

        var sum = __dependency37__.sum;
        var min = __dependency37__.min;
        var max = __dependency37__.max;
        var map = __dependency37__.map;
        var sort = __dependency37__.sort;
        var setDiff = __dependency37__.setDiff;
        var mapBy = __dependency37__.mapBy;
        var mapProperty = __dependency37__.mapProperty;
        var filter = __dependency37__.filter;
        var filterBy = __dependency37__.filterBy;
        var filterProperty = __dependency37__.filterProperty;
        var uniq = __dependency37__.uniq;
        var union = __dependency37__.union;
        var intersect = __dependency37__.intersect;

        var ArrayController = __dependency38__["default"];
        var ObjectController = __dependency39__["default"];
        var Controller = __dependency40__["default"];
        var ControllerMixin = __dependency41__["default"];

        var RSVP = __dependency42__["default"];
        // just for side effect of extending Ember.RSVP
        // just for side effect of extending String.prototype
        // just for side effect of extending Function.prototype
        // END IMPORTS

        // BEGIN EXPORTS
        Ember.compare = compare;
        Ember.copy = copy;
        Ember.isEqual = isEqual;
        Ember.keys = keys;

        Ember.Array = EmberArray;

        Ember.Comparable = Comparable;
        Ember.Copyable = Copyable;

        Ember.SortableMixin = SortableMixin;

        Ember.Freezable = Freezable;
        Ember.FROZEN_ERROR = FROZEN_ERROR;

        Ember.DeferredMixin = DeferredMixin;

        Ember.MutableEnumerable = MutableEnumerable;
        Ember.MutableArray = MutableArray;

        Ember.TargetActionSupport = TargetActionSupport;
        Ember.Evented = Evented;

        Ember.PromiseProxyMixin = PromiseProxyMixin;

        Ember.Observable = Observable;

        Ember.arrayComputed = arrayComputed;
        Ember.ArrayComputedProperty = ArrayComputedProperty;
        Ember.reduceComputed = reduceComputed;
        Ember.ReduceComputedProperty = ReduceComputedProperty;

        // ES6TODO: this seems a less than ideal way/place to add properties to Ember.computed
        var EmComputed = Ember.computed;

        EmComputed.sum = sum;
        EmComputed.min = min;
        EmComputed.max = max;
        EmComputed.map = map;
        EmComputed.sort = sort;
        EmComputed.setDiff = setDiff;
        EmComputed.mapBy = mapBy;
        EmComputed.mapProperty = mapProperty;
        EmComputed.filter = filter;
        EmComputed.filterBy = filterBy;
        EmComputed.filterProperty = filterProperty;
        EmComputed.uniq = uniq;
        EmComputed.union = union;
        EmComputed.intersect = intersect;

        Ember.String = EmberStringUtils;
        Ember.Object = EmberObject;
        Ember.TrackedArray = TrackedArray;
        Ember.SubArray = SubArray;
        Ember.Container = Container;
        Ember.Namespace = Namespace;
        Ember.Enumerable = Enumerable;
        Ember.ArrayProxy = ArrayProxy;
        Ember.ObjectProxy = ObjectProxy;
        Ember.ActionHandler = ActionHandler;
        Ember.CoreObject = CoreObject;
        Ember.EachArray = EachArray;
        Ember.EachProxy = EachProxy;
        Ember.NativeArray = NativeArray;
        // ES6TODO: Currently we must rely on the global from ember-metal/core to avoid circular deps
        // Ember.A = A;
        Ember.Set = Set;
        Ember.Deferred = Deferred;
        Ember.onLoad = onLoad;
        Ember.runLoadHooks = runLoadHooks;

        Ember.ArrayController = ArrayController;
        Ember.ObjectController = ObjectController;
        Ember.Controller = Controller;
        Ember.ControllerMixin = ControllerMixin;

        Ember.RSVP = RSVP;
        // END EXPORTS

        __exports__["default"] = Ember;
    });
    define("ember-runtime/compare",
    ["ember-metal/core", "ember-metal/utils", "ember-runtime/mixins/comparable", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // for Ember.ORDER_DEFINITION
        var typeOf = __dependency2__.typeOf;
        var Comparable = __dependency3__["default"];

        // Used by Ember.compare
        Ember.ORDER_DEFINITION = Ember.ENV.ORDER_DEFINITION || [
        'undefined',
        'null',
        'boolean',
        'number',
        'string',
        'array',
        'object',
        'instance',
        'function',
        'class',
        'date'
        ];

        /**
             This will compare two javascript values of possibly different types.
             It will tell you which one is greater than the other by returning:

              - -1 if the first is smaller than the second,
              - 0 if both are equal,
              - 1 if the first is greater than the second.

             The order is calculated based on `Ember.ORDER_DEFINITION`, if types are different.
             In case they have the same type an appropriate comparison for this type is made.

              ```javascript
              Ember.compare('hello', 'hello');  // 0
              Ember.compare('abc', 'dfg');      // -1
              Ember.compare(2, 1);              // 1
              ```

             @method compare
             @for Ember
             @param {Object} v First value to compare
             @param {Object} w Second value to compare
             @return {Number} -1 if v < w, 0 if v = w and 1 if v > w.
            */
        __exports__["default"] = function compare(v, w) {
            if (v === w) {
                return 0;
            }

            var type1 = typeOf(v);
            var type2 = typeOf(w);

            if (Comparable) {
                if (type1 === 'instance' && Comparable.detect(v.constructor)) {
                    return v.constructor.compare(v, w);
                }

                if (type2 === 'instance' && Comparable.detect(w.constructor)) {
                    return 1 - w.constructor.compare(w, v);
                }
            }

            // If we haven't yet generated a reverse-mapping of Ember.ORDER_DEFINITION,
            // do so now.
            var mapping = Ember.ORDER_DEFINITION_MAPPING;
            if (!mapping) {
                var order = Ember.ORDER_DEFINITION;
                mapping = Ember.ORDER_DEFINITION_MAPPING = {};
                var idx, len;
                for (idx = 0, len = order.length; idx < len; ++idx) {
                    mapping[order[idx]] = idx;
                }

                // We no longer need Ember.ORDER_DEFINITION.
                delete Ember.ORDER_DEFINITION;
            }

            var type1Index = mapping[type1];
            var type2Index = mapping[type2];

            if (type1Index < type2Index) {
                return -1;
            }
            if (type1Index > type2Index) {
                return 1;
            }

            // types are equal - so we have to check values now
            switch (type1) {
            case 'boolean':
            case 'number':
                if (v < w) {
                    return -1;
                }
                if (v > w) {
                    return 1;
                }
                return 0;

            case 'string':
                var comp = v.localeCompare(w);
                if (comp < 0) {
                    return -1;
                }
                if (comp > 0) {
                    return 1;
                }
                return 0;

            case 'array':
                var vLen = v.length;
                var wLen = w.length;
                var l = Math.min(vLen, wLen);
                var r = 0;
                var i = 0;
                while (r === 0 && i < l) {
                    r = compare(v[i], w[i]);
                    i++;
                }
                if (r !== 0) {
                    return r;
                }

                // all elements are equal now
                // shorter array should be ordered first
                if (vLen < wLen) {
                    return -1;
                }
                if (vLen > wLen) {
                    return 1;
                }
                // arrays are equal now
                return 0;

            case 'instance':
                if (Comparable && Comparable.detect(v)) {
                    return v.compare(v, w);
                }
                return 0;

            case 'date':
                var vNum = v.getTime();
                var wNum = w.getTime();
                if (vNum < wNum) {
                    return -1;
                }
                if (vNum > wNum) {
                    return 1;
                }
                return 0;

            default:
                return 0;
            }
        }
    });
    define("ember-runtime/computed/array_computed",
    ["ember-metal/core", "ember-runtime/computed/reduce_computed", "ember-metal/enumerable_utils", "ember-metal/platform", "ember-metal/observer", "ember-metal/error", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        var reduceComputed = __dependency2__.reduceComputed;
        var ReduceComputedProperty = __dependency2__.ReduceComputedProperty;
        var forEach = __dependency3__.forEach;
        var o_create = __dependency4__.create;
        var addObserver = __dependency5__.addObserver;
        var EmberError = __dependency6__["default"];

        var a_slice = [].slice;

        function ArrayComputedProperty() {
            var cp = this;

            ReduceComputedProperty.apply(this, arguments);

            this.func = (function(reduceFunc) {
                return function (propertyName) {
                    if (!cp._hasInstanceMeta(this, propertyName)) {
                        // When we recompute an array computed property, we need already
                        // retrieved arrays to be updated; we can't simply empty the cache and
                        // hope the array is re-retrieved.
                        forEach(cp._dependentKeys, function(dependentKey) {
                            addObserver(this, dependentKey, function() {
                                cp.recomputeOnce.call(this, propertyName);
                            });
                        }, this);
                    }

                    return reduceFunc.apply(this, arguments);
                };
            })(this.func);

            return this;
        }

        ArrayComputedProperty.prototype = o_create(ReduceComputedProperty.prototype);
        ArrayComputedProperty.prototype.initialValue = function () {
            return Ember.A();
        };
        ArrayComputedProperty.prototype.resetValue = function (array) {
            array.clear();
            return array;
        };

        // This is a stopgap to keep the reference counts correct with lazy CPs.
        ArrayComputedProperty.prototype.didChange = function (obj, keyName) {
            return;
        };

        /**
              Creates a computed property which operates on dependent arrays and
              is updated with "one at a time" semantics. When items are added or
              removed from the dependent array(s) an array computed only operates
              on the change instead of re-evaluating the entire array. This should
              return an array, if you'd like to use "one at a time" semantics and
              compute some value other then an array look at
              `Ember.reduceComputed`.

              If there are more than one arguments the first arguments are
              considered to be dependent property keys. The last argument is
              required to be an options object. The options object can have the
              following three properties.

              `initialize` - An optional initialize function. Typically this will be used
              to set up state on the instanceMeta object.

              `removedItem` - A function that is called each time an element is
              removed from the array.

              `addedItem` - A function that is called each time an element is
              added to the array.


              The `initialize` function has the following signature:

              ```javascript
              function(array, changeMeta, instanceMeta)
              ```

              `array` - The initial value of the arrayComputed, an empty array.

              `changeMeta` - An object which contains meta information about the
              computed. It contains the following properties:

                 - `property` the computed property
                 - `propertyName` the name of the property on the object

              `instanceMeta` - An object that can be used to store meta
              information needed for calculating your computed. For example a
              unique computed might use this to store the number of times a given
              element is found in the dependent array.


              The `removedItem` and `addedItem` functions both have the following signature:

              ```javascript
              function(accumulatedValue, item, changeMeta, instanceMeta)
              ```

              `accumulatedValue` - The value returned from the last time
              `removedItem` or `addedItem` was called or an empty array.

              `item` - the element added or removed from the array

              `changeMeta` - An object which contains meta information about the
              change. It contains the following properties:

                - `property` the computed property
                - `propertyName` the name of the property on the object
                - `index` the index of the added or removed item
                - `item` the added or removed item: this is exactly the same as
                  the second arg
                - `arrayChanged` the array that triggered the change. Can be
                  useful when depending on multiple arrays.

              For property changes triggered on an item property change (when
              depKey is something like `someArray.@each.someProperty`),
              `changeMeta` will also contain the following property:

                - `previousValues` an object whose keys are the properties that changed on
                the item, and whose values are the item's previous values.

              `previousValues` is important Ember coalesces item property changes via
              Ember.run.once. This means that by the time removedItem gets called, item has
              the new values, but you may need the previous value (eg for sorting &
              filtering).

              `instanceMeta` - An object that can be used to store meta
              information needed for calculating your computed. For example a
              unique computed might use this to store the number of times a given
              element is found in the dependent array.

              The `removedItem` and `addedItem` functions should return the accumulated
              value. It is acceptable to not return anything (ie return undefined)
              to invalidate the computation. This is generally not a good idea for
              arrayComputed but it's used in eg max and min.

              Example

              ```javascript
              Ember.computed.map = function(dependentKey, callback) {
                var options = {
                  addedItem: function(array, item, changeMeta, instanceMeta) {
                    var mapped = callback(item);
                    array.insertAt(changeMeta.index, mapped);
                    return array;
                  },
                  removedItem: function(array, item, changeMeta, instanceMeta) {
                    array.removeAt(changeMeta.index, 1);
                    return array;
                  }
                };

                return Ember.arrayComputed(dependentKey, options);
              };
              ```

              @method arrayComputed
              @for Ember
              @param {String} [dependentKeys*]
              @param {Object} options
              @return {Ember.ComputedProperty}
            */
        function arrayComputed (options) {
            var args;

            if (arguments.length > 1) {
                args = a_slice.call(arguments, 0, -1);
                options = a_slice.call(arguments, -1)[0];
            }

            if (typeof options !== "object") {
                throw new EmberError("Array Computed Property declared without an options hash");
            }

            var cp = new ArrayComputedProperty(options);

            if (args) {
                cp.property.apply(cp, args);
            }

            return cp;
        }

        __exports__.arrayComputed = arrayComputed;
        __exports__.ArrayComputedProperty = ArrayComputedProperty;
    });
    define("ember-runtime/computed/reduce_computed",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/utils", "ember-metal/error", "ember-metal/property_events", "ember-metal/expand_properties", "ember-metal/observer", "ember-metal/computed", "ember-metal/platform", "ember-metal/enumerable_utils", "ember-runtime/system/tracked_array", "ember-runtime/mixins/array", "ember-metal/run_loop", "ember-runtime/system/set", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // Ember.assert
        var e_get = __dependency2__.get;
        var set = __dependency3__.set;
        var guidFor = __dependency4__.guidFor;
        var metaFor = __dependency4__.meta;
        var EmberError = __dependency5__["default"];
        var propertyWillChange = __dependency6__.propertyWillChange;
        var propertyDidChange = __dependency6__.propertyDidChange;
        var expandProperties = __dependency7__["default"];
        var addObserver = __dependency8__.addObserver;
        var observersFor = __dependency8__.observersFor;
        var removeObserver = __dependency8__.removeObserver;
        var addBeforeObserver = __dependency8__.addBeforeObserver;
        var removeBeforeObserver = __dependency8__.removeBeforeObserver;
        var ComputedProperty = __dependency9__.ComputedProperty;
        var cacheFor = __dependency9__.cacheFor;
        var o_create = __dependency10__.create;
        var forEach = __dependency11__.forEach;
        var TrackedArray = __dependency12__["default"];
        var EmberArray = __dependency13__["default"];
        var run = __dependency14__["default"];
        var Set = __dependency15__["default"];
        var isArray = __dependency4__.isArray;

        var cacheSet = cacheFor.set;
        var cacheGet = cacheFor.get;
        var cacheRemove = cacheFor.remove;
        var a_slice = [].slice;
        // Here we explicitly don't allow `@each.foo`; it would require some special
        // testing, but there's no particular reason why it should be disallowed.
        var eachPropertyPattern = /^(.*)\.@each\.(.*)/;
        var doubleEachPropertyPattern = /(.*\.@each){2,}/;
        var arrayBracketPattern = /\.\[\]$/;

        function get(obj, key) {
            if (key === '@this') {
                return obj;
            }

            return e_get(obj, key);
        }

        /*
              Tracks changes to dependent arrays, as well as to properties of items in
              dependent arrays.

              @class DependentArraysObserver
            */
        function DependentArraysObserver(callbacks, cp, instanceMeta, context, propertyName, sugarMeta) {
            // user specified callbacks for `addedItem` and `removedItem`
            this.callbacks = callbacks;

            // the computed property: remember these are shared across instances
            this.cp = cp;

            // the ReduceComputedPropertyInstanceMeta this DependentArraysObserver is
            // associated with
            this.instanceMeta = instanceMeta;

            // A map of array guids to dependentKeys, for the given context.  We track
            // this because we want to set up the computed property potentially before the
            // dependent array even exists, but when the array observer fires, we lack
            // enough context to know what to update: we can recover that context by
            // getting the dependentKey.
            this.dependentKeysByGuid = {};

            // a map of dependent array guids -> TrackedArray instances.  We use
            // this to lazily recompute indexes for item property observers.
            this.trackedArraysByGuid = {};

            // We suspend observers to ignore replacements from `reset` when totally
            // recomputing.  Unfortunately we cannot properly suspend the observers
            // because we only have the key; instead we make the observers no-ops
            this.suspended = false;

            // This is used to coalesce item changes from property observers within a
            // single item.
            this.changedItems = {};
            // This is used to coalesce item changes for multiple items that depend on
            // some shared state.
            this.changedItemCount = 0;
        }

        function ItemPropertyObserverContext (dependentArray, index, trackedArray) {
            Ember.assert("Internal error: trackedArray is null or undefined", trackedArray);

            this.dependentArray = dependentArray;
            this.index = index;
            this.item = dependentArray.objectAt(index);
            this.trackedArray = trackedArray;
            this.beforeObserver = null;
            this.observer = null;

            this.destroyed = false;
        }

        DependentArraysObserver.prototype = {
            setValue: function (newValue) {
                this.instanceMeta.setValue(newValue, true);
            },
            getValue: function () {
                return this.instanceMeta.getValue();
            },

            setupObservers: function (dependentArray, dependentKey) {
                this.dependentKeysByGuid[guidFor(dependentArray)] = dependentKey;

                dependentArray.addArrayObserver(this, {
                    willChange: 'dependentArrayWillChange',
                    didChange: 'dependentArrayDidChange'
                });

                if (this.cp._itemPropertyKeys[dependentKey]) {
                    this.setupPropertyObservers(dependentKey, this.cp._itemPropertyKeys[dependentKey]);
                }
            },

            teardownObservers: function (dependentArray, dependentKey) {
                var itemPropertyKeys = this.cp._itemPropertyKeys[dependentKey] || [];

                delete this.dependentKeysByGuid[guidFor(dependentArray)];

                this.teardownPropertyObservers(dependentKey, itemPropertyKeys);

                dependentArray.removeArrayObserver(this, {
                    willChange: 'dependentArrayWillChange',
                    didChange: 'dependentArrayDidChange'
                });
            },

            suspendArrayObservers: function (callback, binding) {
                var oldSuspended = this.suspended;
                this.suspended = true;
                callback.call(binding);
                this.suspended = oldSuspended;
            },

            setupPropertyObservers: function (dependentKey, itemPropertyKeys) {
                var dependentArray = get(this.instanceMeta.context, dependentKey),
                length = get(dependentArray, 'length'),
                observerContexts = new Array(length);

                this.resetTransformations(dependentKey, observerContexts);

                forEach(dependentArray, function (item, index) {
                    var observerContext = this.createPropertyObserverContext(dependentArray, index, this.trackedArraysByGuid[dependentKey]);
                    observerContexts[index] = observerContext;

                    forEach(itemPropertyKeys, function (propertyKey) {
                        addBeforeObserver(item, propertyKey, this, observerContext.beforeObserver);
                        addObserver(item, propertyKey, this, observerContext.observer);
                    }, this);
                }, this);
            },

            teardownPropertyObservers: function (dependentKey, itemPropertyKeys) {
                var dependentArrayObserver = this,
                trackedArray = this.trackedArraysByGuid[dependentKey],
                beforeObserver,
                observer,
                item;

                if (!trackedArray) {
                    return;
                }

                trackedArray.apply(function (observerContexts, offset, operation) {
                    if (operation === TrackedArray.DELETE) {
                        return;
                    }

                    forEach(observerContexts, function (observerContext) {
                        observerContext.destroyed = true;
                        beforeObserver = observerContext.beforeObserver;
                        observer = observerContext.observer;
                        item = observerContext.item;

                        forEach(itemPropertyKeys, function (propertyKey) {
                            removeBeforeObserver(item, propertyKey, dependentArrayObserver, beforeObserver);
                            removeObserver(item, propertyKey, dependentArrayObserver, observer);
                        });
                    });
                });
            },

            createPropertyObserverContext: function (dependentArray, index, trackedArray) {
                var observerContext = new ItemPropertyObserverContext(dependentArray, index, trackedArray);

                this.createPropertyObserver(observerContext);

                return observerContext;
            },

            createPropertyObserver: function (observerContext) {
                var dependentArrayObserver = this;

                observerContext.beforeObserver = function (obj, keyName) {
                    return dependentArrayObserver.itemPropertyWillChange(obj, keyName, observerContext.dependentArray, observerContext);
                };
                observerContext.observer = function (obj, keyName) {
                    return dependentArrayObserver.itemPropertyDidChange(obj, keyName, observerContext.dependentArray, observerContext);
                };
            },

            resetTransformations: function (dependentKey, observerContexts) {
                this.trackedArraysByGuid[dependentKey] = new TrackedArray(observerContexts);
            },

            trackAdd: function (dependentKey, index, newItems) {
                var trackedArray = this.trackedArraysByGuid[dependentKey];
                if (trackedArray) {
                    trackedArray.addItems(index, newItems);
                }
            },

            trackRemove: function (dependentKey, index, removedCount) {
                var trackedArray = this.trackedArraysByGuid[dependentKey];

                if (trackedArray) {
                    return trackedArray.removeItems(index, removedCount);
                }

                return [];
            },

            updateIndexes: function (trackedArray, array) {
                var length = get(array, 'length');
                // OPTIMIZE: we could stop updating once we hit the object whose observer
                // fired; ie partially apply the transformations
                trackedArray.apply(function (observerContexts, offset, operation, operationIndex) {
                    // we don't even have observer contexts for removed items, even if we did,
                    // they no longer have any index in the array
                    if (operation === TrackedArray.DELETE) {
                        return;
                    }
                    if (operationIndex === 0 && operation === TrackedArray.RETAIN && observerContexts.length === length && offset === 0) {
                        // If we update many items we don't want to walk the array each time: we
                        // only need to update the indexes at most once per run loop.
                        return;
                    }

                    forEach(observerContexts, function (context, index) {
                        context.index = index + offset;
                    });
                });
            },

            dependentArrayWillChange: function (dependentArray, index, removedCount, addedCount) {
                if (this.suspended) {
                    return;
                }

                var removedItem = this.callbacks.removedItem;
                var changeMeta;
                var guid = guidFor(dependentArray);
                var dependentKey = this.dependentKeysByGuid[guid];
                var itemPropertyKeys = this.cp._itemPropertyKeys[dependentKey] || [];
                var length = get(dependentArray, 'length');
                var normalizedIndex = normalizeIndex(index, length, 0);
                var normalizedRemoveCount = normalizeRemoveCount(normalizedIndex, length, removedCount);
                var item, itemIndex, sliceIndex, observerContexts;

                observerContexts = this.trackRemove(dependentKey, normalizedIndex, normalizedRemoveCount);

                function removeObservers(propertyKey) {
                    observerContexts[sliceIndex].destroyed = true;
                    removeBeforeObserver(item, propertyKey, this, observerContexts[sliceIndex].beforeObserver);
                    removeObserver(item, propertyKey, this, observerContexts[sliceIndex].observer);
                }

                for (sliceIndex = normalizedRemoveCount - 1; sliceIndex >= 0; --sliceIndex) {
                    itemIndex = normalizedIndex + sliceIndex;
                    if (itemIndex >= length) {
                        break;
                    }

                    item = dependentArray.objectAt(itemIndex);

                    forEach(itemPropertyKeys, removeObservers, this);

                    changeMeta = new ChangeMeta(dependentArray, item, itemIndex, this.instanceMeta.propertyName, this.cp, normalizedRemoveCount);
                    this.setValue( removedItem.call(
                    this.instanceMeta.context, this.getValue(), item, changeMeta, this.instanceMeta.sugarMeta));
                }
            },

            dependentArrayDidChange: function (dependentArray, index, removedCount, addedCount) {
                if (this.suspended) {
                    return;
                }

                var addedItem = this.callbacks.addedItem;
                var guid = guidFor(dependentArray);
                var dependentKey = this.dependentKeysByGuid[guid];
                var observerContexts = new Array(addedCount);
                var itemPropertyKeys = this.cp._itemPropertyKeys[dependentKey];
                var length = get(dependentArray, 'length');
                var normalizedIndex = normalizeIndex(index, length, addedCount);
                var changeMeta, observerContext;

                forEach(dependentArray.slice(normalizedIndex, normalizedIndex + addedCount), function (item, sliceIndex) {
                    if (itemPropertyKeys) {
                        observerContext =
                        observerContexts[sliceIndex] =
                        this.createPropertyObserverContext(dependentArray, normalizedIndex + sliceIndex, this.trackedArraysByGuid[dependentKey]);
                        forEach(itemPropertyKeys, function (propertyKey) {
                            addBeforeObserver(item, propertyKey, this, observerContext.beforeObserver);
                            addObserver(item, propertyKey, this, observerContext.observer);
                        }, this);
                    }

                    changeMeta = new ChangeMeta(dependentArray, item, normalizedIndex + sliceIndex, this.instanceMeta.propertyName, this.cp, addedCount);
                    this.setValue( addedItem.call(
                    this.instanceMeta.context, this.getValue(), item, changeMeta, this.instanceMeta.sugarMeta));
                }, this);

                this.trackAdd(dependentKey, normalizedIndex, observerContexts);
            },

            itemPropertyWillChange: function (obj, keyName, array, observerContext) {
                var guid = guidFor(obj);

                if (!this.changedItems[guid]) {
                    this.changedItems[guid] = {
                        array: array,
                        observerContext: observerContext,
                        obj: obj,
                        previousValues: {}
                    };
                }
                ++this.changedItemCount;

                this.changedItems[guid].previousValues[keyName] = get(obj, keyName);
            },

            itemPropertyDidChange: function(obj, keyName, array, observerContext) {
                if (--this.changedItemCount === 0) {
                    this.flushChanges();
                }
            },

            flushChanges: function() {
                var changedItems = this.changedItems, key, c, changeMeta;

                for (key in changedItems) {
                    c = changedItems[key];
                    if (c.observerContext.destroyed) {
                        continue;
                    }

                    this.updateIndexes(c.observerContext.trackedArray, c.observerContext.dependentArray);

                    changeMeta = new ChangeMeta(c.array, c.obj, c.observerContext.index, this.instanceMeta.propertyName, this.cp, changedItems.length, c.previousValues);
                    this.setValue(
                    this.callbacks.removedItem.call(this.instanceMeta.context, this.getValue(), c.obj, changeMeta, this.instanceMeta.sugarMeta));
                    this.setValue(
                    this.callbacks.addedItem.call(this.instanceMeta.context, this.getValue(), c.obj, changeMeta, this.instanceMeta.sugarMeta));
                }
                this.changedItems = {};
            }
        };

        function normalizeIndex(index, length, newItemsOffset) {
            if (index < 0) {
                return Math.max(0, length + index);
            } else if (index < length) {
                return index;
            } else /* index > length */
            {
                return Math.min(length - newItemsOffset, index);
            }
        }

        function normalizeRemoveCount(index, length, removedCount) {
            return Math.min(removedCount, length - index);
        }

        function ChangeMeta(dependentArray, item, index, propertyName, property, changedCount, previousValues) {
            this.arrayChanged = dependentArray;
            this.index = index;
            this.item = item;
            this.propertyName = propertyName;
            this.property = property;
            this.changedCount = changedCount;

            if (previousValues) {
                // previous values only available for item property changes
                this.previousValues = previousValues;
            }
        }

        function addItems (dependentArray, callbacks, cp, propertyName, meta) {
            forEach(dependentArray, function (item, index) {
                meta.setValue( callbacks.addedItem.call(
                this, meta.getValue(), item, new ChangeMeta(dependentArray, item, index, propertyName, cp, dependentArray.length), meta.sugarMeta));
            }, this);
        }

        function reset(cp, propertyName) {
            var callbacks = cp._callbacks(),
            meta;

            if (cp._hasInstanceMeta(this, propertyName)) {
                meta = cp._instanceMeta(this, propertyName);
                meta.setValue(cp.resetValue(meta.getValue()));
            } else {
                meta = cp._instanceMeta(this, propertyName);
            }

            if (cp.options.initialize) {
                cp.options.initialize.call(this, meta.getValue(), {
                    property: cp,
                    propertyName: propertyName 
                }, meta.sugarMeta);
            }
        }

        function partiallyRecomputeFor(obj, dependentKey) {
            if (arrayBracketPattern.test(dependentKey)) {
                return false;
            }

            var value = get(obj, dependentKey);
            return EmberArray.detect(value);
        }

        function ReduceComputedPropertyInstanceMeta(context, propertyName, initialValue) {
            this.context = context;
            this.propertyName = propertyName;
            this.cache = metaFor(context).cache;

            this.dependentArrays = {};
            this.sugarMeta = {};

            this.initialValue = initialValue;
        }

        ReduceComputedPropertyInstanceMeta.prototype = {
            getValue: function () {
                var value = cacheGet(this.cache, this.propertyName);
                if (value !== undefined) {
                    return value;
                } else {
                    return this.initialValue;
                }
            },

            setValue: function(newValue, triggerObservers) {
                // This lets sugars force a recomputation, handy for very simple
                // implementations of eg max.
                if (newValue === cacheGet(this.cache, this.propertyName)) {
                    return;
                }

                if (triggerObservers) {
                    propertyWillChange(this.context, this.propertyName);
                }

                if (newValue === undefined) {
                    cacheRemove(this.cache, this.propertyName);
                } else {
                    cacheSet(this.cache, this.propertyName, newValue);
                }

                if (triggerObservers) {
                    propertyDidChange(this.context, this.propertyName);
                }
            }
        };

        /**
              A computed property whose dependent keys are arrays and which is updated with
              "one at a time" semantics.

              @class ReduceComputedProperty
              @namespace Ember
              @extends Ember.ComputedProperty
              @constructor
            */

        __exports__.ReduceComputedProperty = ReduceComputedProperty;
        // TODO: default export
        function ReduceComputedProperty(options) {
            var cp = this;

            this.options = options;

            this._dependentKeys = null;
            // A map of dependentKey -> [itemProperty, ...] that tracks what properties of
            // items in the array we must track to update this property.
            this._itemPropertyKeys = {};
            this._previousItemPropertyKeys = {};

            this.readOnly();
            this.cacheable();

            this.recomputeOnce = function(propertyName) {
                // What we really want to do is coalesce by <cp, propertyName>.
                // We need a form of `scheduleOnce` that accepts an arbitrary token to
                // coalesce by, in addition to the target and method.
                run.once(this, recompute, propertyName);
            };
            var recompute = function(propertyName) {
                var dependentKeys = cp._dependentKeys,
                meta = cp._instanceMeta(this, propertyName),
                callbacks = cp._callbacks();

                reset.call(this, cp, propertyName);

                meta.dependentArraysObserver.suspendArrayObservers(function () {
                    forEach(cp._dependentKeys, function (dependentKey) {
                        Ember.assert(
                        "dependent array " + dependentKey + " must be an `Ember.Array`.  " +
                        "If you are not extending arrays, you will need to wrap native arrays with `Ember.A`",
                        !(isArray(get(this, dependentKey)) && !EmberArray.detect(get(this, dependentKey))));

                        if (!partiallyRecomputeFor(this, dependentKey)) {
                            return;
                        }

                        var dependentArray = get(this, dependentKey),
                        previousDependentArray = meta.dependentArrays[dependentKey];

                        if (dependentArray === previousDependentArray) {
                            // The array may be the same, but our item property keys may have
                            // changed, so we set them up again.  We can't easily tell if they've
                            // changed: the array may be the same object, but with different
                            // contents.
                            if (cp._previousItemPropertyKeys[dependentKey]) {
                                delete cp._previousItemPropertyKeys[dependentKey];
                                meta.dependentArraysObserver.setupPropertyObservers(dependentKey, cp._itemPropertyKeys[dependentKey]);
                            }
                        } else {
                            meta.dependentArrays[dependentKey] = dependentArray;

                            if (previousDependentArray) {
                                meta.dependentArraysObserver.teardownObservers(previousDependentArray, dependentKey);
                            }

                            if (dependentArray) {
                                meta.dependentArraysObserver.setupObservers(dependentArray, dependentKey);
                            }
                        }
                    }, this);
                }, this);

                forEach(cp._dependentKeys, function(dependentKey) {
                    if (!partiallyRecomputeFor(this, dependentKey)) {
                        return;
                    }

                    var dependentArray = get(this, dependentKey);
                    if (dependentArray) {
                        addItems.call(this, dependentArray, callbacks, cp, propertyName, meta);
                    }
                }, this);
            };


            this.func = function (propertyName) {
                Ember.assert("Computed reduce values require at least one dependent key", cp._dependentKeys);

                recompute.call(this, propertyName);

                return cp._instanceMeta(this, propertyName).getValue();
            };
        }

        ReduceComputedProperty.prototype = o_create(ComputedProperty.prototype);

        function defaultCallback(computedValue) {
            return computedValue;
        }

        ReduceComputedProperty.prototype._callbacks = function () {
            if (!this.callbacks) {
                var options = this.options;
                this.callbacks = {
                    removedItem: options.removedItem || defaultCallback,
                    addedItem: options.addedItem || defaultCallback
                };
            }
            return this.callbacks;
        };

        ReduceComputedProperty.prototype._hasInstanceMeta = function (context, propertyName) {
            return !!metaFor(context).cacheMeta[propertyName];
        };

        ReduceComputedProperty.prototype._instanceMeta = function (context, propertyName) {
            var cacheMeta = metaFor(context).cacheMeta,
            meta = cacheMeta[propertyName];

            if (!meta) {
                meta = cacheMeta[propertyName] = new ReduceComputedPropertyInstanceMeta(context, propertyName, this.initialValue());
                meta.dependentArraysObserver = new DependentArraysObserver(this._callbacks(), this, meta, context, propertyName, meta.sugarMeta);
            }

            return meta;
        };

        ReduceComputedProperty.prototype.initialValue = function () {
            if (typeof this.options.initialValue === 'function') {
                return this.options.initialValue();
            } else {
                return this.options.initialValue;
            }
        };

        ReduceComputedProperty.prototype.resetValue = function (value) {
            return this.initialValue();
        };

        ReduceComputedProperty.prototype.itemPropertyKey = function (dependentArrayKey, itemPropertyKey) {
            this._itemPropertyKeys[dependentArrayKey] = this._itemPropertyKeys[dependentArrayKey] || [];
            this._itemPropertyKeys[dependentArrayKey].push(itemPropertyKey);
        };

        ReduceComputedProperty.prototype.clearItemPropertyKeys = function (dependentArrayKey) {
            if (this._itemPropertyKeys[dependentArrayKey]) {
                this._previousItemPropertyKeys[dependentArrayKey] = this._itemPropertyKeys[dependentArrayKey];
                this._itemPropertyKeys[dependentArrayKey] = [];
            }
        };

        ReduceComputedProperty.prototype.property = function () {
            var cp = this,
            args = a_slice.call(arguments),
            propertyArgs = new Set(),
            match,
            dependentArrayKey,
            itemPropertyKey;

            forEach(args, function (dependentKey) {
                if (doubleEachPropertyPattern.test(dependentKey)) {
                    throw new EmberError("Nested @each properties not supported: " + dependentKey);
                } else if (match = eachPropertyPattern.exec(dependentKey)) {
                    dependentArrayKey = match[1];

                    var itemPropertyKeyPattern = match[2],
                    addItemPropertyKey = function (itemPropertyKey) {
                        cp.itemPropertyKey(dependentArrayKey, itemPropertyKey);
                    };

                    expandProperties(itemPropertyKeyPattern, addItemPropertyKey);
                    propertyArgs.add(dependentArrayKey);
                } else {
                    propertyArgs.add(dependentKey);
                }
            });

            return ComputedProperty.prototype.property.apply(this, propertyArgs.toArray());

        };

        /**
              Creates a computed property which operates on dependent arrays and
              is updated with "one at a time" semantics. When items are added or
              removed from the dependent array(s) a reduce computed only operates
              on the change instead of re-evaluating the entire array.

              If there are more than one arguments the first arguments are
              considered to be dependent property keys. The last argument is
              required to be an options object. The options object can have the
              following four properties:

              `initialValue` - A value or function that will be used as the initial
              value for the computed. If this property is a function the result of calling
              the function will be used as the initial value. This property is required.

              `initialize` - An optional initialize function. Typically this will be used
              to set up state on the instanceMeta object.

              `removedItem` - A function that is called each time an element is removed
              from the array.

              `addedItem` - A function that is called each time an element is added to
              the array.


              The `initialize` function has the following signature:

              ```javascript
              function(initialValue, changeMeta, instanceMeta)
              ```

              `initialValue` - The value of the `initialValue` property from the
              options object.

              `changeMeta` - An object which contains meta information about the
              computed. It contains the following properties:

                 - `property` the computed property
                 - `propertyName` the name of the property on the object

              `instanceMeta` - An object that can be used to store meta
              information needed for calculating your computed. For example a
              unique computed might use this to store the number of times a given
              element is found in the dependent array.


              The `removedItem` and `addedItem` functions both have the following signature:

              ```javascript
              function(accumulatedValue, item, changeMeta, instanceMeta)
              ```

              `accumulatedValue` - The value returned from the last time
              `removedItem` or `addedItem` was called or `initialValue`.

              `item` - the element added or removed from the array

              `changeMeta` - An object which contains meta information about the
              change. It contains the following properties:

                - `property` the computed property
                - `propertyName` the name of the property on the object
                - `index` the index of the added or removed item
                - `item` the added or removed item: this is exactly the same as
                  the second arg
                - `arrayChanged` the array that triggered the change. Can be
                  useful when depending on multiple arrays.

              For property changes triggered on an item property change (when
              depKey is something like `someArray.@each.someProperty`),
              `changeMeta` will also contain the following property:

                - `previousValues` an object whose keys are the properties that changed on
                the item, and whose values are the item's previous values.

              `previousValues` is important Ember coalesces item property changes via
              Ember.run.once. This means that by the time removedItem gets called, item has
              the new values, but you may need the previous value (eg for sorting &
              filtering).

              `instanceMeta` - An object that can be used to store meta
              information needed for calculating your computed. For example a
              unique computed might use this to store the number of times a given
              element is found in the dependent array.

              The `removedItem` and `addedItem` functions should return the accumulated
              value. It is acceptable to not return anything (ie return undefined)
              to invalidate the computation. This is generally not a good idea for
              arrayComputed but it's used in eg max and min.

              Note that observers will be fired if either of these functions return a value
              that differs from the accumulated value.  When returning an object that
              mutates in response to array changes, for example an array that maps
              everything from some other array (see `Ember.computed.map`), it is usually
              important that the *same* array be returned to avoid accidentally triggering observers.

              Example

              ```javascript
              Ember.computed.max = function(dependentKey) {
                return Ember.reduceComputed(dependentKey, {
                  initialValue: -Infinity,

                  addedItem: function(accumulatedValue, item, changeMeta, instanceMeta) {
                    return Math.max(accumulatedValue, item);
                  },

                  removedItem: function(accumulatedValue, item, changeMeta, instanceMeta) {
                    if (item < accumulatedValue) {
                      return accumulatedValue;
                    }
                  }
                });
              };
              ```

              Dependent keys may refer to `@this` to observe changes to the object itself,
              which must be array-like, rather than a property of the object.  This is
              mostly useful for array proxies, to ensure objects are retrieved via
              `objectAtContent`.  This is how you could sort items by properties defined on an item controller.

              Example

              ```javascript
              App.PeopleController = Ember.ArrayController.extend({
                itemController: 'person',

                sortedPeople: Ember.computed.sort('@this.@each.reversedName', function(personA, personB) {
                  // `reversedName` isn't defined on Person, but we have access to it via
                  // the item controller App.PersonController.  If we'd used
                  // `content.@each.reversedName` above, we would be getting the objects
                  // directly and not have access to `reversedName`.
                  //
                  var reversedNameA = get(personA, 'reversedName'),
                      reversedNameB = get(personB, 'reversedName');

                  return Ember.compare(reversedNameA, reversedNameB);
                })
              });

              App.PersonController = Ember.ObjectController.extend({
                reversedName: function() {
                  return reverse(get(this, 'name'));
                }.property('name')
              });
              ```

              Dependent keys whose values are not arrays are treated as regular
              dependencies: when they change, the computed property is completely
              recalculated.  It is sometimes useful to have dependent arrays with similar
              semantics.  Dependent keys which end in `.[]` do not use "one at a time"
              semantics.  When an item is added or removed from such a dependency, the
              computed property is completely recomputed.

              When the computed property is completely recomputed, the `accumulatedValue`
              is discarded, it starts with `initialValue` again, and each item is passed
              to `addedItem` in turn.

              Example

              ```javascript
              Ember.Object.extend({
                // When `string` is changed, `computed` is completely recomputed.
                string: 'a string',

                // When an item is added to `array`, `addedItem` is called.
                array: [],

                // When an item is added to `anotherArray`, `computed` is completely
                // recomputed.
                anotherArray: [],

                computed: Ember.reduceComputed('string', 'array', 'anotherArray.[]', {
                  addedItem: addedItemCallback,
                  removedItem: removedItemCallback
                })
              });
              ```

              @method reduceComputed
              @for Ember
              @param {String} [dependentKeys*]
              @param {Object} options
              @return {Ember.ComputedProperty}
            */
        function reduceComputed(options) {
            var args;

            if (arguments.length > 1) {
                args = a_slice.call(arguments, 0, -1);
                options = a_slice.call(arguments, -1)[0];
            }

            if (typeof options !== "object") {
                throw new EmberError("Reduce Computed Property declared without an options hash");
            }

            if (!('initialValue' in options)) {
                throw new EmberError("Reduce Computed Property declared without an initial value");
            }

            var cp = new ReduceComputedProperty(options);

            if (args) {
                cp.property.apply(cp, args);
            }

            return cp;
        }

        __exports__.reduceComputed = reduceComputed;
    });
    define("ember-runtime/computed/reduce_computed_macros",
    ["ember-metal/core", "ember-metal/merge", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/utils", "ember-metal/error", "ember-metal/enumerable_utils", "ember-metal/run_loop", "ember-metal/observer", "ember-runtime/computed/array_computed", "ember-runtime/computed/reduce_computed", "ember-runtime/system/object_proxy", "ember-runtime/system/subarray", "ember-runtime/keys", "ember-runtime/compare", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-runtime
            */

        var Ember = __dependency1__["default"];
        // Ember.assert
        var merge = __dependency2__["default"];
        var get = __dependency3__.get;
        var set = __dependency4__.set;
        var isArray = __dependency5__.isArray;
        var guidFor = __dependency5__.guidFor;
        var EmberError = __dependency6__["default"];
        var forEach = __dependency7__.forEach;
        var run = __dependency8__["default"];
        var addObserver = __dependency9__.addObserver;
        var arrayComputed = __dependency10__.arrayComputed;
        var reduceComputed = __dependency11__.reduceComputed;
        var ObjectProxy = __dependency12__["default"];
        var SubArray = __dependency13__["default"];
        var keys = __dependency14__["default"];
        var compare = __dependency15__["default"];

        var a_slice = [].slice;

        /**
             A computed property that returns the sum of the value
             in the dependent array.

             @method computed.sum
             @for Ember
             @param {String} dependentKey
             @return {Ember.ComputedProperty} computes the sum of all values in the dependentKey's array
             @since 1.4.0
            */

        function sum(dependentKey) {
            return reduceComputed(dependentKey, {
                initialValue: 0,

                addedItem: function(accumulatedValue, item, changeMeta, instanceMeta) {
                    return accumulatedValue + item;
                },

                removedItem: function(accumulatedValue, item, changeMeta, instanceMeta) {
                    return accumulatedValue - item;
                }
            });
        }

        __exports__.sum = sum; /**
              A computed property that calculates the maximum value in the
              dependent array. This will return `-Infinity` when the dependent
              array is empty.

              ```javascript
              var Person = Ember.Object.extend({
                childAges: Ember.computed.mapBy('children', 'age'),
                maxChildAge: Ember.computed.max('childAges')
              });

              var lordByron = Person.create({ children: [] });

              lordByron.get('maxChildAge'); // -Infinity
              lordByron.get('children').pushObject({
                name: 'Augusta Ada Byron', age: 7
              });
              lordByron.get('maxChildAge'); // 7
              lordByron.get('children').pushObjects([{
                name: 'Allegra Byron',
                age: 5
              }, {
                name: 'Elizabeth Medora Leigh',
                age: 8
              }]);
              lordByron.get('maxChildAge'); // 8
              ```

              @method computed.max
              @for Ember
              @param {String} dependentKey
              @return {Ember.ComputedProperty} computes the largest value in the dependentKey's array
            */
        function max (dependentKey) {
            return reduceComputed(dependentKey, {
                initialValue: - Infinity,

                addedItem: function (accumulatedValue, item, changeMeta, instanceMeta) {
                    return Math.max(accumulatedValue, item);
                },

                removedItem: function (accumulatedValue, item, changeMeta, instanceMeta) {
                    if (item < accumulatedValue) {
                        return accumulatedValue;
                    }
                }
            });
        }

        __exports__.max = max; /**
              A computed property that calculates the minimum value in the
              dependent array. This will return `Infinity` when the dependent
              array is empty.

              ```javascript
              var Person = Ember.Object.extend({
                childAges: Ember.computed.mapBy('children', 'age'),
                minChildAge: Ember.computed.min('childAges')
              });

              var lordByron = Person.create({ children: [] });

              lordByron.get('minChildAge'); // Infinity
              lordByron.get('children').pushObject({
                name: 'Augusta Ada Byron', age: 7
              });
              lordByron.get('minChildAge'); // 7
              lordByron.get('children').pushObjects([{
                name: 'Allegra Byron',
                age: 5
              }, {
                name: 'Elizabeth Medora Leigh',
                age: 8
              }]);
              lordByron.get('minChildAge'); // 5
              ```

              @method computed.min
              @for Ember
              @param {String} dependentKey
              @return {Ember.ComputedProperty} computes the smallest value in the dependentKey's array
            */
        function min(dependentKey) {
            return reduceComputed(dependentKey, {
                initialValue: Infinity,

                addedItem: function (accumulatedValue, item, changeMeta, instanceMeta) {
                    return Math.min(accumulatedValue, item);
                },

                removedItem: function (accumulatedValue, item, changeMeta, instanceMeta) {
                    if (item > accumulatedValue) {
                        return accumulatedValue;
                    }
                }
            });
        }

        __exports__.min = min; /**
              Returns an array mapped via the callback

              The callback method you provide should have the following signature.
              `item` is the current item in the iteration.

              ```javascript
              function(item);
              ```

              Example

              ```javascript
              var Hamster = Ember.Object.extend({
                excitingChores: Ember.computed.map('chores', function(chore) {
                  return chore.toUpperCase() + '!';
                })
              });

              var hamster = Hamster.create({
                chores: ['clean', 'write more unit tests']
              });

              hamster.get('excitingChores'); // ['CLEAN!', 'WRITE MORE UNIT TESTS!']
              ```

              @method computed.map
              @for Ember
              @param {String} dependentKey
              @param {Function} callback
              @return {Ember.ComputedProperty} an array mapped via the callback
            */
        function map(dependentKey, callback) {
            var options = {
                addedItem: function(array, item, changeMeta, instanceMeta) {
                    var mapped = callback.call(this, item);
                    array.insertAt(changeMeta.index, mapped);
                    return array;
                },
                removedItem: function(array, item, changeMeta, instanceMeta) {
                    array.removeAt(changeMeta.index, 1);
                    return array;
                }
            };

            return arrayComputed(dependentKey, options);
        }

        __exports__.map = map; /**
              Returns an array mapped to the specified key.

              ```javascript
              var Person = Ember.Object.extend({
                childAges: Ember.computed.mapBy('children', 'age')
              });

              var lordByron = Person.create({ children: [] });

              lordByron.get('childAges'); // []
              lordByron.get('children').pushObject({ name: 'Augusta Ada Byron', age: 7 });
              lordByron.get('childAges'); // [7]
              lordByron.get('children').pushObjects([{
                name: 'Allegra Byron',
                age: 5
              }, {
                name: 'Elizabeth Medora Leigh',
                age: 8
              }]);
              lordByron.get('childAges'); // [7, 5, 8]
              ```

              @method computed.mapBy
              @for Ember
              @param {String} dependentKey
              @param {String} propertyKey
              @return {Ember.ComputedProperty} an array mapped to the specified key
            */
        function mapBy (dependentKey, propertyKey) {
            var callback = function(item) {
                return get(item, propertyKey);
            };
            return map(dependentKey + '.@each.' + propertyKey, callback);
        }

        __exports__.mapBy = mapBy; /**
              @method computed.mapProperty
              @for Ember
              @deprecated Use `Ember.computed.mapBy` instead
              @param dependentKey
              @param propertyKey
            */
        var mapProperty = mapBy;
        __exports__.mapProperty = mapProperty;
        /**
              Filters the array by the callback.

              The callback method you provide should have the following signature.
              `item` is the current item in the iteration.

              ```javascript
              function(item);
              ```

              ```javascript
              var Hamster = Ember.Object.extend({
                remainingChores: Ember.computed.filter('chores', function(chore) {
                  return !chore.done;
                })
              });

              var hamster = Hamster.create({ 
                chores: [
                  { name: 'cook', done: true },
                  { name: 'clean', done: true },
                  { name: 'write more unit tests', done: false }
                ] 
              });

              hamster.get('remainingChores'); // [{name: 'write more unit tests', done: false}]
              ```

              @method computed.filter
              @for Ember
              @param {String} dependentKey
              @param {Function} callback
              @return {Ember.ComputedProperty} the filtered array
            */
        function filter(dependentKey, callback) {
            var options = {
                initialize: function (array, changeMeta, instanceMeta) {
                    instanceMeta.filteredArrayIndexes = new SubArray();
                },

                addedItem: function(array, item, changeMeta, instanceMeta) {
                    var match = !!callback.call(this, item),
                    filterIndex = instanceMeta.filteredArrayIndexes.addItem(changeMeta.index, match);

                    if (match) {
                        array.insertAt(filterIndex, item);
                    }

                    return array;
                },

                removedItem: function(array, item, changeMeta, instanceMeta) {
                    var filterIndex = instanceMeta.filteredArrayIndexes.removeItem(changeMeta.index);

                    if (filterIndex > -1) {
                        array.removeAt(filterIndex);
                    }

                    return array;
                }
            };

            return arrayComputed(dependentKey, options);
        }

        __exports__.filter = filter; /**
              Filters the array by the property and value

              ```javascript
              var Hamster = Ember.Object.extend({
                remainingChores: Ember.computed.filterBy('chores', 'done', false)
              });

              var hamster = Hamster.create({
                chores: [
                  { name: 'cook', done: true },
                  { name: 'clean', done: true },
                  { name: 'write more unit tests', done: false }
                ]
              });

              hamster.get('remainingChores'); // [{ name: 'write more unit tests', done: false }]
              ```

              @method computed.filterBy
              @for Ember
              @param {String} dependentKey
              @param {String} propertyKey
              @param {*} value
              @return {Ember.ComputedProperty} the filtered array
            */
        function filterBy (dependentKey, propertyKey, value) {
            var callback;

            if (arguments.length === 2) {
                callback = function(item) {
                    return get(item, propertyKey);
                };
            } else {
                callback = function(item) {
                    return get(item, propertyKey) === value;
                };
            }

            return filter(dependentKey + '.@each.' + propertyKey, callback);
        }

        __exports__.filterBy = filterBy; /**
              @method computed.filterProperty
              @for Ember
              @param dependentKey
              @param propertyKey
              @param value
              @deprecated Use `Ember.computed.filterBy` instead
            */
        var filterProperty = filterBy;
        __exports__.filterProperty = filterProperty;
        /**
              A computed property which returns a new array with all the unique
              elements from one or more dependent arrays.

              Example

              ```javascript
              var Hamster = Ember.Object.extend({
                uniqueFruits: Ember.computed.uniq('fruits')
              });

              var hamster = Hamster.create({
                fruits: [
                  'banana',
                  'grape',
                  'kale',
                  'banana'
                ]
              });

              hamster.get('uniqueFruits'); // ['banana', 'grape', 'kale']
              ```

              @method computed.uniq
              @for Ember
              @param {String} propertyKey*
              @return {Ember.ComputedProperty} computes a new array with all the
              unique elements from the dependent array
            */
        function uniq() {
            var args = a_slice.call(arguments);
            args.push({
                initialize: function(array, changeMeta, instanceMeta) {
                    instanceMeta.itemCounts = {};
                },

                addedItem: function(array, item, changeMeta, instanceMeta) {
                    var guid = guidFor(item);

                    if (!instanceMeta.itemCounts[guid]) {
                        instanceMeta.itemCounts[guid] = 1;
                    } else {
                        ++instanceMeta.itemCounts[guid];
                    }
                    array.addObject(item);
                    return array;
                },
                removedItem: function(array, item, _, instanceMeta) {
                    var guid = guidFor(item),
                    itemCounts = instanceMeta.itemCounts;

                    if (--itemCounts[guid] === 0) {
                        array.removeObject(item);
                    }
                    return array;
                }
            });
            return arrayComputed.apply(null, args);
        }

        __exports__.uniq = uniq; /**
              Alias for [Ember.computed.uniq](/api/#method_computed_uniq).

              @method computed.union
              @for Ember
              @param {String} propertyKey*
              @return {Ember.ComputedProperty} computes a new array with all the
              unique elements from the dependent array
            */
        var union = uniq;
        __exports__.union = union;
        /**
              A computed property which returns a new array with all the duplicated
              elements from two or more dependent arrays.

              Example

              ```javascript
              var obj = Ember.Object.createWithMixins({
                adaFriends: ['Charles Babbage', 'John Hobhouse', 'William King', 'Mary Somerville'],
                charlesFriends: ['William King', 'Mary Somerville', 'Ada Lovelace', 'George Peacock'],
                friendsInCommon: Ember.computed.intersect('adaFriends', 'charlesFriends')
              });

              obj.get('friendsInCommon'); // ['William King', 'Mary Somerville']
              ```

              @method computed.intersect
              @for Ember
              @param {String} propertyKey*
              @return {Ember.ComputedProperty} computes a new array with all the
              duplicated elements from the dependent arrays
            */
        function intersect() {
            var getDependentKeyGuids = function (changeMeta) {
                return map(changeMeta.property._dependentKeys, function (dependentKey) {
                    return guidFor(dependentKey);
                });
            };

            var args = a_slice.call(arguments);
            args.push({
                initialize: function (array, changeMeta, instanceMeta) {
                    instanceMeta.itemCounts = {};
                },

                addedItem: function(array, item, changeMeta, instanceMeta) {
                    var itemGuid = guidFor(item),
                    dependentGuids = getDependentKeyGuids(changeMeta),
                    dependentGuid = guidFor(changeMeta.arrayChanged),
                    numberOfDependentArrays = changeMeta.property._dependentKeys.length,
                    itemCounts = instanceMeta.itemCounts;

                    if (!itemCounts[itemGuid]) {
                        itemCounts[itemGuid] = {};
                    }
                    if (itemCounts[itemGuid][dependentGuid] === undefined) {
                        itemCounts[itemGuid][dependentGuid] = 0;
                    }

                    if (++itemCounts[itemGuid][dependentGuid] === 1 &&
                    numberOfDependentArrays === keys(itemCounts[itemGuid]).length) {

                        array.addObject(item);
                    }
                    return array;
                },
                removedItem: function(array, item, changeMeta, instanceMeta) {
                    var itemGuid = guidFor(item),
                    dependentGuids = getDependentKeyGuids(changeMeta),
                    dependentGuid = guidFor(changeMeta.arrayChanged),
                    numberOfDependentArrays = changeMeta.property._dependentKeys.length,
                    numberOfArraysItemAppearsIn,
                    itemCounts = instanceMeta.itemCounts;

                    if (itemCounts[itemGuid][dependentGuid] === undefined) {
                        itemCounts[itemGuid][dependentGuid] = 0;
                    }
                    if (--itemCounts[itemGuid][dependentGuid] === 0) {
                        delete itemCounts[itemGuid][dependentGuid];
                        numberOfArraysItemAppearsIn = keys(itemCounts[itemGuid]).length;

                        if (numberOfArraysItemAppearsIn === 0) {
                            delete itemCounts[itemGuid];
                        }
                        array.removeObject(item);
                    }
                    return array;
                }
            });
            return arrayComputed.apply(null, args);
        }

        __exports__.intersect = intersect; /**
              A computed property which returns a new array with all the
              properties from the first dependent array that are not in the second
              dependent array.

              Example

              ```javascript
              var Hamster = Ember.Object.extend({
                likes: ['banana', 'grape', 'kale'],
                wants: Ember.computed.setDiff('likes', 'fruits')
              });

              var hamster = Hamster.create({
                fruits: [
                  'grape',
                  'kale',
                ]
              });

              hamster.get('wants'); // ['banana']
              ```

              @method computed.setDiff
              @for Ember
              @param {String} setAProperty
              @param {String} setBProperty
              @return {Ember.ComputedProperty} computes a new array with all the
              items from the first dependent array that are not in the second
              dependent array
            */
        function setDiff(setAProperty, setBProperty) {
            if (arguments.length !== 2) {
                throw new EmberError("setDiff requires exactly two dependent arrays.");
            }
            return arrayComputed(setAProperty, setBProperty, {
                addedItem: function (array, item, changeMeta, instanceMeta) {
                    var setA = get(this, setAProperty),
                    setB = get(this, setBProperty);

                    if (changeMeta.arrayChanged === setA) {
                        if (!setB.contains(item)) {
                            array.addObject(item);
                        }
                    } else {
                        array.removeObject(item);
                    }
                    return array;
                },

                removedItem: function (array, item, changeMeta, instanceMeta) {
                    var setA = get(this, setAProperty),
                    setB = get(this, setBProperty);

                    if (changeMeta.arrayChanged === setB) {
                        if (setA.contains(item)) {
                            array.addObject(item);
                        }
                    } else {
                        array.removeObject(item);
                    }
                    return array;
                }
            });
        }

        __exports__.setDiff = setDiff;
        function binarySearch(array, item, low, high) {
            var mid, midItem, res, guidMid, guidItem;

            if (arguments.length < 4) {
                high = get(array, 'length');
            }
            if (arguments.length < 3) {
                low = 0;
            }

            if (low === high) {
                return low;
            }

            mid = low + Math.floor((high - low) / 2);
            midItem = array.objectAt(mid);

            guidMid = _guidFor(midItem);
            guidItem = _guidFor(item);

            if (guidMid === guidItem) {
                return mid;
            }

            res = this.order(midItem, item);
            if (res === 0) {
                res = guidMid < guidItem ? -1 : 1;
            }


            if (res < 0) {
                return this.binarySearch(array, item, mid + 1, high);
            } else if (res > 0) {
                return this.binarySearch(array, item, low, mid);
            }

            return mid;

            function _guidFor(item) {
                if (SearchProxy.detectInstance(item)) {
                    return guidFor(get(item, 'content'));
                }
                return guidFor(item);
            }
        }


        var SearchProxy = ObjectProxy.extend();

        /**
              A computed property which returns a new array with all the
              properties from the first dependent array sorted based on a property
              or sort function.

              The callback method you provide should have the following signature:

              ```javascript
              function(itemA, itemB);
              ```

              - `itemA` the first item to compare.
              - `itemB` the second item to compare.

              This function should return negative number (e.g. `-1`) when `itemA` should come before
              `itemB`. It should return positive number (e.g. `1`) when `itemA` should come after
              `itemB`. If the `itemA` and `itemB` are equal this function should return `0`.

              Therefore, if this function is comparing some numeric values, simple `itemA - itemB` or
              `itemA.get( 'foo' ) - itemB.get( 'foo' )` can be used instead of series of `if`.

              Example

              ```javascript
              var ToDoList = Ember.Object.extend({
                // using standard ascending sort
                todosSorting: ['name'],
                sortedTodos: Ember.computed.sort('todos', 'todosSorting'),

                // using descending sort
                todosSortingDesc: ['name:desc'],
                sortedTodosDesc: Ember.computed.sort('todos', 'todosSortingDesc'),

                // using a custom sort function
                priorityTodos: Ember.computed.sort('todos', function(a, b){
                  if (a.priority > b.priority) {
                    return 1;
                  } else if (a.priority < b.priority) {
                    return -1;
                  }

                  return 0;
                })
              });

              var todoList = ToDoList.create({todos: [
                { name: 'Unit Test', priority: 2 },
                { name: 'Documentation', priority: 3 },
                { name: 'Release', priority: 1 }
              ]});

              todoList.get('sortedTodos');      // [{ name:'Documentation', priority:3 }, { name:'Release', priority:1 }, { name:'Unit Test', priority:2 }]
              todoList.get('sortedTodosDesc');  // [{ name:'Unit Test', priority:2 }, { name:'Release', priority:1 }, { name:'Documentation', priority:3 }]
              todoList.get('priorityTodos');    // [{ name:'Release', priority:1 }, { name:'Unit Test', priority:2 }, { name:'Documentation', priority:3 }]
              ```

              @method computed.sort
              @for Ember
              @param {String} dependentKey
              @param {String or Function} sortDefinition a dependent key to an
              array of sort properties (add `:desc` to the arrays sort properties to sort descending) or a function to use when sorting
              @return {Ember.ComputedProperty} computes a new sorted array based
              on the sort property array or callback function
            */
        function sort(itemsKey, sortDefinition) {
            Ember.assert("Ember.computed.sort requires two arguments: an array key to sort and either a sort properties key or sort function", arguments.length === 2);

            var initFn, sortPropertiesKey;

            if (typeof sortDefinition === 'function') {
                initFn = function (array, changeMeta, instanceMeta) {
                    instanceMeta.order = sortDefinition;
                    instanceMeta.binarySearch = binarySearch;
                };
            } else {
                sortPropertiesKey = sortDefinition;
                initFn = function (array, changeMeta, instanceMeta) {
                    function setupSortProperties() {
                        var sortPropertyDefinitions = get(this, sortPropertiesKey),
                        sortProperty,
                        sortProperties = instanceMeta.sortProperties = [],
                        sortPropertyAscending = instanceMeta.sortPropertyAscending = {},
                        idx,
                        asc;

                        Ember.assert("Cannot sort: '" + sortPropertiesKey + "' is not an array.", isArray(sortPropertyDefinitions));

                        changeMeta.property.clearItemPropertyKeys(itemsKey);

                        forEach(sortPropertyDefinitions, function (sortPropertyDefinition) {
                            if ((idx = sortPropertyDefinition.indexOf(':')) !== -1) {
                                sortProperty = sortPropertyDefinition.substring(0, idx);
                                asc = sortPropertyDefinition.substring(idx + 1).toLowerCase() !== 'desc';
                            } else {
                                sortProperty = sortPropertyDefinition;
                                asc = true;
                            }

                            sortProperties.push(sortProperty);
                            sortPropertyAscending[sortProperty] = asc;
                            changeMeta.property.itemPropertyKey(itemsKey, sortProperty);
                        });

                        sortPropertyDefinitions.addObserver('@each', this, updateSortPropertiesOnce);
                    }

                    function updateSortPropertiesOnce() {
                        run.once(this, updateSortProperties, changeMeta.propertyName);
                    }

                    function updateSortProperties(propertyName) {
                        setupSortProperties.call(this);
                        changeMeta.property.recomputeOnce.call(this, propertyName);
                    }

                    addObserver(this, sortPropertiesKey, updateSortPropertiesOnce);

                    setupSortProperties.call(this);


                    instanceMeta.order = function (itemA, itemB) {
                        var isProxy = itemB instanceof SearchProxy,
                        sortProperty, result, asc;

                        for (var i = 0; i < this.sortProperties.length; ++i) {
                            sortProperty = this.sortProperties[i];
                            result = compare(get(itemA, sortProperty), isProxy ? itemB[sortProperty] : get(itemB, sortProperty));

                            if (result !== 0) {
                                asc = this.sortPropertyAscending[sortProperty];
                                return asc ? result : (-1 * result);
                            }
                        }

                        return 0;
                    };

                    instanceMeta.binarySearch = binarySearch;
                };
            }

            return arrayComputed(itemsKey, {
                initialize: initFn,

                addedItem: function (array, item, changeMeta, instanceMeta) {
                    var index = instanceMeta.binarySearch(array, item);
                    array.insertAt(index, item);
                    return array;
                },

                removedItem: function (array, item, changeMeta, instanceMeta) {
                    var proxyProperties, index, searchItem;

                    if (changeMeta.previousValues) {
                        proxyProperties = merge({
                            content: item 
                        }, changeMeta.previousValues);

                        searchItem = SearchProxy.create(proxyProperties);
                    } else {
                        searchItem = item;
                    }

                    index = instanceMeta.binarySearch(array, searchItem);
                    array.removeAt(index);
                    return array;
                }
            });
        }

        __exports__.sort = sort;
    });
    define("ember-runtime/controllers/array_controller",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/enumerable_utils", "ember-runtime/system/array_proxy", "ember-runtime/mixins/sortable", "ember-runtime/mixins/controller", "ember-metal/computed", "ember-metal/error", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-runtime
            */

        var Ember = __dependency1__["default"];
        var get = __dependency2__.get;
        var set = __dependency3__.set;
        var forEach = __dependency4__.forEach;
        var replace = __dependency4__.replace;
        var ArrayProxy = __dependency5__["default"];
        var SortableMixin = __dependency6__["default"];
        var ControllerMixin = __dependency7__["default"];
        var computed = __dependency8__.computed;
        var EmberError = __dependency9__["default"];


        /**
              `Ember.ArrayController` provides a way for you to publish a collection of
              objects so that you can easily bind to the collection from a Handlebars
              `#each` helper, an `Ember.CollectionView`, or other controllers.

              The advantage of using an `ArrayController` is that you only have to set up
              your view bindings once; to change what's displayed, simply swap out the
              `model` property on the controller.

              For example, imagine you wanted to display a list of items fetched via an XHR
              request. Create an `Ember.ArrayController` and set its `model` property:

              ```javascript
              MyApp.listController = Ember.ArrayController.create();

              $.get('people.json', function(data) {
                MyApp.listController.set('model', data);
              });
              ```

              Then, create a view that binds to your new controller:

              ```handlebars
              {{#each MyApp.listController}}
                {{firstName}} {{lastName}}
              {{/each}}
              ```

              Although you are binding to the controller, the behavior of this controller
              is to pass through any methods or properties to the underlying array. This
              capability comes from `Ember.ArrayProxy`, which this class inherits from.

              Sometimes you want to display computed properties within the body of an
              `#each` helper that depend on the underlying items in `model`, but are not
              present on those items.   To do this, set `itemController` to the name of a
              controller (probably an `ObjectController`) that will wrap each individual item.

              For example:

              ```handlebars
                {{#each post in controller}}
                  <li>{{post.title}} ({{post.titleLength}} characters)</li>
                {{/each}}
              ```

              ```javascript
              App.PostsController = Ember.ArrayController.extend({
                itemController: 'post'
              });

              App.PostController = Ember.ObjectController.extend({
                // the `title` property will be proxied to the underlying post.

                titleLength: function() {
                  return this.get('title').length;
                }.property('title')
              });
              ```

              In some cases it is helpful to return a different `itemController` depending
              on the particular item.  Subclasses can do this by overriding
              `lookupItemController`.

              For example:

              ```javascript
              App.MyArrayController = Ember.ArrayController.extend({
                lookupItemController: function( object ) {
                  if (object.get('isSpecial')) {
                    return "special"; // use App.SpecialController
                  } else {
                    return "regular"; // use App.RegularController
                  }
                }
              });
              ```

              The itemController instances will have a `parentController` property set to
              the `ArrayController` instance.

              @class ArrayController
              @namespace Ember
              @extends Ember.ArrayProxy
              @uses Ember.SortableMixin
              @uses Ember.ControllerMixin
            */

        __exports__["default"] = ArrayProxy.extend(ControllerMixin, SortableMixin, {

            /**
                    The controller used to wrap items, if any.

                    @property itemController
                    @type String
                    @default null
                  */
            itemController: null,

            /**
                    Return the name of the controller to wrap items, or `null` if items should
                    be returned directly.  The default implementation simply returns the
                    `itemController` property, but subclasses can override this method to return
                    different controllers for different objects.

                    For example:

                    ```javascript
                    App.MyArrayController = Ember.ArrayController.extend({
                      lookupItemController: function( object ) {
                        if (object.get('isSpecial')) {
                          return "special"; // use App.SpecialController
                        } else {
                          return "regular"; // use App.RegularController
                        }
                      }
                    });
                    ```

                    @method lookupItemController
                    @param {Object} object
                    @return {String}
                  */
            lookupItemController: function(object) {
                return get(this, 'itemController');
            },

            objectAtContent: function(idx) {
                var length = get(this, 'length');
                var arrangedContent = get(this, 'arrangedContent');
                var object = arrangedContent && arrangedContent.objectAt(idx);
                var controllerClass;

                if (idx >= 0 && idx < length) {
                    controllerClass = this.lookupItemController(object);
                    if (controllerClass) {
                        return this.controllerAt(idx, object, controllerClass);
                    }
                }

                // When `controllerClass` is falsy, we have not opted in to using item
                // controllers, so return the object directly.

                // When the index is out of range, we want to return the "out of range"
                // value, whatever that might be.  Rather than make assumptions
                // (e.g. guessing `null` or `undefined`) we defer this to `arrangedContent`.
                return object;
            },

            arrangedContentDidChange: function() {
                this._super();
                this._resetSubControllers();
            },

            arrayContentDidChange: function(idx, removedCnt, addedCnt) {
                var subControllers = this._subControllers;

                if (subControllers.length) {
                    var subControllersToRemove = subControllers.slice(idx, idx + removedCnt);

                    forEach(subControllersToRemove, function(subController) {
                        if (subController) {
                            subController.destroy();
                        }
                    });

                    replace(subControllers, idx, removedCnt, new Array(addedCnt));
                }

                // The shadow array of subcontrollers must be updated before we trigger
                // observers, otherwise observers will get the wrong subcontainer when
                // calling `objectAt`
                this._super(idx, removedCnt, addedCnt);
            },

            init: function() {
                this._super();
                this._subControllers = [];
            },

            model: computed(function () {
                return Ember.A();
            }),

            /**
                   * Flag to mark as being "virtual". Used to keep this instance
                   * from participating in the parentController hierarchy.
                   *
                   * @private
                   * @property _isVirtual
                   * @type Boolean
                   */
            _isVirtual: false,

            controllerAt: function(idx, object, controllerClass) {
                var fullName, subController, parentController;

                var container = get(this, 'container');
                var subControllers = this._subControllers;

                if (subControllers.length > idx) {
                    subController = subControllers[idx];

                    if (subController) {
                        return subController;
                    }
                }

                fullName = 'controller:' + controllerClass;

                if (!container.has(fullName)) {
                    throw new EmberError('Could not resolve itemController: "' + controllerClass + '"');
                }

                if (this._isVirtual) {
                    parentController = get(this, 'parentController');
                } else {
                    parentController = this;
                }

                subController = container.lookupFactory(fullName).create({
                    target: parentController,
                    parentController: parentController,
                    model: object
                });

                subControllers[idx] = subController;

                return subController;
            },

            _subControllers: null,

            _resetSubControllers: function() {
                var controller;
                var subControllers = this._subControllers;

                if (subControllers.length) {
                    for (var i = 0, length = subControllers.length; length > i; i++) {
                        controller = subControllers[i];
                        if (controller) {
                            controller.destroy();
                        }
                    }

                    subControllers.length = 0;
                }
            },

            willDestroy: function() {
                this._resetSubControllers();
                this._super();
            }
        });
    });
    define("ember-runtime/controllers/controller",
    ["ember-runtime/system/object", "ember-runtime/mixins/controller", "exports"],
    function(__dependency1__, __dependency2__, __exports__) {
        "use strict";
        var EmberObject = __dependency1__["default"];
        var Mixin = __dependency2__["default"];

        /**
            @module ember
            @submodule ember-runtime
            */

        /**
              @class Controller
              @namespace Ember
              @extends Ember.Object
              @uses Ember.ControllerMixin
            */
        __exports__["default"] = EmberObject.extend(Mixin);
    });
    define("ember-runtime/controllers/object_controller",
    ["ember-runtime/mixins/controller", "ember-runtime/system/object_proxy", "exports"],
    function(__dependency1__, __dependency2__, __exports__) {
        "use strict";
        var ControllerMixin = __dependency1__["default"];
        var ObjectProxy = __dependency2__["default"];

        /**
            @module ember
            @submodule ember-runtime
            */

        /**
              `Ember.ObjectController` is part of Ember's Controller layer. It is intended
              to wrap a single object, proxying unhandled attempts to `get` and `set` to the underlying
              model object, and to forward unhandled action attempts to its `target`.

              `Ember.ObjectController` derives this functionality from its superclass
              `Ember.ObjectProxy` and the `Ember.ControllerMixin` mixin.

              @class ObjectController
              @namespace Ember
              @extends Ember.ObjectProxy
              @uses Ember.ControllerMixin
            **/
        __exports__["default"] = ObjectProxy.extend(ControllerMixin);
    });
    define("ember-runtime/copy",
    ["ember-metal/enumerable_utils", "ember-metal/utils", "ember-runtime/system/object", "ember-runtime/mixins/copyable", "ember-metal/platform", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
        "use strict";
        var indexOf = __dependency1__.indexOf;
        var typeOf = __dependency2__.typeOf;
        var EmberObject = __dependency3__["default"];
        var Copyable = __dependency4__["default"];
        var create = __dependency5__.create;

        function _copy(obj, deep, seen, copies) {
            var ret, loc, key;

            // primitive data types are immutable, just return them.
            if ('object' !== typeof obj || obj === null) 
                return obj;

            // avoid cyclical loops
            if (deep && (loc = indexOf(seen, obj)) >= 0) 
                return copies[loc];

            Ember.assert('Cannot clone an Ember.Object that does not implement Ember.Copyable', !(obj instanceof EmberObject) || (Copyable && Copyable.detect(obj)));

            // IMPORTANT: this specific test will detect a native array only. Any other
            // object will need to implement Copyable.
            if (typeOf(obj) === 'array') {
                ret = obj.slice();
                if (deep) {
                    loc = ret.length;
                    while (--loc >= 0) 
                        ret[loc] = _copy(ret[loc], deep, seen, copies);
                }
            } else if (Copyable && Copyable.detect(obj)) {
                ret = obj.copy(deep, seen, copies);
            } else if (obj instanceof Date) {
                ret = new Date(obj.getTime());
            } else {
                ret = {};
                for (key in obj) {
                    if (!obj.hasOwnProperty(key)) 
                        continue;

                        // Prevents browsers that don't respect non-enumerability from
                        // copying internal Ember properties
                        if (key.substring(0, 2) === '__') 
                            continue;

                            ret[key] = deep ? _copy(obj[key], deep, seen, copies) : obj[key];
                }
            }

            if (deep) {
                seen.push(obj);
                copies.push(ret);
            }

            return ret;
        }

        /**
              Creates a clone of the passed object. This function can take just about
              any type of object and create a clone of it, including primitive values
              (which are not actually cloned because they are immutable).

              If the passed object implements the `clone()` method, then this function
              will simply call that method and return the result.

              @method copy
              @for Ember
              @param {Object} obj The object to clone
              @param {Boolean} deep If true, a deep copy of the object is made
              @return {Object} The cloned object
            */
        __exports__["default"] = function copy(obj, deep) {
            // fast paths
            if ('object' !== typeof obj || obj === null) 
                return obj; // can't copy primitives
            if (Copyable && Copyable.detect(obj)) 
                return obj.copy(deep);
            return _copy(obj, deep, deep ? [] : null, deep ? [] : null);
        }
    });
    define("ember-runtime/core",
    ["exports"],
    function(__exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-runtime
            */

        /**
              Compares two objects, returning true if they are logically equal. This is
              a deeper comparison than a simple triple equal. For sets it will compare the
              internal objects. For any other object that implements `isEqual()` it will
              respect that method.

              ```javascript
              Ember.isEqual('hello', 'hello');  // true
              Ember.isEqual(1, 2);              // false
              Ember.isEqual([4, 2], [4, 2]);    // false
              ```

              @method isEqual
              @for Ember
              @param {Object} a first object to compare
              @param {Object} b second object to compare
              @return {Boolean}
            */
        var isEqual = function isEqual(a, b) {
            if (a && 'function' === typeof a.isEqual) 
                return a.isEqual(b);
            if (a instanceof Date && b instanceof Date) {
                return a.getTime() === b.getTime();
            }
            return a === b;
        };
        __exports__.isEqual = isEqual;
    });
    define("ember-runtime/ext/function",
    ["ember-metal/core", "ember-metal/expand_properties", "ember-metal/computed"],
    function(__dependency1__, __dependency2__, __dependency3__) {
        "use strict";
        /**
            @module ember
            @submodule ember-runtime
            */

        var Ember = __dependency1__["default"];
        // Ember.EXTEND_PROTOTYPES, Ember.assert
        var expandProperties = __dependency2__["default"];
        var computed = __dependency3__.computed;

        var a_slice = Array.prototype.slice;
        var FunctionPrototype = Function.prototype;

        if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Function) {

            /**
                    The `property` extension of Javascript's Function prototype is available
                    when `Ember.EXTEND_PROTOTYPES` or `Ember.EXTEND_PROTOTYPES.Function` is
                    `true`, which is the default.

                    Computed properties allow you to treat a function like a property:

                    ```javascript
                    MyApp.President = Ember.Object.extend({
                      firstName: '',
                      lastName:  '',

                      fullName: function() {
                        return this.get('firstName') + ' ' + this.get('lastName');

                        // Call this flag to mark the function as a property
                      }.property()
                    });

                    var president = MyApp.President.create({
                      firstName: "Barack",
                      lastName: "Obama"
                    });

                    president.get('fullName');    // "Barack Obama"
                    ```

                    Treating a function like a property is useful because they can work with
                    bindings, just like any other property.

                    Many computed properties have dependencies on other properties. For
                    example, in the above example, the `fullName` property depends on
                    `firstName` and `lastName` to determine its value. You can tell Ember
                    about these dependencies like this:

                    ```javascript
                    MyApp.President = Ember.Object.extend({
                      firstName: '',
                      lastName:  '',

                      fullName: function() {
                        return this.get('firstName') + ' ' + this.get('lastName');

                        // Tell Ember.js that this computed property depends on firstName
                        // and lastName
                      }.property('firstName', 'lastName')
                    });
                    ```

                    Make sure you list these dependencies so Ember knows when to update
                    bindings that connect to a computed property. Changing a dependency
                    will not immediately trigger an update of the computed property, but
                    will instead clear the cache so that it is updated when the next `get`
                    is called on the property.

                    See [Ember.ComputedProperty](/api/classes/Ember.ComputedProperty.html), [Ember.computed](/api/#method_computed).

                    @method property
                    @for Function
                  */
            FunctionPrototype.property = function() {
                var ret = computed(this);
                // ComputedProperty.prototype.property expands properties; no need for us to
                // do so here.
                return ret.property.apply(ret, arguments);
            };

            /**
                    The `observes` extension of Javascript's Function prototype is available
                    when `Ember.EXTEND_PROTOTYPES` or `Ember.EXTEND_PROTOTYPES.Function` is
                    true, which is the default.

                    You can observe property changes simply by adding the `observes`
                    call to the end of your method declarations in classes that you write.
                    For example:

                    ```javascript
                    Ember.Object.extend({
                      valueObserver: function() {
                        // Executes whenever the "value" property changes
                      }.observes('value')
                    });
                    ```

                    In the future this method may become asynchronous. If you want to ensure
                    synchronous behavior, use `observesImmediately`.

                    See `Ember.observer`.

                    @method observes
                    @for Function
                  */
            FunctionPrototype.observes = function() {
                var addWatchedProperty = function (obs) {
                    watched.push(obs);
                };
                var watched = [];

                for (var i = 0; i < arguments.length; ++i) {
                    expandProperties(arguments[i], addWatchedProperty);
                }

                this.__ember_observes__ = watched;

                return this;
            };

            /**
                    The `observesImmediately` extension of Javascript's Function prototype is
                    available when `Ember.EXTEND_PROTOTYPES` or
                    `Ember.EXTEND_PROTOTYPES.Function` is true, which is the default.

                    You can observe property changes simply by adding the `observesImmediately`
                    call to the end of your method declarations in classes that you write.
                    For example:

                    ```javascript
                    Ember.Object.extend({
                      valueObserver: function() {
                        // Executes immediately after the "value" property changes
                      }.observesImmediately('value')
                    });
                    ```

                    In the future, `observes` may become asynchronous. In this event,
                    `observesImmediately` will maintain the synchronous behavior.

                    See `Ember.immediateObserver`.

                    @method observesImmediately
                    @for Function
                  */
            FunctionPrototype.observesImmediately = function() {
                for (var i = 0, l = arguments.length; i < l; i++) {
                    var arg = arguments[i];
                    Ember.assert("Immediate observers must observe internal properties only, not properties on other objects.", arg.indexOf('.') === -1);
                }

                // observes handles property expansion
                return this.observes.apply(this, arguments);
            };

            /**
                    The `observesBefore` extension of Javascript's Function prototype is
                    available when `Ember.EXTEND_PROTOTYPES` or
                    `Ember.EXTEND_PROTOTYPES.Function` is true, which is the default.

                    You can get notified when a property change is about to happen by
                    by adding the `observesBefore` call to the end of your method
                    declarations in classes that you write. For example:

                    ```javascript
                    Ember.Object.extend({
                      valueObserver: function() {
                        // Executes whenever the "value" property is about to change
                      }.observesBefore('value')
                    });
                    ```

                    See `Ember.beforeObserver`.

                    @method observesBefore
                    @for Function
                  */
            FunctionPrototype.observesBefore = function() {
                var addWatchedProperty = function (obs) {
                    watched.push(obs);
                };
                var watched = [];

                for (var i = 0; i < arguments.length; ++i) {
                    expandProperties(arguments[i], addWatchedProperty);
                }

                this.__ember_observesBefore__ = watched;

                return this;
            };

            /**
                    The `on` extension of Javascript's Function prototype is available
                    when `Ember.EXTEND_PROTOTYPES` or `Ember.EXTEND_PROTOTYPES.Function` is
                    true, which is the default.

                    You can listen for events simply by adding the `on` call to the end of
                    your method declarations in classes or mixins that you write. For example:

                    ```javascript
                    Ember.Mixin.create({
                      doSomethingWithElement: function() {
                        // Executes whenever the "didInsertElement" event fires
                      }.on('didInsertElement')
                    });
                    ```

                    See `Ember.on`.

                    @method on
                    @for Function
                  */
            FunctionPrototype.on = function() {
                var events = a_slice.call(arguments);
                this.__ember_listens__ = events;
                return this;
            };
        }
    });
    define("ember-runtime/ext/rsvp",
    ["ember-metal/core", "ember-metal/logger", "exports"],
    function(__dependency1__, __dependency2__, __exports__) {
        "use strict";
        /* globals RSVP:true */

        var Ember = __dependency1__["default"];
        var Logger = __dependency2__["default"];

        var RSVP = requireModule("rsvp");
        var Test, testModuleName = 'ember-testing/test';

        RSVP.onerrorDefault = function(error) {
            if (error instanceof Error) {
                if (Ember.testing) {
                    // ES6TODO: remove when possible
                    if (!Test && Ember.__loader.registry[testModuleName]) {
                        Test = requireModule(testModuleName)['default'];
                    }

                    if (Test && Test.adapter) {
                        Test.adapter.exception(error);
                    } else {
                        throw error;
                    }
                } else if (Ember.onerror) {
                    Ember.onerror(error);
                } else {
                    Logger.error(error.stack);
                    Ember.assert(error, false);
                }
            }
        };

        RSVP.on('error', RSVP.onerrorDefault);

        __exports__["default"] = RSVP;
    });
    define("ember-runtime/ext/string",
    ["ember-metal/core", "ember-runtime/system/string"],
    function(__dependency1__, __dependency2__) {
        "use strict";
        /**
            @module ember
            @submodule ember-runtime
            */

        var Ember = __dependency1__["default"];
        // Ember.EXTEND_PROTOTYPES, Ember.assert, Ember.FEATURES
        var fmt = __dependency2__.fmt;
        var w = __dependency2__.w;
        var loc = __dependency2__.loc;
        var camelize = __dependency2__.camelize;
        var decamelize = __dependency2__.decamelize;
        var dasherize = __dependency2__.dasherize;
        var underscore = __dependency2__.underscore;
        var capitalize = __dependency2__.capitalize;
        var classify = __dependency2__.classify;

        var StringPrototype = String.prototype;

        if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {

            /**
                    See [Ember.String.fmt](/api/classes/Ember.String.html#method_fmt).

                    @method fmt
                    @for String
                  */
            StringPrototype.fmt = function() {
                return fmt(this, arguments);
            };

            /**
                    See [Ember.String.w](/api/classes/Ember.String.html#method_w).

                    @method w
                    @for String
                  */
            StringPrototype.w = function() {
                return w(this);
            };

            /**
                    See [Ember.String.loc](/api/classes/Ember.String.html#method_loc).

                    @method loc
                    @for String
                  */
            StringPrototype.loc = function() {
                return loc(this, arguments);
            };

            /**
                    See [Ember.String.camelize](/api/classes/Ember.String.html#method_camelize).

                    @method camelize
                    @for String
                  */
            StringPrototype.camelize = function() {
                return camelize(this);
            };

            /**
                    See [Ember.String.decamelize](/api/classes/Ember.String.html#method_decamelize).

                    @method decamelize
                    @for String
                  */
            StringPrototype.decamelize = function() {
                return decamelize(this);
            };

            /**
                    See [Ember.String.dasherize](/api/classes/Ember.String.html#method_dasherize).

                    @method dasherize
                    @for String
                  */
            StringPrototype.dasherize = function() {
                return dasherize(this);
            };

            /**
                    See [Ember.String.underscore](/api/classes/Ember.String.html#method_underscore).

                    @method underscore
                    @for String
                  */
            StringPrototype.underscore = function() {
                return underscore(this);
            };

            /**
                    See [Ember.String.classify](/api/classes/Ember.String.html#method_classify).

                    @method classify
                    @for String
                  */
            StringPrototype.classify = function() {
                return classify(this);
            };

            /**
                    See [Ember.String.capitalize](/api/classes/Ember.String.html#method_capitalize).

                    @method capitalize
                    @for String
                  */
            StringPrototype.capitalize = function() {
                return capitalize(this);
            };
        }
    });
    define("ember-runtime/keys",
    ["ember-metal/enumerable_utils", "ember-metal/platform", "exports"],
    function(__dependency1__, __dependency2__, __exports__) {
        "use strict";
        var EnumerableUtils = __dependency1__["default"];
        var create = __dependency2__.create;

        /**
              Returns all of the keys defined on an object or hash. This is useful
              when inspecting objects for debugging. On browsers that support it, this
              uses the native `Object.keys` implementation.

              @method keys
              @for Ember
              @param {Object} obj
              @return {Array} Array containing keys of obj
            */
        var keys = Object.keys;
        if (!keys || create.isSimulated) {
            var prototypeProperties = [
            'constructor',
            'hasOwnProperty',
            'isPrototypeOf',
            'propertyIsEnumerable',
            'valueOf',
            'toLocaleString',
            'toString'
            ],
            pushPropertyName = function(obj, array, key) {
                // Prevents browsers that don't respect non-enumerability from
                // copying internal Ember properties
                if (key.substring(0, 2) === '__') 
                    return;
                if (key === '_super') 
                    return;
                if (EnumerableUtils.indexOf(array, key) >= 0) 
                    return;
                if (typeof obj.hasOwnProperty === 'function' && !obj.hasOwnProperty(key)) 
                    return;

                array.push(key);
            };

            keys = function keys(obj) {
                var ret = [], key;
                for (key in obj) {
                    pushPropertyName(obj, ret, key);
                }

                // IE8 doesn't enumerate property that named the same as prototype properties.
                for (var i = 0, l = prototypeProperties.length; i < l; i++) {
                    key = prototypeProperties[i];

                    pushPropertyName(obj, ret, key);
                }

                return ret;
            };
        }

        __exports__["default"] = keys;
    });
    define("ember-runtime/mixins/action_handler",
    ["ember-metal/merge", "ember-metal/mixin", "ember-metal/property_get", "ember-metal/utils", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-runtime
            */
        var merge = __dependency1__["default"];
        var Mixin = __dependency2__.Mixin;
        var get = __dependency3__.get;
        var typeOf = __dependency4__.typeOf;

        /**
              The `Ember.ActionHandler` mixin implements support for moving an `actions`
              property to an `_actions` property at extend time, and adding `_actions`
              to the object's mergedProperties list.

              `Ember.ActionHandler` is available on some familiar classes including
              `Ember.Route`, `Ember.View`, `Ember.Component`, and controllers such as
              `Ember.Controller` and `Ember.ObjectController`.
              (Internally the mixin is used by `Ember.CoreView`, `Ember.ControllerMixin`,
              and `Ember.Route` and available to the above classes through
              inheritance.)

              @class ActionHandler
              @namespace Ember
            */
        var ActionHandler = Mixin.create({
            mergedProperties: ['_actions'],

            /**
                    The collection of functions, keyed by name, available on this
                    `ActionHandler` as action targets.

                    These functions will be invoked when a matching `{{action}}` is triggered
                    from within a template and the application's current route is this route.

                    Actions can also be invoked from other parts of your application
                    via `ActionHandler#send`.

                    The `actions` hash will inherit action handlers from
                    the `actions` hash defined on extended parent classes
                    or mixins rather than just replace the entire hash, e.g.:

                    ```js
                    App.CanDisplayBanner = Ember.Mixin.create({
                      actions: {
                        displayBanner: function(msg) {
                          // ...
                        }
                      }
                    });

                    App.WelcomeRoute = Ember.Route.extend(App.CanDisplayBanner, {
                      actions: {
                        playMusic: function() {
                          // ...
                        }
                      }
                    });

                    // `WelcomeRoute`, when active, will be able to respond
                    // to both actions, since the actions hash is merged rather
                    // then replaced when extending mixins / parent classes.
                    this.send('displayBanner');
                    this.send('playMusic');
                    ```

                    Within a Controller, Route, View or Component's action handler,
                    the value of the `this` context is the Controller, Route, View or
                    Component object:

                    ```js
                    App.SongRoute = Ember.Route.extend({
                      actions: {
                        myAction: function() {
                          this.controllerFor("song");
                          this.transitionTo("other.route");
                          ...
                        }
                      }
                    });
                    ```

                    It is also possible to call `this._super()` from within an
                    action handler if it overrides a handler defined on a parent
                    class or mixin:

                    Take for example the following routes:

                    ```js
                    App.DebugRoute = Ember.Mixin.create({
                      actions: {
                        debugRouteInformation: function() {
                          console.debug("trololo");
                        }
                      }
                    });

                    App.AnnoyingDebugRoute = Ember.Route.extend(App.DebugRoute, {
                      actions: {
                        debugRouteInformation: function() {
                          // also call the debugRouteInformation of mixed in App.DebugRoute
                          this._super();

                          // show additional annoyance
                          window.alert(...);
                        }
                      }
                    });
                    ```

                    ## Bubbling

                    By default, an action will stop bubbling once a handler defined
                    on the `actions` hash handles it. To continue bubbling the action,
                    you must return `true` from the handler:

                    ```js
                    App.Router.map(function() {
                      this.resource("album", function() {
                        this.route("song");
                      });
                    });

                    App.AlbumRoute = Ember.Route.extend({
                      actions: {
                        startPlaying: function() {
                        }
                      }
                    });

                    App.AlbumSongRoute = Ember.Route.extend({
                      actions: {
                        startPlaying: function() {
                          // ...

                          if (actionShouldAlsoBeTriggeredOnParentRoute) {
                            return true;
                          }
                        }
                      }
                    });
                    ```

                    @property actions
                    @type Hash
                    @default null
                  */

            /**
                    Moves `actions` to `_actions` at extend time. Note that this currently
                    modifies the mixin themselves, which is technically dubious but
                    is practically of little consequence. This may change in the future.

                    @private
                    @method willMergeMixin
                  */
            willMergeMixin: function(props) {
                var hashName;

                if (!props._actions) {
                    Ember.assert("'actions' should not be a function", typeof(props.actions) !== 'function');

                    if (typeOf(props.actions) === 'object') {
                        hashName = 'actions';
                    } else if (typeOf(props.events) === 'object') {
                        Ember.deprecate('Action handlers contained in an `events` object are deprecated in favor of putting them in an `actions` object', false);
                        hashName = 'events';
                    }

                    if (hashName) {
                        props._actions = merge(props._actions || {}, props[hashName]);
                    }

                    delete props[hashName];
                }
            },

            /**
                    Triggers a named action on the `ActionHandler`. Any parameters
                    supplied after the `actionName` string will be passed as arguments
                    to the action target function.

                    If the `ActionHandler` has its `target` property set, actions may
                    bubble to the `target`. Bubbling happens when an `actionName` can
                    not be found in the `ActionHandler`'s `actions` hash or if the
                    action target function returns `true`.

                    Example

                    ```js
                    App.WelcomeRoute = Ember.Route.extend({
                      actions: {
                        playTheme: function() {
                           this.send('playMusic', 'theme.mp3');
                        },
                        playMusic: function(track) {
                          // ...
                        }
                      }
                    });
                    ```

                    @method send
                    @param {String} actionName The action to trigger
                    @param {*} context a context to send with the action
                  */
            send: function(actionName) {
                var args = [].slice.call(arguments, 1), target;

                if (this._actions && this._actions[actionName]) {
                    if (this._actions[actionName].apply(this, args) === true) {
                        // handler returned true, so this action will bubble
                    } else {
                        return;
                    }
                } else if (!Ember.FEATURES.isEnabled('ember-routing-drop-deprecated-action-style') && this.deprecatedSend && this.deprecatedSendHandles && this.deprecatedSendHandles(actionName)) {
                    Ember.warn("The current default is deprecated but will prefer to handle actions directly on the controller instead of a similarly named action in the actions hash. To turn off this deprecated feature set: Ember.FEATURES['ember-routing-drop-deprecated-action-style'] = true");
                    if (this.deprecatedSend.apply(this, [].slice.call(arguments)) === true) {
                        // handler return true, so this action will bubble
                    } else {
                        return;
                    }
                }

                if (target = get(this, 'target')) {
                    Ember.assert("The `target` for " + this + " (" + target + ") does not have a `send` method", typeof target.send === 'function');
                    target.send.apply(target, arguments);
                }
            }
        });

        __exports__["default"] = ActionHandler;
    });
    define("ember-runtime/mixins/array",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/computed", "ember-metal/is_none", "ember-runtime/mixins/enumerable", "ember-metal/enumerable_utils", "ember-metal/mixin", "ember-metal/property_events", "ember-metal/events", "ember-metal/watching", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-runtime
            */

        // ..........................................................
        // HELPERS
        //
        var Ember = __dependency1__["default"];
        // ES6TODO: Ember.A

        var get = __dependency2__.get;
        var set = __dependency3__.set;
        var computed = __dependency4__.computed;
        var cacheFor = __dependency4__.cacheFor;
        var isNone = __dependency5__.isNone;
        var none = __dependency5__.none;
        var Enumerable = __dependency6__["default"];
        var map = __dependency7__.map;
        var Mixin = __dependency8__.Mixin;
        var required = __dependency8__.required;
        var propertyWillChange = __dependency9__.propertyWillChange;
        var propertyDidChange = __dependency9__.propertyDidChange;
        var addListener = __dependency10__.addListener;
        var removeListener = __dependency10__.removeListener;
        var sendEvent = __dependency10__.sendEvent;
        var hasListeners = __dependency10__.hasListeners;
        var isWatching = __dependency11__.isWatching;

        // ..........................................................
        // ARRAY
        //
        /**
              This mixin implements Observer-friendly Array-like behavior. It is not a
              concrete implementation, but it can be used up by other classes that want
              to appear like arrays.

              For example, ArrayProxy and ArrayController are both concrete classes that can
              be instantiated to implement array-like behavior. Both of these classes use
              the Array Mixin by way of the MutableArray mixin, which allows observable
              changes to be made to the underlying array.

              Unlike `Ember.Enumerable,` this mixin defines methods specifically for
              collections that provide index-ordered access to their contents. When you
              are designing code that needs to accept any kind of Array-like object, you
              should use these methods instead of Array primitives because these will
              properly notify observers of changes to the array.

              Although these methods are efficient, they do add a layer of indirection to
              your application so it is a good idea to use them only when you need the
              flexibility of using both true JavaScript arrays and "virtual" arrays such
              as controllers and collections.

              You can use the methods defined in this module to access and modify array
              contents in a KVO-friendly way. You can also be notified whenever the
              membership of an array changes by using `.observes('myArray.[]')`.

              To support `Ember.Array` in your own class, you must override two
              primitives to use it: `replace()` and `objectAt()`.

              Note that the Ember.Array mixin also incorporates the `Ember.Enumerable`
              mixin. All `Ember.Array`-like objects are also enumerable.

              @class Array
              @namespace Ember
              @uses Ember.Enumerable
              @since Ember 0.9.0
            */
        __exports__["default"] = Mixin.create(Enumerable, {

            /**
                    Your array must support the `length` property. Your replace methods should
                    set this property whenever it changes.

                    @property {Number} length
                  */
            length: required(),

            /**
                    Returns the object at the given `index`. If the given `index` is negative
                    or is greater or equal than the array length, returns `undefined`.

                    This is one of the primitives you must implement to support `Ember.Array`.
                    If your object supports retrieving the value of an array item using `get()`
                    (i.e. `myArray.get(0)`), then you do not need to implement this method
                    yourself.

                    ```javascript
                    var arr = ['a', 'b', 'c', 'd'];
                    arr.objectAt(0);   // "a"
                    arr.objectAt(3);   // "d"
                    arr.objectAt(-1);  // undefined
                    arr.objectAt(4);   // undefined
                    arr.objectAt(5);   // undefined
                    ```

                    @method objectAt
                    @param {Number} idx The index of the item to return.
                    @return {*} item at index or undefined
                  */
            objectAt: function(idx) {
                if ((idx < 0) || (idx >= get(this, 'length'))) 
                    return undefined;
                return get(this, idx);
            },

            /**
                    This returns the objects at the specified indexes, using `objectAt`.

                    ```javascript
                    var arr = ['a', 'b', 'c', 'd'];
                    arr.objectsAt([0, 1, 2]);  // ["a", "b", "c"]
                    arr.objectsAt([2, 3, 4]);  // ["c", "d", undefined]
                    ```

                    @method objectsAt
                    @param {Array} indexes An array of indexes of items to return.
                    @return {Array}
                   */
            objectsAt: function(indexes) {
                var self = this;
                return map(indexes, function(idx) {
                    return self.objectAt(idx);
                });
            },

            // overrides Ember.Enumerable version
            nextObject: function(idx) {
                return this.objectAt(idx);
            },

            /**
                    This is the handler for the special array content property. If you get
                    this property, it will return this. If you set this property to a new
                    array, it will replace the current content.

                    This property overrides the default property defined in `Ember.Enumerable`.

                    @property []
                    @return this
                  */
            '[]': computed(function(key, value) {
                if (value !== undefined) 
                    this.replace(0, get(this, 'length'), value) ;
                return this ;
            }),

            firstObject: computed(function() {
                return this.objectAt(0);
            }),

            lastObject: computed(function() {
                return this.objectAt(get(this, 'length')-1);
            }),

            // optimized version from Enumerable
            contains: function(obj) {
                return this.indexOf(obj) >= 0;
            },

            // Add any extra methods to Ember.Array that are native to the built-in Array.
            /**
                    Returns a new array that is a slice of the receiver. This implementation
                    uses the observable array methods to retrieve the objects for the new
                    slice.

                    ```javascript
                    var arr = ['red', 'green', 'blue'];
                    arr.slice(0);       // ['red', 'green', 'blue']
                    arr.slice(0, 2);    // ['red', 'green']
                    arr.slice(1, 100);  // ['green', 'blue']
                    ```

                    @method slice
                    @param {Integer} beginIndex (Optional) index to begin slicing from.
                    @param {Integer} endIndex (Optional) index to end the slice at (but not included).
                    @return {Array} New array with specified slice
                  */
            slice: function(beginIndex, endIndex) {
                var ret = Ember.A();
                var length = get(this, 'length') ;
                if (isNone(beginIndex)) 
                    beginIndex = 0 ;
                if (isNone(endIndex) || (endIndex > length)) 
                    endIndex = length ;

                if (beginIndex < 0) 
                    beginIndex = length + beginIndex;
                if (endIndex < 0) 
                    endIndex = length + endIndex;

                while (beginIndex < endIndex) {
                    ret[ret.length] = this.objectAt(beginIndex++) ;
                }
                return ret ;
            },

            /**
                    Returns the index of the given object's first occurrence.
                    If no `startAt` argument is given, the starting location to
                    search is 0. If it's negative, will count backward from
                    the end of the array. Returns -1 if no match is found.

                    ```javascript
                    var arr = ["a", "b", "c", "d", "a"];
                    arr.indexOf("a");       //  0
                    arr.indexOf("z");       // -1
                    arr.indexOf("a", 2);    //  4
                    arr.indexOf("a", -1);   //  4
                    arr.indexOf("b", 3);    // -1
                    arr.indexOf("a", 100);  // -1
                    ```

                    @method indexOf
                    @param {Object} object the item to search for
                    @param {Number} startAt optional starting location to search, default 0
                    @return {Number} index or -1 if not found
                  */
            indexOf: function(object, startAt) {
                var idx, len = get(this, 'length');

                if (startAt === undefined) 
                    startAt = 0;
                if (startAt < 0) 
                    startAt += len;

                for (idx = startAt; idx < len; idx++) {
                    if (this.objectAt(idx) === object) 
                        return idx;
                }
                return -1;
            },

            /**
                    Returns the index of the given object's last occurrence.
                    If no `startAt` argument is given, the search starts from
                    the last position. If it's negative, will count backward
                    from the end of the array. Returns -1 if no match is found.

                    ```javascript
                    var arr = ["a", "b", "c", "d", "a"];
                    arr.lastIndexOf("a");       //  4
                    arr.lastIndexOf("z");       // -1
                    arr.lastIndexOf("a", 2);    //  0
                    arr.lastIndexOf("a", -1);   //  4
                    arr.lastIndexOf("b", 3);    //  1
                    arr.lastIndexOf("a", 100);  //  4
                    ```

                    @method lastIndexOf
                    @param {Object} object the item to search for
                    @param {Number} startAt optional starting location to search, default 0
                    @return {Number} index or -1 if not found
                  */
            lastIndexOf: function(object, startAt) {
                var idx, len = get(this, 'length');

                if (startAt === undefined || startAt >= len) 
                    startAt = len-1;
                if (startAt < 0) 
                    startAt += len;

                for (idx = startAt; idx >= 0; idx--) {
                    if (this.objectAt(idx) === object) 
                        return idx;
                }
                return -1;
            },

            // ..........................................................
            // ARRAY OBSERVERS
            //

            /**
                    Adds an array observer to the receiving array. The array observer object
                    normally must implement two methods:

                    * `arrayWillChange(observedObj, start, removeCount, addCount)` - This method will be
                      called just before the array is modified.
                    * `arrayDidChange(observedObj, start, removeCount, addCount)` - This method will be
                      called just after the array is modified.

                    Both callbacks will be passed the observed object, starting index of the
                    change as well a a count of the items to be removed and added. You can use
                    these callbacks to optionally inspect the array during the change, clear
                    caches, or do any other bookkeeping necessary.

                    In addition to passing a target, you can also include an options hash
                    which you can use to override the method names that will be invoked on the
                    target.

                    @method addArrayObserver
                    @param {Object} target The observer object.
                    @param {Hash} opts Optional hash of configuration options including
                      `willChange` and `didChange` option.
                    @return {Ember.Array} receiver
                  */
            addArrayObserver: function(target, opts) {
                var willChange = (opts && opts.willChange) || 'arrayWillChange',
                didChange = (opts && opts.didChange) || 'arrayDidChange';

                var hasObservers = get(this, 'hasArrayObservers');
                if (!hasObservers) 
                    propertyWillChange(this, 'hasArrayObservers');
                addListener(this, '@array:before', target, willChange);
                addListener(this, '@array:change', target, didChange);
                if (!hasObservers) 
                    propertyDidChange(this, 'hasArrayObservers');
                return this;
            },

            /**
                    Removes an array observer from the object if the observer is current
                    registered. Calling this method multiple times with the same object will
                    have no effect.

                    @method removeArrayObserver
                    @param {Object} target The object observing the array.
                    @param {Hash} opts Optional hash of configuration options including
                      `willChange` and `didChange` option.
                    @return {Ember.Array} receiver
                  */
            removeArrayObserver: function(target, opts) {
                var willChange = (opts && opts.willChange) || 'arrayWillChange',
                didChange = (opts && opts.didChange) || 'arrayDidChange';

                var hasObservers = get(this, 'hasArrayObservers');
                if (hasObservers) 
                    propertyWillChange(this, 'hasArrayObservers');
                removeListener(this, '@array:before', target, willChange);
                removeListener(this, '@array:change', target, didChange);
                if (hasObservers) 
                    propertyDidChange(this, 'hasArrayObservers');
                return this;
            },

            /**
                    Becomes true whenever the array currently has observers watching changes
                    on the array.

                    @property {Boolean} hasArrayObservers
                  */
            hasArrayObservers: computed(function() {
                return hasListeners(this, '@array:change') || hasListeners(this, '@array:before');
            }),

            /**
                    If you are implementing an object that supports `Ember.Array`, call this
                    method just before the array content changes to notify any observers and
                    invalidate any related properties. Pass the starting index of the change
                    as well as a delta of the amounts to change.

                    @method arrayContentWillChange
                    @param {Number} startIdx The starting index in the array that will change.
                    @param {Number} removeAmt The number of items that will be removed. If you
                      pass `null` assumes 0
                    @param {Number} addAmt The number of items that will be added. If you
                      pass `null` assumes 0.
                    @return {Ember.Array} receiver
                  */
            arrayContentWillChange: function(startIdx, removeAmt, addAmt) {

                // if no args are passed assume everything changes
                if (startIdx === undefined) {
                    startIdx = 0;
                    removeAmt = addAmt = -1;
                } else {
                    if (removeAmt === undefined) 
                        removeAmt =- 1;
                    if (addAmt === undefined) 
                        addAmt =- 1;
                }

                // Make sure the @each proxy is set up if anyone is observing @each
                if (isWatching(this, '@each')) {
                    get(this, '@each');
                }

                sendEvent(this, '@array:before', [this, startIdx, removeAmt, addAmt]);

                var removing, lim;
                if (startIdx >= 0 && removeAmt >= 0 && get(this, 'hasEnumerableObservers')) {
                    removing = [];
                    lim = startIdx + removeAmt;
                    for (var idx = startIdx; idx < lim; idx++) 
                        removing.push(this.objectAt(idx));
                } else {
                    removing = removeAmt;
                }

                this.enumerableContentWillChange(removing, addAmt);

                return this;
            },

            /**
                    If you are implementing an object that supports `Ember.Array`, call this
                    method just after the array content changes to notify any observers and
                    invalidate any related properties. Pass the starting index of the change
                    as well as a delta of the amounts to change.

                    @method arrayContentDidChange
                    @param {Number} startIdx The starting index in the array that did change.
                    @param {Number} removeAmt The number of items that were removed. If you
                      pass `null` assumes 0
                    @param {Number} addAmt The number of items that were added. If you
                      pass `null` assumes 0.
                    @return {Ember.Array} receiver
                  */
            arrayContentDidChange: function(startIdx, removeAmt, addAmt) {

                // if no args are passed assume everything changes
                if (startIdx === undefined) {
                    startIdx = 0;
                    removeAmt = addAmt = -1;
                } else {
                    if (removeAmt === undefined) 
                        removeAmt =- 1;
                    if (addAmt === undefined) 
                        addAmt =- 1;
                }

                var adding, lim;
                if (startIdx >= 0 && addAmt >= 0 && get(this, 'hasEnumerableObservers')) {
                    adding = [];
                    lim = startIdx + addAmt;
                    for (var idx = startIdx; idx < lim; idx++) 
                        adding.push(this.objectAt(idx));
                } else {
                    adding = addAmt;
                }

                this.enumerableContentDidChange(removeAmt, adding);
                sendEvent(this, '@array:change', [this, startIdx, removeAmt, addAmt]);

                var length = get(this, 'length'),
                cachedFirst = cacheFor(this, 'firstObject'),
                cachedLast = cacheFor(this, 'lastObject');
                if (this.objectAt(0) !== cachedFirst) {
                    propertyWillChange(this, 'firstObject');
                    propertyDidChange(this, 'firstObject');
                }
                if (this.objectAt(length-1) !== cachedLast) {
                    propertyWillChange(this, 'lastObject');
                    propertyDidChange(this, 'lastObject');
                }

                return this;
            },

            // ..........................................................
            // ENUMERATED PROPERTIES
            //

            /**
                    Returns a special object that can be used to observe individual properties
                    on the array. Just get an equivalent property on this object and it will
                    return an enumerable that maps automatically to the named key on the
                    member objects.

                    If you merely want to watch for any items being added or removed to the array,
                    use the `[]` property instead of `@each`.

                    @property @each
                  */
            '@each': computed(function() {
                if (!this.__each) {
                    // ES6TODO: GRRRRR
                    var EachProxy = requireModule('ember-runtime/system/each_proxy')['EachProxy'];

                    this.__each = new EachProxy(this);
                }

                return this.__each;
            })
        });
    });
    define("ember-runtime/mixins/comparable",
    ["ember-metal/mixin", "exports"],
    function(__dependency1__, __exports__) {
        "use strict";
        var Mixin = __dependency1__.Mixin;
        var required = __dependency1__.required;

        /**
            @module ember
            @submodule ember-runtime
            */

        /**
              Implements some standard methods for comparing objects. Add this mixin to
              any class you create that can compare its instances.

              You should implement the `compare()` method.

              @class Comparable
              @namespace Ember
              @since Ember 0.9
            */
        __exports__["default"] = Mixin.create({

            /**
                    Override to return the result of the comparison of the two parameters. The
                    compare method should return:

                    - `-1` if `a < b`
                    - `0` if `a == b`
                    - `1` if `a > b`

                    Default implementation raises an exception.

                    @method compare
                    @param a {Object} the first object to compare
                    @param b {Object} the second object to compare
                    @return {Integer} the result of the comparison
                  */
            compare: required(Function)
        });
    });
    define("ember-runtime/mixins/controller",
    ["ember-metal/core", "ember-metal/property_get", "ember-runtime/system/object", "ember-metal/mixin", "ember-metal/computed", "ember-runtime/mixins/action_handler", "ember-runtime/mixins/controller_content_model_alias_deprecation", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // Ember.assert, Ember.deprecate
        var get = __dependency2__.get;
        var EmberObject = __dependency3__["default"];
        var Mixin = __dependency4__.Mixin;
        var computed = __dependency5__.computed;
        var ActionHandler = __dependency6__["default"];
        var ControllerContentModelAliasDeprecation = __dependency7__["default"];

        /**
              `Ember.ControllerMixin` provides a standard interface for all classes that
              compose Ember's controller layer: `Ember.Controller`,
              `Ember.ArrayController`, and `Ember.ObjectController`.

              @class ControllerMixin
              @namespace Ember
              @uses Ember.ActionHandler
            */
        __exports__["default"] = Mixin.create(ActionHandler, ControllerContentModelAliasDeprecation, {
            /* ducktype as a controller */
            isController: true,

            /**
                    The object to which actions from the view should be sent.

                    For example, when a Handlebars template uses the `{{action}}` helper,
                    it will attempt to send the action to the view's controller's `target`.

                    By default, the value of the target property is set to the router, and
                    is injected when a controller is instantiated. This injection is defined
                    in Ember.Application#buildContainer, and is applied as part of the
                    applications initialization process. It can also be set after a controller
                    has been instantiated, for instance when using the render helper in a
                    template, or when a controller is used as an `itemController`. In most
                    cases the `target` property will automatically be set to the logical
                    consumer of actions for the controller.

                    @property target
                    @default null
                  */
            target: null,

            container: null,

            parentController: null,

            store: null,

            model: null,
            content: computed.alias('model'),

            deprecatedSendHandles: function(actionName) {
                return !!this[actionName];
            },

            deprecatedSend: function(actionName) {
                var args = [].slice.call(arguments, 1);
                Ember.assert('' + this + " has the action " + actionName + " but it is not a function", typeof this[actionName] === 'function');
                Ember.deprecate('Action handlers implemented directly on controllers are deprecated in favor of action handlers on an `actions` object ( action: `' + actionName + '` on ' + this + ')', false);
                this[actionName].apply(this, args);
                return;
            }
        });
    });
    define("ember-runtime/mixins/controller_content_model_alias_deprecation",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/mixin", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // Ember.deprecate
        var get = __dependency2__.get;
        var Mixin = __dependency3__.Mixin;

        /**
              The ControllerContentModelAliasDeprecation mixin is used to provide a useful
              deprecation warning when specifying `content` directly on a `Ember.Controller`
              (without also specifying `model`).

              Ember versions prior to 1.7 used `model` as an alias of `content`, but due to
              much confusion this alias was reversed (so `content` is now an alias of `model).

              This change reduces many caveats with model/content, and also sets a
              simple ground rule: Never set a controllers content, rather always set
              it's model and ember will do the right thing.


              `Ember.ControllerContentModelAliasDeprecation` is used internally by Ember in
              `Ember.Controller`.

              @class ControllerContentModelAliasDeprecation
              @namespace Ember
            */
        __exports__["default"] = Mixin.create({
            /**
                    @private

                    Moves `content` to `model`  at extend time if a `model` is not also specified.

                    Note that this currently modifies the mixin themselves, which is technically
                    dubious but is practically of little consequence. This may change in the
                    future.

                    @method willMergeMixin
                    @since 1.4.0
                  */
            willMergeMixin: function(props) {
                // Calling super is only OK here since we KNOW that
                // there is another Mixin loaded first.
                this._super.apply(this, arguments);

                var modelSpecified = !!props.model;

                if (props.content && !modelSpecified) {
                    props.model = props.content;
                    delete props['content'];

                    Ember.deprecate('Do not specify `content` on a Controller, use `model` instead.', false);
                }
            }
        });
    });
    define("ember-runtime/mixins/copyable",
    ["ember-metal/property_get", "ember-metal/property_set", "ember-metal/mixin", "ember-runtime/mixins/freezable", "ember-runtime/system/string", "ember-metal/error", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-runtime
            */


        var get = __dependency1__.get;
        var set = __dependency2__.set;
        var required = __dependency3__.required;
        var Freezable = __dependency4__.Freezable;
        var Mixin = __dependency3__.Mixin;
        var fmt = __dependency5__.fmt;
        var EmberError = __dependency6__["default"];


        /**
              Implements some standard methods for copying an object. Add this mixin to
              any object you create that can create a copy of itself. This mixin is
              added automatically to the built-in array.

              You should generally implement the `copy()` method to return a copy of the
              receiver.

              Note that `frozenCopy()` will only work if you also implement
              `Ember.Freezable`.

              @class Copyable
              @namespace Ember
              @since Ember 0.9
            */
        __exports__["default"] = Mixin.create({
            /**
                    Override to return a copy of the receiver. Default implementation raises
                    an exception.

                    @method copy
                    @param {Boolean} deep if `true`, a deep copy of the object should be made
                    @return {Object} copy of receiver
                  */
            copy: required(Function),

            /**
                    If the object implements `Ember.Freezable`, then this will return a new
                    copy if the object is not frozen and the receiver if the object is frozen.

                    Raises an exception if you try to call this method on a object that does
                    not support freezing.

                    You should use this method whenever you want a copy of a freezable object
                    since a freezable object can simply return itself without actually
                    consuming more memory.

                    @method frozenCopy
                    @return {Object} copy of receiver or receiver
                  */
            frozenCopy: function() {
                if (Freezable && Freezable.detect(this)) {
                    return get(this, 'isFrozen') ? this : this.copy().freeze();
                } else {
                    throw new EmberError(fmt("%@ does not support freezing", [this]));
                }
            }
        });
    });
    define("ember-runtime/mixins/deferred",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/mixin", "ember-metal/computed", "ember-metal/run_loop", "ember-runtime/ext/rsvp", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // Ember.FEATURES, Ember.Test
        var get = __dependency2__.get;
        var Mixin = __dependency3__.Mixin;
        var computed = __dependency4__.computed;
        var run = __dependency5__["default"];
        var RSVP = __dependency6__["default"];

        var asyncStart = function() {
            if (Ember.Test && Ember.Test.adapter) {
                Ember.Test.adapter.asyncStart();
            }
        };

        var asyncEnd = function() {
            if (Ember.Test && Ember.Test.adapter) {
                Ember.Test.adapter.asyncEnd();
            }
        };

        RSVP.configure('async', function(callback, promise) {
            var async = !run.currentRunLoop;

            if (Ember.testing && async) {
                asyncStart();
            }

            run.backburner.schedule('actions', function() {
                if (Ember.testing && async) {
                    asyncEnd();
                }
                callback(promise);
            });
        });

        RSVP.Promise.prototype.fail = function(callback, label) {
            Ember.deprecate('RSVP.Promise.fail has been renamed as RSVP.Promise.catch');
            return this['catch'](callback, label);
        };

        /**
            @module ember
            @submodule ember-runtime
            */


        /**
              @class Deferred
              @namespace Ember
             */
        __exports__["default"] = Mixin.create({
            /**
                    Add handlers to be called when the Deferred object is resolved or rejected.

                    @method then
                    @param {Function} resolve a callback function to be called when done
                    @param {Function} reject  a callback function to be called when failed
                  */
            then: function(resolve, reject, label) {
                var deferred, promise, entity;

                entity = this;
                deferred = get(this, '_deferred');
                promise = deferred.promise;

                function fulfillmentHandler(fulfillment) {
                    if (fulfillment === promise) {
                        return resolve(entity);
                    } else {
                        return resolve(fulfillment);
                    }
                }

                return promise.then(resolve && fulfillmentHandler, reject, label);
            },

            /**
                    Resolve a Deferred object and call any `doneCallbacks` with the given args.

                    @method resolve
                  */
            resolve: function(value) {
                var deferred, promise;

                deferred = get(this, '_deferred');
                promise = deferred.promise;

                if (value === this) {
                    deferred.resolve(promise);
                } else {
                    deferred.resolve(value);
                }
            },

            /**
                    Reject a Deferred object and call any `failCallbacks` with the given args.

                    @method reject
                  */
            reject: function(value) {
                get(this, '_deferred').reject(value);
            },

            _deferred: computed(function() {
                Ember.deprecate('Usage of Ember.DeferredMixin or Ember.Deferred is deprecated.', this._suppressDeferredDeprecation);

                return RSVP.defer('Ember: DeferredMixin - ' + this);
            })
        });
    });
    define("ember-runtime/mixins/enumerable",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/utils", "ember-metal/mixin", "ember-metal/enumerable_utils", "ember-metal/computed", "ember-metal/property_events", "ember-metal/events", "ember-runtime/compare", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-runtime
            */

        // ..........................................................
        // HELPERS
        //

        var Ember = __dependency1__["default"];
        var get = __dependency2__.get;
        var set = __dependency3__.set;
        var apply = __dependency4__.apply;
        var Mixin = __dependency5__.Mixin;
        var required = __dependency5__.required;
        var aliasMethod = __dependency5__.aliasMethod;
        var indexOf = __dependency6__.indexOf;
        var computed = __dependency7__.computed;
        var propertyWillChange = __dependency8__.propertyWillChange;
        var propertyDidChange = __dependency8__.propertyDidChange;
        var addListener = __dependency9__.addListener;
        var removeListener = __dependency9__.removeListener;
        var sendEvent = __dependency9__.sendEvent;
        var hasListeners = __dependency9__.hasListeners;
        var compare = __dependency10__["default"];

        var a_slice = Array.prototype.slice;

        var contexts = [];

        function popCtx() {
            return contexts.length === 0 ? {} : contexts.pop();
        }

        function pushCtx(ctx) {
            contexts.push(ctx);
            return null;
        }

        function iter(key, value) {
            var valueProvided = arguments.length === 2;

            function i(item) {
                var cur = get(item, key);
                return valueProvided ? value === cur : !!cur;
            }

            return i;
        }

        /**
              This mixin defines the common interface implemented by enumerable objects
              in Ember. Most of these methods follow the standard Array iteration
              API defined up to JavaScript 1.8 (excluding language-specific features that
              cannot be emulated in older versions of JavaScript).

              This mixin is applied automatically to the Array class on page load, so you
              can use any of these methods on simple arrays. If Array already implements
              one of these methods, the mixin will not override them.

              ## Writing Your Own Enumerable

              To make your own custom class enumerable, you need two items:

              1. You must have a length property. This property should change whenever
                 the number of items in your enumerable object changes. If you use this
                 with an `Ember.Object` subclass, you should be sure to change the length
                 property using `set().`

              2. You must implement `nextObject().` See documentation.

              Once you have these two methods implemented, apply the `Ember.Enumerable` mixin
              to your class and you will be able to enumerate the contents of your object
              like any other collection.

              ## Using Ember Enumeration with Other Libraries

              Many other libraries provide some kind of iterator or enumeration like
              facility. This is often where the most common API conflicts occur.
              Ember's API is designed to be as friendly as possible with other
              libraries by implementing only methods that mostly correspond to the
              JavaScript 1.8 API.

              @class Enumerable
              @namespace Ember
              @since Ember 0.9
            */
        __exports__["default"] = Mixin.create({

            /**
                    Implement this method to make your class enumerable.

                    This method will be call repeatedly during enumeration. The index value
                    will always begin with 0 and increment monotonically. You don't have to
                    rely on the index value to determine what object to return, but you should
                    always check the value and start from the beginning when you see the
                    requested index is 0.

                    The `previousObject` is the object that was returned from the last call
                    to `nextObject` for the current iteration. This is a useful way to
                    manage iteration if you are tracing a linked list, for example.

                    Finally the context parameter will always contain a hash you can use as
                    a "scratchpad" to maintain any other state you need in order to iterate
                    properly. The context object is reused and is not reset between
                    iterations so make sure you setup the context with a fresh state whenever
                    the index parameter is 0.

                    Generally iterators will continue to call `nextObject` until the index
                    reaches the your current length-1. If you run out of data before this
                    time for some reason, you should simply return undefined.

                    The default implementation of this method simply looks up the index.
                    This works great on any Array-like objects.

                    @method nextObject
                    @param {Number} index the current index of the iteration
                    @param {Object} previousObject the value returned by the last call to
                      `nextObject`.
                    @param {Object} context a context object you can use to maintain state.
                    @return {Object} the next object in the iteration or undefined
                  */
            nextObject: required(Function),

            /**
                    Helper method returns the first object from a collection. This is usually
                    used by bindings and other parts of the framework to extract a single
                    object if the enumerable contains only one item.

                    If you override this method, you should implement it so that it will
                    always return the same value each time it is called. If your enumerable
                    contains only one object, this method should always return that object.
                    If your enumerable is empty, this method should return `undefined`.

                    ```javascript
                    var arr = ["a", "b", "c"];
                    arr.get('firstObject');  // "a"

                    var arr = [];
                    arr.get('firstObject');  // undefined
                    ```

                    @property firstObject
                    @return {Object} the object or undefined
                  */
            firstObject: computed('[]', function() {
                if (get(this, 'length') === 0) 
                    return undefined ;

                // handle generic enumerables
                var context = popCtx(), ret;
                ret = this.nextObject(0, null, context);
                pushCtx(context);
                return ret;
            }),

            /**
                    Helper method returns the last object from a collection. If your enumerable
                    contains only one object, this method should always return that object.
                    If your enumerable is empty, this method should return `undefined`.

                    ```javascript
                    var arr = ["a", "b", "c"];
                    arr.get('lastObject');  // "c"

                    var arr = [];
                    arr.get('lastObject');  // undefined
                    ```

                    @property lastObject
                    @return {Object} the last object or undefined
                  */
            lastObject: computed('[]', function() {
                var len = get(this, 'length');
                if (len === 0) 
                    return undefined ;
                var context = popCtx(), idx = 0, cur, last = null;
                do {
                    last = cur;
                    cur = this.nextObject(idx++, last, context);
                }
                while (cur !== undefined);
                pushCtx(context);
                return last;
            }),

            /**
                    Returns `true` if the passed object can be found in the receiver. The
                    default version will iterate through the enumerable until the object
                    is found. You may want to override this with a more efficient version.

                    ```javascript
                    var arr = ["a", "b", "c"];
                    arr.contains("a"); // true
                    arr.contains("z"); // false
                    ```

                    @method contains
                    @param {Object} obj The object to search for.
                    @return {Boolean} `true` if object is found in enumerable.
                  */
            contains: function(obj) {
                return this.find(function(item) {
                    return item === obj;
                }) !== undefined;
            },

            /**
                    Iterates through the enumerable, calling the passed function on each
                    item. This method corresponds to the `forEach()` method defined in
                    JavaScript 1.6.

                    The callback method you provide should have the following signature (all
                    parameters are optional):

                    ```javascript
                    function(item, index, enumerable);
                    ```

                    - `item` is the current item in the iteration.
                    - `index` is the current index in the iteration.
                    - `enumerable` is the enumerable object itself.

                    Note that in addition to a callback, you can also pass an optional target
                    object that will be set as `this` on the context. This is a good way
                    to give your iterator function access to the current object.

                    @method forEach
                    @param {Function} callback The callback to execute
                    @param {Object} [target] The target object to use
                    @return {Object} receiver
                  */
            forEach: function(callback, target) {
                if (typeof callback !== 'function') 
                    throw new TypeError() ;
                var len = get(this, 'length'), last = null, context = popCtx();

                if (target === undefined) 
                    target = null;

                for (var idx = 0; idx < len; idx++) {
                    var next = this.nextObject(idx, last, context) ;
                    callback.call(target, next, idx, this);
                    last = next ;
                }
                last = null ;
                context = pushCtx(context);
                return this ;
            },

            /**
                    Alias for `mapBy`

                    @method getEach
                    @param {String} key name of the property
                    @return {Array} The mapped array.
                  */
            getEach: function(key) {
                return this.mapBy(key);
            },

            /**
                    Sets the value on the named property for each member. This is more
                    efficient than using other methods defined on this helper. If the object
                    implements Ember.Observable, the value will be changed to `set(),` otherwise
                    it will be set directly. `null` objects are skipped.

                    @method setEach
                    @param {String} key The key to set
                    @param {Object} value The object to set
                    @return {Object} receiver
                  */
            setEach: function(key, value) {
                return this.forEach(function(item) {
                    set(item, key, value);
                });
            },

            /**
                    Maps all of the items in the enumeration to another value, returning
                    a new array. This method corresponds to `map()` defined in JavaScript 1.6.

                    The callback method you provide should have the following signature (all
                    parameters are optional):

                    ```javascript
                    function(item, index, enumerable);
                    ```

                    - `item` is the current item in the iteration.
                    - `index` is the current index in the iteration.
                    - `enumerable` is the enumerable object itself.

                    It should return the mapped value.

                    Note that in addition to a callback, you can also pass an optional target
                    object that will be set as `this` on the context. This is a good way
                    to give your iterator function access to the current object.

                    @method map
                    @param {Function} callback The callback to execute
                    @param {Object} [target] The target object to use
                    @return {Array} The mapped array.
                  */
            map: function(callback, target) {
                var ret = Ember.A();
                this.forEach(function(x, idx, i) {
                    ret[idx] = callback.call(target, x, idx, i);
                });
                return ret ;
            },

            /**
                    Similar to map, this specialized function returns the value of the named
                    property on all items in the enumeration.

                    @method mapBy
                    @param {String} key name of the property
                    @return {Array} The mapped array.
                  */
            mapBy: function(key) {
                return this.map(function(next) {
                    return get(next, key);
                });
            },

            /**
                    Similar to map, this specialized function returns the value of the named
                    property on all items in the enumeration.

                    @method mapProperty
                    @param {String} key name of the property
                    @return {Array} The mapped array.
                    @deprecated Use `mapBy` instead
                  */

            mapProperty: aliasMethod('mapBy'),

            /**
                    Returns an array with all of the items in the enumeration that the passed
                    function returns true for. This method corresponds to `filter()` defined in
                    JavaScript 1.6.

                    The callback method you provide should have the following signature (all
                    parameters are optional):

                    ```javascript
                    function(item, index, enumerable);
                    ```

                    - `item` is the current item in the iteration.
                    - `index` is the current index in the iteration.
                    - `enumerable` is the enumerable object itself.

                    It should return the `true` to include the item in the results, `false`
                    otherwise.

                    Note that in addition to a callback, you can also pass an optional target
                    object that will be set as `this` on the context. This is a good way
                    to give your iterator function access to the current object.

                    @method filter
                    @param {Function} callback The callback to execute
                    @param {Object} [target] The target object to use
                    @return {Array} A filtered array.
                  */
            filter: function(callback, target) {
                var ret = Ember.A();
                this.forEach(function(x, idx, i) {
                    if (callback.call(target, x, idx, i)) 
                        ret.push(x);
                });
                return ret ;
            },

            /**
                    Returns an array with all of the items in the enumeration where the passed
                    function returns false for. This method is the inverse of filter().

                    The callback method you provide should have the following signature (all
                    parameters are optional):

                    ```javascript
                    function(item, index, enumerable);
                    ```

                    - *item* is the current item in the iteration.
                    - *index* is the current index in the iteration
                    - *enumerable* is the enumerable object itself.

                    It should return the a falsey value to include the item in the results.

                    Note that in addition to a callback, you can also pass an optional target
                    object that will be set as "this" on the context. This is a good way
                    to give your iterator function access to the current object.

                    @method reject
                    @param {Function} callback The callback to execute
                    @param {Object} [target] The target object to use
                    @return {Array} A rejected array.
                   */
            reject: function(callback, target) {
                return this.filter(function() {
                    return !(apply(target, callback, arguments));
                });
            },

            /**
                    Returns an array with just the items with the matched property. You
                    can pass an optional second argument with the target value. Otherwise
                    this will match any property that evaluates to `true`.

                    @method filterBy
                    @param {String} key the property to test
                    @param {*} [value] optional value to test against.
                    @return {Array} filtered array
                  */
            filterBy: function(key, value) {
                return this.filter(apply(this, iter, arguments));
            },

            /**
                    Returns an array with just the items with the matched property. You
                    can pass an optional second argument with the target value. Otherwise
                    this will match any property that evaluates to `true`.

                    @method filterProperty
                    @param {String} key the property to test
                    @param {String} [value] optional value to test against.
                    @return {Array} filtered array
                    @deprecated Use `filterBy` instead
                  */
            filterProperty: aliasMethod('filterBy'),

            /**
                    Returns an array with the items that do not have truthy values for
                    key.  You can pass an optional second argument with the target value.  Otherwise
                    this will match any property that evaluates to false.

                    @method rejectBy
                    @param {String} key the property to test
                    @param {String} [value] optional value to test against.
                    @return {Array} rejected array
                  */
            rejectBy: function(key, value) {
                var exactValue = function(item) {
                    return get(item, key) === value;
                },
                hasValue = function(item) {
                    return !!get(item, key);
                },
                use = (arguments.length === 2 ? exactValue : hasValue);

                return this.reject(use);
            },

            /**
                    Returns an array with the items that do not have truthy values for
                    key.  You can pass an optional second argument with the target value.  Otherwise
                    this will match any property that evaluates to false.

                    @method rejectProperty
                    @param {String} key the property to test
                    @param {String} [value] optional value to test against.
                    @return {Array} rejected array
                    @deprecated Use `rejectBy` instead
                  */
            rejectProperty: aliasMethod('rejectBy'),

            /**
                    Returns the first item in the array for which the callback returns true.
                    This method works similar to the `filter()` method defined in JavaScript 1.6
                    except that it will stop working on the array once a match is found.

                    The callback method you provide should have the following signature (all
                    parameters are optional):

                    ```javascript
                    function(item, index, enumerable);
                    ```

                    - `item` is the current item in the iteration.
                    - `index` is the current index in the iteration.
                    - `enumerable` is the enumerable object itself.

                    It should return the `true` to include the item in the results, `false`
                    otherwise.

                    Note that in addition to a callback, you can also pass an optional target
                    object that will be set as `this` on the context. This is a good way
                    to give your iterator function access to the current object.

                    @method find
                    @param {Function} callback The callback to execute
                    @param {Object} [target] The target object to use
                    @return {Object} Found item or `undefined`.
                  */
            find: function(callback, target) {
                var len = get(this, 'length') ;
                if (target === undefined) 
                    target = null;

                var last = null, next, found = false, ret ;
                var context = popCtx();
                for (var idx = 0; idx < len && !found; idx++) {
                    next = this.nextObject(idx, last, context) ;
                    if (found = callback.call(target, next, idx, this)) 
                        ret = next ;
                    last = next ;
                }
                next = last = null ;
                context = pushCtx(context);
                return ret ;
            },

            /**
                    Returns the first item with a property matching the passed value. You
                    can pass an optional second argument with the target value. Otherwise
                    this will match any property that evaluates to `true`.

                    This method works much like the more generic `find()` method.

                    @method findBy
                    @param {String} key the property to test
                    @param {String} [value] optional value to test against.
                    @return {Object} found item or `undefined`
                  */
            findBy: function(key, value) {
                return this.find(apply(this, iter, arguments));
            },

            /**
                    Returns the first item with a property matching the passed value. You
                    can pass an optional second argument with the target value. Otherwise
                    this will match any property that evaluates to `true`.

                    This method works much like the more generic `find()` method.

                    @method findProperty
                    @param {String} key the property to test
                    @param {String} [value] optional value to test against.
                    @return {Object} found item or `undefined`
                    @deprecated Use `findBy` instead
                  */
            findProperty: aliasMethod('findBy'),

            /**
                    Returns `true` if the passed function returns true for every item in the
                    enumeration. This corresponds with the `every()` method in JavaScript 1.6.

                    The callback method you provide should have the following signature (all
                    parameters are optional):

                    ```javascript
                    function(item, index, enumerable);
                    ```

                    - `item` is the current item in the iteration.
                    - `index` is the current index in the iteration.
                    - `enumerable` is the enumerable object itself.

                    It should return the `true` or `false`.

                    Note that in addition to a callback, you can also pass an optional target
                    object that will be set as `this` on the context. This is a good way
                    to give your iterator function access to the current object.

                    Example Usage:

                    ```javascript
                    if (people.every(isEngineer)) { Paychecks.addBigBonus(); }
                    ```

                    @method every
                    @param {Function} callback The callback to execute
                    @param {Object} [target] The target object to use
                    @return {Boolean}
                  */
            every: function(callback, target) {
                return !this.find(function(x, idx, i) {
                    return !callback.call(target, x, idx, i);
                });
            },

            /**
                    @method everyBy
                    @param {String} key the property to test
                    @param {String} [value] optional value to test against.
                    @deprecated Use `isEvery` instead
                    @return {Boolean}
                  */
            everyBy: aliasMethod('isEvery'),

            /**
                    @method everyProperty
                    @param {String} key the property to test
                    @param {String} [value] optional value to test against.
                    @deprecated Use `isEvery` instead
                    @return {Boolean}
                  */
            everyProperty: aliasMethod('isEvery'),

            /**
                    Returns `true` if the passed property resolves to `true` for all items in
                    the enumerable. This method is often simpler/faster than using a callback.

                    @method isEvery
                    @param {String} key the property to test
                    @param {String} [value] optional value to test against.
                    @return {Boolean}
                    @since 1.3.0
                  */
            isEvery: function(key, value) {
                return this.every(apply(this, iter, arguments));
            },

            /**
                    Returns `true` if the passed function returns true for any item in the
                    enumeration. This corresponds with the `some()` method in JavaScript 1.6.

                    The callback method you provide should have the following signature (all
                    parameters are optional):

                    ```javascript
                    function(item, index, enumerable);
                    ```

                    - `item` is the current item in the iteration.
                    - `index` is the current index in the iteration.
                    - `enumerable` is the enumerable object itself.

                    It should return the `true` to include the item in the results, `false`
                    otherwise.

                    Note that in addition to a callback, you can also pass an optional target
                    object that will be set as `this` on the context. This is a good way
                    to give your iterator function access to the current object.

                    Usage Example:

                    ```javascript
                    if (people.any(isManager)) { Paychecks.addBiggerBonus(); }
                    ```

                    @method any
                    @param {Function} callback The callback to execute
                    @param {Object} [target] The target object to use
                    @return {Boolean} `true` if the passed function returns `true` for any item
                  */
            any: function(callback, target) {
                var len = get(this, 'length'),
                context = popCtx(),
                found = false,
                last = null,
                next, idx;

                if (target === undefined) {
                    target = null;
                }

                for (idx = 0; idx < len && !found; idx++) {
                    next = this.nextObject(idx, last, context);
                    found = callback.call(target, next, idx, this);
                    last = next;
                }

                next = last = null;
                context = pushCtx(context);
                return found;
            },

            /**
                    Returns `true` if the passed function returns true for any item in the
                    enumeration. This corresponds with the `some()` method in JavaScript 1.6.

                    The callback method you provide should have the following signature (all
                    parameters are optional):

                    ```javascript
                    function(item, index, enumerable);
                    ```

                    - `item` is the current item in the iteration.
                    - `index` is the current index in the iteration.
                    - `enumerable` is the enumerable object itself.

                    It should return the `true` to include the item in the results, `false`
                    otherwise.

                    Note that in addition to a callback, you can also pass an optional target
                    object that will be set as `this` on the context. This is a good way
                    to give your iterator function access to the current object.

                    Usage Example:

                    ```javascript
                    if (people.some(isManager)) { Paychecks.addBiggerBonus(); }
                    ```

                    @method some
                    @param {Function} callback The callback to execute
                    @param {Object} [target] The target object to use
                    @return {Boolean} `true` if the passed function returns `true` for any item
                    @deprecated Use `any` instead
                  */
            some: aliasMethod('any'),

            /**
                    Returns `true` if the passed property resolves to `true` for any item in
                    the enumerable. This method is often simpler/faster than using a callback.

                    @method isAny
                    @param {String} key the property to test
                    @param {String} [value] optional value to test against.
                    @return {Boolean} `true` if the passed function returns `true` for any item
                    @since 1.3.0
                  */
            isAny: function(key, value) {
                return this.any(apply(this, iter, arguments));
            },

            /**
                    @method anyBy
                    @param {String} key the property to test
                    @param {String} [value] optional value to test against.
                    @return {Boolean} `true` if the passed function returns `true` for any item
                    @deprecated Use `isAny` instead
                  */
            anyBy: aliasMethod('isAny'),

            /**
                    @method someProperty
                    @param {String} key the property to test
                    @param {String} [value] optional value to test against.
                    @return {Boolean} `true` if the passed function returns `true` for any item
                    @deprecated Use `isAny` instead
                  */
            someProperty: aliasMethod('isAny'),

            /**
                    This will combine the values of the enumerator into a single value. It
                    is a useful way to collect a summary value from an enumeration. This
                    corresponds to the `reduce()` method defined in JavaScript 1.8.

                    The callback method you provide should have the following signature (all
                    parameters are optional):

                    ```javascript
                    function(previousValue, item, index, enumerable);
                    ```

                    - `previousValue` is the value returned by the last call to the iterator.
                    - `item` is the current item in the iteration.
                    - `index` is the current index in the iteration.
                    - `enumerable` is the enumerable object itself.

                    Return the new cumulative value.

                    In addition to the callback you can also pass an `initialValue`. An error
                    will be raised if you do not pass an initial value and the enumerator is
                    empty.

                    Note that unlike the other methods, this method does not allow you to
                    pass a target object to set as this for the callback. It's part of the
                    spec. Sorry.

                    @method reduce
                    @param {Function} callback The callback to execute
                    @param {Object} initialValue Initial value for the reduce
                    @param {String} reducerProperty internal use only.
                    @return {Object} The reduced value.
                  */
            reduce: function(callback, initialValue, reducerProperty) {
                if (typeof callback !== "function") {
                    throw new TypeError();
                }

                var ret = initialValue;

                this.forEach(function(item, i) {
                    ret = callback(ret, item, i, this, reducerProperty);
                }, this);

                return ret;
            },

            /**
                    Invokes the named method on every object in the receiver that
                    implements it. This method corresponds to the implementation in
                    Prototype 1.6.

                    @method invoke
                    @param {String} methodName the name of the method
                    @param {Object...} args optional arguments to pass as well.
                    @return {Array} return values from calling invoke.
                  */
            invoke: function(methodName) {
                var args, ret = Ember.A();
                if (arguments.length > 1) 
                    args = a_slice.call(arguments, 1);

                this.forEach(function(x, idx) {
                    var method = x && x[methodName];
                    if ('function' === typeof method) {
                        ret[idx] = args ? apply(x, method, args) : x[methodName]();
                    }
                }, this);

                return ret;
            },

            /**
                    Simply converts the enumerable into a genuine array. The order is not
                    guaranteed. Corresponds to the method implemented by Prototype.

                    @method toArray
                    @return {Array} the enumerable as an array.
                  */
            toArray: function() {
                var ret = Ember.A();
                this.forEach(function(o, idx) {
                    ret[idx] = o;
                });
                return ret;
            },

            /**
                    Returns a copy of the array with all null and undefined elements removed.

                    ```javascript
                    var arr = ["a", null, "c", undefined];
                    arr.compact();  // ["a", "c"]
                    ```

                    @method compact
                    @return {Array} the array without null and undefined elements.
                  */
            compact: function() {
                return this.filter(function(value) {
                    return value != null;
                });
            },

            /**
                    Returns a new enumerable that excludes the passed value. The default
                    implementation returns an array regardless of the receiver type unless
                    the receiver does not contain the value.

                    ```javascript
                    var arr = ["a", "b", "a", "c"];
                    arr.without("a");  // ["b", "c"]
                    ```

                    @method without
                    @param {Object} value
                    @return {Ember.Enumerable}
                  */
            without: function(value) {
                if (!this.contains(value)) 
                    return this; // nothing to do
                var ret = Ember.A();
                this.forEach(function(k) {
                    if (k !== value) 
                        ret[ret.length] = k;
                }) ;
                return ret ;
            },

            /**
                    Returns a new enumerable that contains only unique values. The default
                    implementation returns an array regardless of the receiver type.

                    ```javascript
                    var arr = ["a", "a", "b", "b"];
                    arr.uniq();  // ["a", "b"]
                    ```

                    @method uniq
                    @return {Ember.Enumerable}
                  */
            uniq: function() {
                var ret = Ember.A();
                this.forEach(function(k) {
                    if (indexOf(ret, k) < 0) 
                        ret.push(k);
                });
                return ret;
            },

            /**
                    This property will trigger anytime the enumerable's content changes.
                    You can observe this property to be notified of changes to the enumerables
                    content.

                    For plain enumerables, this property is read only. `Array` overrides
                    this method.

                    @property []
                    @type Array
                    @return this
                  */
            '[]': computed(function(key, value) {
                return this;
            }),

            // ..........................................................
            // ENUMERABLE OBSERVERS
            //

            /**
                    Registers an enumerable observer. Must implement `Ember.EnumerableObserver`
                    mixin.

                    @method addEnumerableObserver
                    @param {Object} target
                    @param {Hash} [opts]
                    @return this
                  */
            addEnumerableObserver: function(target, opts) {
                var willChange = (opts && opts.willChange) || 'enumerableWillChange',
                didChange = (opts && opts.didChange) || 'enumerableDidChange';

                var hasObservers = get(this, 'hasEnumerableObservers');
                if (!hasObservers) 
                    propertyWillChange(this, 'hasEnumerableObservers');
                addListener(this, '@enumerable:before', target, willChange);
                addListener(this, '@enumerable:change', target, didChange);
                if (!hasObservers) 
                    propertyDidChange(this, 'hasEnumerableObservers');
                return this;
            },

            /**
                    Removes a registered enumerable observer.

                    @method removeEnumerableObserver
                    @param {Object} target
                    @param {Hash} [opts]
                    @return this
                  */
            removeEnumerableObserver: function(target, opts) {
                var willChange = (opts && opts.willChange) || 'enumerableWillChange',
                didChange = (opts && opts.didChange) || 'enumerableDidChange';

                var hasObservers = get(this, 'hasEnumerableObservers');
                if (hasObservers) 
                    propertyWillChange(this, 'hasEnumerableObservers');
                removeListener(this, '@enumerable:before', target, willChange);
                removeListener(this, '@enumerable:change', target, didChange);
                if (hasObservers) 
                    propertyDidChange(this, 'hasEnumerableObservers');
                return this;
            },

            /**
                    Becomes true whenever the array currently has observers watching changes
                    on the array.

                    @property hasEnumerableObservers
                    @type Boolean
                  */
            hasEnumerableObservers: computed(function() {
                return hasListeners(this, '@enumerable:change') || hasListeners(this, '@enumerable:before');
            }),


            /**
                    Invoke this method just before the contents of your enumerable will
                    change. You can either omit the parameters completely or pass the objects
                    to be removed or added if available or just a count.

                    @method enumerableContentWillChange
                    @param {Ember.Enumerable|Number} removing An enumerable of the objects to
                      be removed or the number of items to be removed.
                    @param {Ember.Enumerable|Number} adding An enumerable of the objects to be
                      added or the number of items to be added.
                    @chainable
                  */
            enumerableContentWillChange: function(removing, adding) {

                var removeCnt, addCnt, hasDelta;

                if ('number' === typeof removing) 
                    removeCnt = removing;
                else if (removing) 
                    removeCnt = get(removing, 'length');
                else 
                    removeCnt = removing = -1;

                if ('number' === typeof adding) 
                    addCnt = adding;
                else if (adding) 
                    addCnt = get(adding, 'length');
                else 
                    addCnt = adding = -1;

                hasDelta = addCnt < 0 || removeCnt < 0 || addCnt - removeCnt !== 0;

                if (removing === -1) 
                    removing = null;
                if (adding === -1) 
                    adding = null;

                propertyWillChange(this, '[]');
                if (hasDelta) 
                    propertyWillChange(this, 'length');
                sendEvent(this, '@enumerable:before', [this, removing, adding]);

                return this;
            },

            /**
                    Invoke this method when the contents of your enumerable has changed.
                    This will notify any observers watching for content changes. If you are
                    implementing an ordered enumerable (such as an array), also pass the
                    start and end values where the content changed so that it can be used to
                    notify range observers.

                    @method enumerableContentDidChange
                    @param {Ember.Enumerable|Number} removing An enumerable of the objects to
                      be removed or the number of items to be removed.
                    @param {Ember.Enumerable|Number} adding  An enumerable of the objects to
                      be added or the number of items to be added.
                    @chainable
                  */
            enumerableContentDidChange: function(removing, adding) {
                var removeCnt, addCnt, hasDelta;

                if ('number' === typeof removing) 
                    removeCnt = removing;
                else if (removing) 
                    removeCnt = get(removing, 'length');
                else 
                    removeCnt = removing = -1;

                if ('number' === typeof adding) 
                    addCnt = adding;
                else if (adding) 
                    addCnt = get(adding, 'length');
                else 
                    addCnt = adding = -1;

                hasDelta = addCnt < 0 || removeCnt < 0 || addCnt - removeCnt !== 0;

                if (removing === -1) 
                    removing = null;
                if (adding === -1) 
                    adding = null;

                sendEvent(this, '@enumerable:change', [this, removing, adding]);
                if (hasDelta) 
                    propertyDidChange(this, 'length');
                propertyDidChange(this, '[]');

                return this ;
            },

            /**
                    Converts the enumerable into an array and sorts by the keys
                    specified in the argument.

                    You may provide multiple arguments to sort by multiple properties.

                    @method sortBy
                    @param {String} property name(s) to sort on
                    @return {Array} The sorted array.
                    @since 1.2.0
                    */
            sortBy: function() {
                var sortKeys = arguments;
                return this.toArray().sort(function(a, b) {
                    for (var i = 0; i < sortKeys.length; i++) {
                        var key = sortKeys[i],
                        propA = get(a, key),
                        propB = get(b, key);
                        // return 1 or -1 else continue to the next sortKey
                        var compareValue = compare(propA, propB);
                        if (compareValue) {
                            return compareValue;
                        }
                    }
                    return 0;
                });
            }
        });
    });
    define("ember-runtime/mixins/evented",
    ["ember-metal/mixin", "ember-metal/events", "exports"],
    function(__dependency1__, __dependency2__, __exports__) {
        "use strict";
        var Mixin = __dependency1__.Mixin;
        var addListener = __dependency2__.addListener;
        var removeListener = __dependency2__.removeListener;
        var hasListeners = __dependency2__.hasListeners;
        var sendEvent = __dependency2__.sendEvent;

        /**
            @module ember
            @submodule ember-runtime
            */

        /**
              This mixin allows for Ember objects to subscribe to and emit events.

              ```javascript
              App.Person = Ember.Object.extend(Ember.Evented, {
                greet: function() {
                  // ...
                  this.trigger('greet');
                }
              });

              var person = App.Person.create();

              person.on('greet', function() {
                console.log('Our person has greeted');
              });

              person.greet();

              // outputs: 'Our person has greeted'
              ```

              You can also chain multiple event subscriptions:

              ```javascript
              person.on('greet', function() {
                console.log('Our person has greeted');
              }).one('greet', function() {
                console.log('Offer one-time special');
              }).off('event', this, forgetThis);
              ```

              @class Evented
              @namespace Ember
             */
        __exports__["default"] = Mixin.create({

            /**
                   Subscribes to a named event with given function.

                   ```javascript
                   person.on('didLoad', function() {
                     // fired once the person has loaded
                   });
                   ```

                   An optional target can be passed in as the 2nd argument that will
                   be set as the "this" for the callback. This is a good way to give your
                   function access to the object triggering the event. When the target
                   parameter is used the callback becomes the third argument.

                   @method on
                   @param {String} name The name of the event
                   @param {Object} [target] The "this" binding for the callback
                   @param {Function} method The callback to execute
                   @return this
                  */
            on: function(name, target, method) {
                addListener(this, name, target, method);
                return this;
            },

            /**
                    Subscribes a function to a named event and then cancels the subscription
                    after the first time the event is triggered. It is good to use ``one`` when
                    you only care about the first time an event has taken place.

                    This function takes an optional 2nd argument that will become the "this"
                    value for the callback. If this argument is passed then the 3rd argument
                    becomes the function.

                    @method one
                    @param {String} name The name of the event
                    @param {Object} [target] The "this" binding for the callback
                    @param {Function} method The callback to execute
                    @return this
                  */
            one: function(name, target, method) {
                if (!method) {
                    method = target;
                    target = null;
                }

                addListener(this, name, target, method, true);
                return this;
            },

            /**
                    Triggers a named event for the object. Any additional arguments
                    will be passed as parameters to the functions that are subscribed to the
                    event.

                    ```javascript
                    person.on('didEat', function(food) {
                      console.log('person ate some ' + food);
                    });

                    person.trigger('didEat', 'broccoli');

                    // outputs: person ate some broccoli
                    ```
                    @method trigger
                    @param {String} name The name of the event
                    @param {Object...} args Optional arguments to pass on
                  */
            trigger: function(name) {
                var length = arguments.length;
                var args = new Array(length - 1);

                for (var i = 1; i < length; i++) {
                    args[i - 1] = arguments[i];
                }

                sendEvent(this, name, args);
            },

            /**
                    Cancels subscription for given name, target, and method.

                    @method off
                    @param {String} name The name of the event
                    @param {Object} target The target of the subscription
                    @param {Function} method The function of the subscription
                    @return this
                  */
            off: function(name, target, method) {
                removeListener(this, name, target, method);
                return this;
            },

            /**
                    Checks to see if object has any subscriptions for named event.

                    @method has
                    @param {String} name The name of the event
                    @return {Boolean} does the object have a subscription for event
                   */
            has: function(name) {
                return hasListeners(this, name);
            }
        });
    });
    define("ember-runtime/mixins/freezable",
    ["ember-metal/mixin", "ember-metal/property_get", "ember-metal/property_set", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-runtime
            */

        var Mixin = __dependency1__.Mixin;
        var get = __dependency2__.get;
        var set = __dependency3__.set;

        /**
              The `Ember.Freezable` mixin implements some basic methods for marking an
              object as frozen. Once an object is frozen it should be read only. No changes
              may be made the internal state of the object.

              ## Enforcement

              To fully support freezing in your subclass, you must include this mixin and
              override any method that might alter any property on the object to instead
              raise an exception. You can check the state of an object by checking the
              `isFrozen` property.

              Although future versions of JavaScript may support language-level freezing
              object objects, that is not the case today. Even if an object is freezable,
              it is still technically possible to modify the object, even though it could
              break other parts of your application that do not expect a frozen object to
              change. It is, therefore, very important that you always respect the
              `isFrozen` property on all freezable objects.

              ## Example Usage

              The example below shows a simple object that implement the `Ember.Freezable`
              protocol.

              ```javascript
              Contact = Ember.Object.extend(Ember.Freezable, {
                firstName: null,
                lastName: null,

                // swaps the names
                swapNames: function() {
                  if (this.get('isFrozen')) throw Ember.FROZEN_ERROR;
                  var tmp = this.get('firstName');
                  this.set('firstName', this.get('lastName'));
                  this.set('lastName', tmp);
                  return this;
                }

              });

              c = Contact.create({ firstName: "John", lastName: "Doe" });
              c.swapNames();  // returns c
              c.freeze();
              c.swapNames();  // EXCEPTION
              ```

              ## Copying

              Usually the `Ember.Freezable` protocol is implemented in cooperation with the
              `Ember.Copyable` protocol, which defines a `frozenCopy()` method that will
              return a frozen object, if the object implements this method as well.

              @class Freezable
              @namespace Ember
              @since Ember 0.9
            */
        var Freezable = Mixin.create({

            /**
                    Set to `true` when the object is frozen. Use this property to detect
                    whether your object is frozen or not.

                    @property isFrozen
                    @type Boolean
                  */
            isFrozen: false,

            /**
                    Freezes the object. Once this method has been called the object should
                    no longer allow any properties to be edited.

                    @method freeze
                    @return {Object} receiver
                  */
            freeze: function() {
                if (get(this, 'isFrozen')) 
                    return this;
                set(this, 'isFrozen', true);
                return this;
            }

        });
        __exports__.Freezable = Freezable;
        var FROZEN_ERROR = "Frozen object cannot be modified.";
        __exports__.FROZEN_ERROR = FROZEN_ERROR;
    });
    define("ember-runtime/mixins/mutable_array",
    ["ember-metal/property_get", "ember-metal/property_set", "ember-metal/utils", "ember-metal/error", "ember-metal/mixin", "ember-runtime/mixins/array", "ember-runtime/mixins/mutable_enumerable", "ember-runtime/mixins/enumerable", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-runtime
            */


        // require('ember-runtime/mixins/array');
        // require('ember-runtime/mixins/mutable_enumerable');

        // ..........................................................
        // CONSTANTS
        //

        var OUT_OF_RANGE_EXCEPTION = "Index out of range";
        var EMPTY = [];

        // ..........................................................
        // HELPERS
        //

        var get = __dependency1__.get;
        var set = __dependency2__.set;
        var isArray = __dependency3__.isArray;
        var EmberError = __dependency4__["default"];
        var Mixin = __dependency5__.Mixin;
        var required = __dependency5__.required;
        var EmberArray = __dependency6__["default"];
        var MutableEnumerable = __dependency7__["default"];
        var Enumerable = __dependency8__["default"];
        /**
              This mixin defines the API for modifying array-like objects. These methods
              can be applied only to a collection that keeps its items in an ordered set.
              It builds upon the Array mixin and adds methods to modify the array.
              Concrete implementations of this class include ArrayProxy and ArrayController.

              It is important to use the methods in this class to modify arrays so that
              changes are observable. This allows the binding system in Ember to function
              correctly.


              Note that an Array can change even if it does not implement this mixin.
              For example, one might implement a SparseArray that cannot be directly
              modified, but if its underlying enumerable changes, it will change also.

              @class MutableArray
              @namespace Ember
              @uses Ember.Array
              @uses Ember.MutableEnumerable
            */
        __exports__["default"] = Mixin.create(EmberArray, MutableEnumerable, {

            /**
                    __Required.__ You must implement this method to apply this mixin.

                    This is one of the primitives you must implement to support `Ember.Array`.
                    You should replace amt objects started at idx with the objects in the
                    passed array. You should also call `this.enumerableContentDidChange()`

                    @method replace
                    @param {Number} idx Starting index in the array to replace. If
                      idx >= length, then append to the end of the array.
                    @param {Number} amt Number of elements that should be removed from
                      the array, starting at *idx*.
                    @param {Array} objects An array of zero or more objects that should be
                      inserted into the array at *idx*
                  */
            replace: required(),

            /**
                    Remove all elements from the array. This is useful if you
                    want to reuse an existing array without having to recreate it.

                    ```javascript
                    var colors = ["red", "green", "blue"];
                    color.length();   //  3
                    colors.clear();   //  []
                    colors.length();  //  0
                    ```

                    @method clear
                    @return {Ember.Array} An empty Array.
                  */
            clear: function () {
                var len = get(this, 'length');
                if (len === 0) 
                    return this;
                this.replace(0, len, EMPTY);
                return this;
            },

            /**
                    This will use the primitive `replace()` method to insert an object at the
                    specified index.

                    ```javascript
                    var colors = ["red", "green", "blue"];
                    colors.insertAt(2, "yellow");  // ["red", "green", "yellow", "blue"]
                    colors.insertAt(5, "orange");  // Error: Index out of range
                    ```

                    @method insertAt
                    @param {Number} idx index of insert the object at.
                    @param {Object} object object to insert
                    @return {Ember.Array} receiver
                  */
            insertAt: function(idx, object) {
                if (idx > get(this, 'length')) 
                    throw new EmberError(OUT_OF_RANGE_EXCEPTION);
                this.replace(idx, 0, [object]);
                return this;
            },

            /**
                    Remove an object at the specified index using the `replace()` primitive
                    method. You can pass either a single index, or a start and a length.

                    If you pass a start and length that is beyond the
                    length this method will throw an `OUT_OF_RANGE_EXCEPTION`.

                    ```javascript
                    var colors = ["red", "green", "blue", "yellow", "orange"];
                    colors.removeAt(0);     // ["green", "blue", "yellow", "orange"]
                    colors.removeAt(2, 2);  // ["green", "blue"]
                    colors.removeAt(4, 2);  // Error: Index out of range
                    ```

                    @method removeAt
                    @param {Number} start index, start of range
                    @param {Number} len length of passing range
                    @return {Ember.Array} receiver
                  */
            removeAt: function(start, len) {
                if ('number' === typeof start) {

                    if ((start < 0) || (start >= get(this, 'length'))) {
                        throw new EmberError(OUT_OF_RANGE_EXCEPTION);
                    }

                    // fast case
                    if (len === undefined) 
                        len = 1;
                    this.replace(start, len, EMPTY);
                }

                return this;
            },

            /**
                    Push the object onto the end of the array. Works just like `push()` but it
                    is KVO-compliant.

                    ```javascript
                    var colors = ["red", "green"];
                    colors.pushObject("black");     // ["red", "green", "black"]
                    colors.pushObject(["yellow"]);  // ["red", "green", ["yellow"]]
                    ```

                    @method pushObject
                    @param {*} obj object to push
                    @return object same object passed as a param
                  */
            pushObject: function(obj) {
                this.insertAt(get(this, 'length'), obj);
                return obj;
            },

            /**
                    Add the objects in the passed numerable to the end of the array. Defers
                    notifying observers of the change until all objects are added.

                    ```javascript
                    var colors = ["red"];
                    colors.pushObjects(["yellow", "orange"]);  // ["red", "yellow", "orange"]
                    ```

                    @method pushObjects
                    @param {Ember.Enumerable} objects the objects to add
                    @return {Ember.Array} receiver
                  */
            pushObjects: function(objects) {
                if (!(Enumerable.detect(objects) || isArray(objects))) {
                    throw new TypeError("Must pass Ember.Enumerable to Ember.MutableArray#pushObjects");
                }
                this.replace(get(this, 'length'), 0, objects);
                return this;
            },

            /**
                    Pop object from array or nil if none are left. Works just like `pop()` but
                    it is KVO-compliant.

                    ```javascript
                    var colors = ["red", "green", "blue"];
                    colors.popObject();   // "blue"
                    console.log(colors);  // ["red", "green"]
                    ```

                    @method popObject
                    @return object
                  */
            popObject: function() {
                var len = get(this, 'length');
                if (len === 0) 
                    return null;

                var ret = this.objectAt(len-1);
                this.removeAt(len-1, 1);
                return ret;
            },

            /**
                    Shift an object from start of array or nil if none are left. Works just
                    like `shift()` but it is KVO-compliant.

                    ```javascript
                    var colors = ["red", "green", "blue"];
                    colors.shiftObject();  // "red"
                    console.log(colors);   // ["green", "blue"]
                    ```

                    @method shiftObject
                    @return object
                  */
            shiftObject: function() {
                if (get(this, 'length') === 0) 
                    return null;
                var ret = this.objectAt(0);
                this.removeAt(0);
                return ret;
            },

            /**
                    Unshift an object to start of array. Works just like `unshift()` but it is
                    KVO-compliant.

                    ```javascript
                    var colors = ["red"];
                    colors.unshiftObject("yellow");    // ["yellow", "red"]
                    colors.unshiftObject(["black"]);   // [["black"], "yellow", "red"]
                    ```

                    @method unshiftObject
                    @param {*} obj object to unshift
                    @return object same object passed as a param
                  */
            unshiftObject: function(obj) {
                this.insertAt(0, obj);
                return obj;
            },

            /**
                    Adds the named objects to the beginning of the array. Defers notifying
                    observers until all objects have been added.

                    ```javascript
                    var colors = ["red"];
                    colors.unshiftObjects(["black", "white"]);   // ["black", "white", "red"]
                    colors.unshiftObjects("yellow"); // Type Error: 'undefined' is not a function
                    ```

                    @method unshiftObjects
                    @param {Ember.Enumerable} objects the objects to add
                    @return {Ember.Array} receiver
                  */
            unshiftObjects: function(objects) {
                this.replace(0, 0, objects);
                return this;
            },

            /**
                    Reverse objects in the array. Works just like `reverse()` but it is
                    KVO-compliant.

                    @method reverseObjects
                    @return {Ember.Array} receiver
                   */
            reverseObjects: function() {
                var len = get(this, 'length');
                if (len === 0) 
                    return this;
                var objects = this.toArray().reverse();
                this.replace(0, len, objects);
                return this;
            },

            /**
                    Replace all the the receiver's content with content of the argument.
                    If argument is an empty array receiver will be cleared.

                    ```javascript
                    var colors = ["red", "green", "blue"];
                    colors.setObjects(["black", "white"]);  // ["black", "white"]
                    colors.setObjects([]);                  // []
                    ```

                    @method setObjects
                    @param {Ember.Array} objects array whose content will be used for replacing
                        the content of the receiver
                    @return {Ember.Array} receiver with the new content
                   */
            setObjects: function(objects) {
                if (objects.length === 0) 
                    return this.clear();

                var len = get(this, 'length');
                this.replace(0, len, objects);
                return this;
            },

            // ..........................................................
            // IMPLEMENT Ember.MutableEnumerable
            //

            /**
                    Remove all occurances of an object in the array.

                    ```javascript
                    var cities = ["Chicago", "Berlin", "Lima", "Chicago"];
                    cities.removeObject("Chicago");  // ["Berlin", "Lima"]
                    cities.removeObject("Lima");     // ["Berlin"]
                    cities.removeObject("Tokyo")     // ["Berlin"]
                    ```

                    @method removeObject
                    @param {*} obj object to remove
                    @return {Ember.Array} receiver
                  */
            removeObject: function(obj) {
                var loc = get(this, 'length') || 0;
                while (--loc >= 0) {
                    var curObject = this.objectAt(loc);
                    if (curObject === obj) 
                        this.removeAt(loc);
                }
                return this;
            },

            /**
                    Push the object onto the end of the array if it is not already
                    present in the array.

                    ```javascript
                    var cities = ["Chicago", "Berlin"];
                    cities.addObject("Lima");    // ["Chicago", "Berlin", "Lima"]
                    cities.addObject("Berlin");  // ["Chicago", "Berlin", "Lima"]
                    ```

                    @method addObject
                    @param {*} obj object to add, if not already present
                    @return {Ember.Array} receiver
                  */
            addObject: function(obj) {
                if (!this.contains(obj)) 
                    this.pushObject(obj);
                return this;
            }

        });
    });
    define("ember-runtime/mixins/mutable_enumerable",
    ["ember-metal/enumerable_utils", "ember-runtime/mixins/enumerable", "ember-metal/mixin", "ember-metal/property_events", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
        "use strict";
        var forEach = __dependency1__.forEach;
        var Enumerable = __dependency2__["default"];
        var Mixin = __dependency3__.Mixin;
        var required = __dependency3__.required;
        var beginPropertyChanges = __dependency4__.beginPropertyChanges;
        var endPropertyChanges = __dependency4__.endPropertyChanges;

        /**
            @module ember
            @submodule ember-runtime
            */

        /**
              This mixin defines the API for modifying generic enumerables. These methods
              can be applied to an object regardless of whether it is ordered or
              unordered.

              Note that an Enumerable can change even if it does not implement this mixin.
              For example, a MappedEnumerable cannot be directly modified but if its
              underlying enumerable changes, it will change also.

              ## Adding Objects

              To add an object to an enumerable, use the `addObject()` method. This
              method will only add the object to the enumerable if the object is not
              already present and is of a type supported by the enumerable.

              ```javascript
              set.addObject(contact);
              ```

              ## Removing Objects

              To remove an object from an enumerable, use the `removeObject()` method. This
              will only remove the object if it is present in the enumerable, otherwise
              this method has no effect.

              ```javascript
              set.removeObject(contact);
              ```

              ## Implementing In Your Own Code

              If you are implementing an object and want to support this API, just include
              this mixin in your class and implement the required methods. In your unit
              tests, be sure to apply the Ember.MutableEnumerableTests to your object.

              @class MutableEnumerable
              @namespace Ember
              @uses Ember.Enumerable
            */
        __exports__["default"] = Mixin.create(Enumerable, {

            /**
                    __Required.__ You must implement this method to apply this mixin.

                    Attempts to add the passed object to the receiver if the object is not
                    already present in the collection. If the object is present, this method
                    has no effect.

                    If the passed object is of a type not supported by the receiver,
                    then this method should raise an exception.

                    @method addObject
                    @param {Object} object The object to add to the enumerable.
                    @return {Object} the passed object
                  */
            addObject: required(Function),

            /**
                    Adds each object in the passed enumerable to the receiver.

                    @method addObjects
                    @param {Ember.Enumerable} objects the objects to add.
                    @return {Object} receiver
                  */
            addObjects: function(objects) {
                beginPropertyChanges(this);
                forEach(objects, function(obj) {
                    this.addObject(obj);
                }, this);
                endPropertyChanges(this);
                return this;
            },

            /**
                    __Required.__ You must implement this method to apply this mixin.

                    Attempts to remove the passed object from the receiver collection if the
                    object is present in the collection. If the object is not present,
                    this method has no effect.

                    If the passed object is of a type not supported by the receiver,
                    then this method should raise an exception.

                    @method removeObject
                    @param {Object} object The object to remove from the enumerable.
                    @return {Object} the passed object
                  */
            removeObject: required(Function),


            /**
                    Removes each object in the passed enumerable from the receiver.

                    @method removeObjects
                    @param {Ember.Enumerable} objects the objects to remove
                    @return {Object} receiver
                  */
            removeObjects: function(objects) {
                beginPropertyChanges(this);
                for (var i = objects.length - 1; i >= 0; i--) {
                    this.removeObject(objects[i]);
                }
                endPropertyChanges(this);
                return this;
            }
        });
    });
    define("ember-runtime/mixins/observable",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/utils", "ember-metal/get_properties", "ember-metal/set_properties", "ember-metal/mixin", "ember-metal/events", "ember-metal/property_events", "ember-metal/observer", "ember-metal/computed", "ember-metal/is_none", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-runtime
            */
        var Ember = __dependency1__["default"];
        // Ember.assert

        var get = __dependency2__.get;
        var getWithDefault = __dependency2__.getWithDefault;
        var set = __dependency3__.set;
        var apply = __dependency4__.apply;
        var getProperties = __dependency5__["default"];
        var setProperties = __dependency6__["default"];
        var Mixin = __dependency7__.Mixin;
        var hasListeners = __dependency8__.hasListeners;
        var beginPropertyChanges = __dependency9__.beginPropertyChanges;
        var propertyWillChange = __dependency9__.propertyWillChange;
        var propertyDidChange = __dependency9__.propertyDidChange;
        var endPropertyChanges = __dependency9__.endPropertyChanges;
        var addObserver = __dependency10__.addObserver;
        var addBeforeObserver = __dependency10__.addBeforeObserver;
        var removeObserver = __dependency10__.removeObserver;
        var observersFor = __dependency10__.observersFor;
        var cacheFor = __dependency11__.cacheFor;
        var isNone = __dependency12__.isNone;


        var slice = Array.prototype.slice;
        /**
              ## Overview

              This mixin provides properties and property observing functionality, core
              features of the Ember object model.

              Properties and observers allow one object to observe changes to a
              property on another object. This is one of the fundamental ways that
              models, controllers and views communicate with each other in an Ember
              application.

              Any object that has this mixin applied can be used in observer
              operations. That includes `Ember.Object` and most objects you will
              interact with as you write your Ember application.

              Note that you will not generally apply this mixin to classes yourself,
              but you will use the features provided by this module frequently, so it
              is important to understand how to use it.

              ## Using `get()` and `set()`

              Because of Ember's support for bindings and observers, you will always
              access properties using the get method, and set properties using the
              set method. This allows the observing objects to be notified and
              computed properties to be handled properly.

              More documentation about `get` and `set` are below.

              ## Observing Property Changes

              You typically observe property changes simply by adding the `observes`
              call to the end of your method declarations in classes that you write.
              For example:

              ```javascript
              Ember.Object.extend({
                valueObserver: function() {
                  // Executes whenever the "value" property changes
                }.observes('value')
              });
              ```

              Although this is the most common way to add an observer, this capability
              is actually built into the `Ember.Object` class on top of two methods
              defined in this mixin: `addObserver` and `removeObserver`. You can use
              these two methods to add and remove observers yourself if you need to
              do so at runtime.

              To add an observer for a property, call:

              ```javascript
              object.addObserver('propertyKey', targetObject, targetAction)
              ```

              This will call the `targetAction` method on the `targetObject` whenever
              the value of the `propertyKey` changes.

              Note that if `propertyKey` is a computed property, the observer will be
              called when any of the property dependencies are changed, even if the
              resulting value of the computed property is unchanged. This is necessary
              because computed properties are not computed until `get` is called.

              @class Observable
              @namespace Ember
            */
        __exports__["default"] = Mixin.create({

            /**
                    Retrieves the value of a property from the object.

                    This method is usually similar to using `object[keyName]` or `object.keyName`,
                    however it supports both computed properties and the unknownProperty
                    handler.

                    Because `get` unifies the syntax for accessing all these kinds
                    of properties, it can make many refactorings easier, such as replacing a
                    simple property with a computed property, or vice versa.

                    ### Computed Properties

                    Computed properties are methods defined with the `property` modifier
                    declared at the end, such as:

                    ```javascript
                    fullName: function() {
                      return this.get('firstName') + ' ' + this.get('lastName');
                    }.property('firstName', 'lastName')
                    ```

                    When you call `get` on a computed property, the function will be
                    called and the return value will be returned instead of the function
                    itself.

                    ### Unknown Properties

                    Likewise, if you try to call `get` on a property whose value is
                    `undefined`, the `unknownProperty()` method will be called on the object.
                    If this method returns any value other than `undefined`, it will be returned
                    instead. This allows you to implement "virtual" properties that are
                    not defined upfront.

                    @method get
                    @param {String} keyName The property to retrieve
                    @return {Object} The property value or undefined.
                  */
            get: function(keyName) {
                return get(this, keyName);
            },

            /**
                    To get multiple properties at once, call `getProperties`
                    with a list of strings or an array:

                    ```javascript
                    record.getProperties('firstName', 'lastName', 'zipCode');
                    // { firstName: 'John', lastName: 'Doe', zipCode: '10011' }
                    ```

                    is equivalent to:

                    ```javascript
                    record.getProperties(['firstName', 'lastName', 'zipCode']);
                    // { firstName: 'John', lastName: 'Doe', zipCode: '10011' }
                    ```

                    @method getProperties
                    @param {String...|Array} list of keys to get
                    @return {Hash}
                  */
            getProperties: function() {
                return apply(null, getProperties, [this].concat(slice.call(arguments)));
            },

            /**
                    Sets the provided key or path to the value.

                    This method is generally very similar to calling `object[key] = value` or
                    `object.key = value`, except that it provides support for computed
                    properties, the `setUnknownProperty()` method and property observers.

                    ### Computed Properties

                    If you try to set a value on a key that has a computed property handler
                    defined (see the `get()` method for an example), then `set()` will call
                    that method, passing both the value and key instead of simply changing
                    the value itself. This is useful for those times when you need to
                    implement a property that is composed of one or more member
                    properties.

                    ### Unknown Properties

                    If you try to set a value on a key that is undefined in the target
                    object, then the `setUnknownProperty()` handler will be called instead. This
                    gives you an opportunity to implement complex "virtual" properties that
                    are not predefined on the object. If `setUnknownProperty()` returns
                    undefined, then `set()` will simply set the value on the object.

                    ### Property Observers

                    In addition to changing the property, `set()` will also register a property
                    change with the object. Unless you have placed this call inside of a
                    `beginPropertyChanges()` and `endPropertyChanges(),` any "local" observers
                    (i.e. observer methods declared on the same object), will be called
                    immediately. Any "remote" observers (i.e. observer methods declared on
                    another object) will be placed in a queue and called at a later time in a
                    coalesced manner.

                    ### Chaining

                    In addition to property changes, `set()` returns the value of the object
                    itself so you can do chaining like this:

                    ```javascript
                    record.set('firstName', 'Charles').set('lastName', 'Jolley');
                    ```

                    @method set
                    @param {String} keyName The property to set
                    @param {Object} value The value to set or `null`.
                    @return {Ember.Observable}
                  */
            set: function(keyName, value) {
                set(this, keyName, value);
                return this;
            },


            /**
                    Sets a list of properties at once. These properties are set inside
                    a single `beginPropertyChanges` and `endPropertyChanges` batch, so
                    observers will be buffered.

                    ```javascript
                    record.setProperties({ firstName: 'Charles', lastName: 'Jolley' });
                    ```

                    @method setProperties
                    @param {Hash} hash the hash of keys and values to set
                    @return {Ember.Observable}
                  */
            setProperties: function(hash) {
                return setProperties(this, hash);
            },

            /**
                    Begins a grouping of property changes.

                    You can use this method to group property changes so that notifications
                    will not be sent until the changes are finished. If you plan to make a
                    large number of changes to an object at one time, you should call this
                    method at the beginning of the changes to begin deferring change
                    notifications. When you are done making changes, call
                    `endPropertyChanges()` to deliver the deferred change notifications and end
                    deferring.

                    @method beginPropertyChanges
                    @return {Ember.Observable}
                  */
            beginPropertyChanges: function() {
                beginPropertyChanges();
                return this;
            },

            /**
                    Ends a grouping of property changes.

                    You can use this method to group property changes so that notifications
                    will not be sent until the changes are finished. If you plan to make a
                    large number of changes to an object at one time, you should call
                    `beginPropertyChanges()` at the beginning of the changes to defer change
                    notifications. When you are done making changes, call this method to
                    deliver the deferred change notifications and end deferring.

                    @method endPropertyChanges
                    @return {Ember.Observable}
                  */
            endPropertyChanges: function() {
                endPropertyChanges();
                return this;
            },

            /**
                    Notify the observer system that a property is about to change.

                    Sometimes you need to change a value directly or indirectly without
                    actually calling `get()` or `set()` on it. In this case, you can use this
                    method and `propertyDidChange()` instead. Calling these two methods
                    together will notify all observers that the property has potentially
                    changed value.

                    Note that you must always call `propertyWillChange` and `propertyDidChange`
                    as a pair. If you do not, it may get the property change groups out of
                    order and cause notifications to be delivered more often than you would
                    like.

                    @method propertyWillChange
                    @param {String} keyName The property key that is about to change.
                    @return {Ember.Observable}
                  */
            propertyWillChange: function(keyName) {
                propertyWillChange(this, keyName);
                return this;
            },

            /**
                    Notify the observer system that a property has just changed.

                    Sometimes you need to change a value directly or indirectly without
                    actually calling `get()` or `set()` on it. In this case, you can use this
                    method and `propertyWillChange()` instead. Calling these two methods
                    together will notify all observers that the property has potentially
                    changed value.

                    Note that you must always call `propertyWillChange` and `propertyDidChange`
                    as a pair. If you do not, it may get the property change groups out of
                    order and cause notifications to be delivered more often than you would
                    like.

                    @method propertyDidChange
                    @param {String} keyName The property key that has just changed.
                    @return {Ember.Observable}
                  */
            propertyDidChange: function(keyName) {
                propertyDidChange(this, keyName);
                return this;
            },

            /**
                    Convenience method to call `propertyWillChange` and `propertyDidChange` in
                    succession.

                    @method notifyPropertyChange
                    @param {String} keyName The property key to be notified about.
                    @return {Ember.Observable}
                  */
            notifyPropertyChange: function(keyName) {
                this.propertyWillChange(keyName);
                this.propertyDidChange(keyName);
                return this;
            },

            addBeforeObserver: function(key, target, method) {
                addBeforeObserver(this, key, target, method);
            },

            /**
                    Adds an observer on a property.

                    This is the core method used to register an observer for a property.

                    Once you call this method, any time the key's value is set, your observer
                    will be notified. Note that the observers are triggered any time the
                    value is set, regardless of whether it has actually changed. Your
                    observer should be prepared to handle that.

                    You can also pass an optional context parameter to this method. The
                    context will be passed to your observer method whenever it is triggered.
                    Note that if you add the same target/method pair on a key multiple times
                    with different context parameters, your observer will only be called once
                    with the last context you passed.

                    ### Observer Methods

                    Observer methods you pass should generally have the following signature if
                    you do not pass a `context` parameter:

                    ```javascript
                    fooDidChange: function(sender, key, value, rev) { };
                    ```

                    The sender is the object that changed. The key is the property that
                    changes. The value property is currently reserved and unused. The rev
                    is the last property revision of the object when it changed, which you can
                    use to detect if the key value has really changed or not.

                    If you pass a `context` parameter, the context will be passed before the
                    revision like so:

                    ```javascript
                    fooDidChange: function(sender, key, value, context, rev) { };
                    ```

                    Usually you will not need the value, context or revision parameters at
                    the end. In this case, it is common to write observer methods that take
                    only a sender and key value as parameters or, if you aren't interested in
                    any of these values, to write an observer that has no parameters at all.

                    @method addObserver
                    @param {String} key The key to observer
                    @param {Object} target The target object to invoke
                    @param {String|Function} method The method to invoke.
                  */
            addObserver: function(key, target, method) {
                addObserver(this, key, target, method);
            },

            /**
                    Remove an observer you have previously registered on this object. Pass
                    the same key, target, and method you passed to `addObserver()` and your
                    target will no longer receive notifications.

                    @method removeObserver
                    @param {String} key The key to observer
                    @param {Object} target The target object to invoke
                    @param {String|Function} method The method to invoke.
                  */
            removeObserver: function(key, target, method) {
                removeObserver(this, key, target, method);
            },

            /**
                    Returns `true` if the object currently has observers registered for a
                    particular key. You can use this method to potentially defer performing
                    an expensive action until someone begins observing a particular property
                    on the object.

                    @method hasObserverFor
                    @param {String} key Key to check
                    @return {Boolean}
                  */
            hasObserverFor: function(key) {
                return hasListeners(this, key + ':change');
            },

            /**
                    Retrieves the value of a property, or a default value in the case that the
                    property returns `undefined`.

                    ```javascript
                    person.getWithDefault('lastName', 'Doe');
                    ```

                    @method getWithDefault
                    @param {String} keyName The name of the property to retrieve
                    @param {Object} defaultValue The value to return if the property value is undefined
                    @return {Object} The property value or the defaultValue.
                  */
            getWithDefault: function(keyName, defaultValue) {
                return getWithDefault(this, keyName, defaultValue);
            },

            /**
                    Set the value of a property to the current value plus some amount.

                    ```javascript
                    person.incrementProperty('age');
                    team.incrementProperty('score', 2);
                    ```

                    @method incrementProperty
                    @param {String} keyName The name of the property to increment
                    @param {Number} increment The amount to increment by. Defaults to 1
                    @return {Number} The new property value
                  */
            incrementProperty: function(keyName, increment) {
                if (isNone(increment)) {
                    increment = 1;
                }
                Ember.assert("Must pass a numeric value to incrementProperty", (!isNaN(parseFloat(increment)) && isFinite(increment)));
                set(this, keyName, (parseFloat(get(this, keyName)) || 0) + increment);
                return get(this, keyName);
            },

            /**
                    Set the value of a property to the current value minus some amount.

                    ```javascript
                    player.decrementProperty('lives');
                    orc.decrementProperty('health', 5);
                    ```

                    @method decrementProperty
                    @param {String} keyName The name of the property to decrement
                    @param {Number} decrement The amount to decrement by. Defaults to 1
                    @return {Number} The new property value
                  */
            decrementProperty: function(keyName, decrement) {
                if (isNone(decrement)) {
                    decrement = 1;
                }
                Ember.assert("Must pass a numeric value to decrementProperty", (!isNaN(parseFloat(decrement)) && isFinite(decrement)));
                set(this, keyName, (get(this, keyName) || 0) - decrement);
                return get(this, keyName);
            },

            /**
                    Set the value of a boolean property to the opposite of it's
                    current value.

                    ```javascript
                    starship.toggleProperty('warpDriveEngaged');
                    ```

                    @method toggleProperty
                    @param {String} keyName The name of the property to toggle
                    @return {Object} The new property value
                  */
            toggleProperty: function(keyName) {
                set(this, keyName, !get(this, keyName));
                return get(this, keyName);
            },

            /**
                    Returns the cached value of a computed property, if it exists.
                    This allows you to inspect the value of a computed property
                    without accidentally invoking it if it is intended to be
                    generated lazily.

                    @method cacheFor
                    @param {String} keyName
                    @return {Object} The cached value of the computed property, if any
                  */
            cacheFor: function(keyName) {
                return cacheFor(this, keyName);
            },

            // intended for debugging purposes
            observersForKey: function(keyName) {
                return observersFor(this, keyName);
            }
        });
    });
    define("ember-runtime/mixins/promise_proxy",
    ["ember-metal/property_get", "ember-metal/property_set", "ember-metal/computed", "ember-metal/mixin", "ember-metal/error", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
        "use strict";
        var get = __dependency1__.get;
        var set = __dependency2__.set;
        var computed = __dependency3__.computed;
        var Mixin = __dependency4__.Mixin;
        var EmberError = __dependency5__["default"];

        var not = computed.not;
        var or = computed.or;

        /**
              @module ember
              @submodule ember-runtime
             */

        function tap(proxy, promise) {
            set(proxy, 'isFulfilled', false);
            set(proxy, 'isRejected', false);

            return promise.then(function(value) {
                set(proxy, 'isFulfilled', true);
                set(proxy, 'content', value);
                return value;
            }, function(reason) {
                set(proxy, 'isRejected', true);
                set(proxy, 'reason', reason);
                throw reason;
            }, "Ember: PromiseProxy");
        }

        /**
              A low level mixin making ObjectProxy, ObjectController or ArrayController's promise aware.

              ```javascript
              var ObjectPromiseController = Ember.ObjectController.extend(Ember.PromiseProxyMixin);

              var controller = ObjectPromiseController.create({
                promise: $.getJSON('/some/remote/data.json')
              });

              controller.then(function(json){
                 // the json
              }, function(reason) {
                 // the reason why you have no json
              });
              ```

              the controller has bindable attributes which
              track the promises life cycle

              ```javascript
              controller.get('isPending')   //=> true
              controller.get('isSettled')  //=> false
              controller.get('isRejected')  //=> false
              controller.get('isFulfilled') //=> false
              ```

              When the the $.getJSON completes, and the promise is fulfilled
              with json, the life cycle attributes will update accordingly.

              ```javascript
              controller.get('isPending')   //=> false
              controller.get('isSettled')   //=> true
              controller.get('isRejected')  //=> false
              controller.get('isFulfilled') //=> true
              ```

              As the controller is an ObjectController, and the json now its content,
              all the json properties will be available directly from the controller.

              ```javascript
              // Assuming the following json:
              {
                firstName: 'Stefan',
                lastName: 'Penner'
              }

              // both properties will accessible on the controller
              controller.get('firstName') //=> 'Stefan'
              controller.get('lastName')  //=> 'Penner'
              ```

              If the controller is backing a template, the attributes are
              bindable from within that template

              ```handlebars
              {{#if isPending}}
                loading...
              {{else}}
                firstName: {{firstName}}
                lastName: {{lastName}}
              {{/if}}
              ```
              @class Ember.PromiseProxyMixin
            */
        __exports__["default"] = Mixin.create({
            /**
                    If the proxied promise is rejected this will contain the reason
                    provided.

                    @property reason
                    @default null
                  */
            reason: null,

            /**
                    Once the proxied promise has settled this will become `false`.

                    @property isPending
                    @default true
                  */
            isPending: not('isSettled').readOnly(),

            /**
                    Once the proxied promise has settled this will become `true`.

                    @property isSettled
                    @default false
                  */
            isSettled: or('isRejected', 'isFulfilled').readOnly(),

            /**
                    Will become `true` if the proxied promise is rejected.

                    @property isRejected
                    @default false
                  */
            isRejected: false,

            /**
                    Will become `true` if the proxied promise is fulfilled.

                    @property isFulfilled
                    @default false
                  */
            isFulfilled: false,

            /**
                    The promise whose fulfillment value is being proxied by this object.

                    This property must be specified upon creation, and should not be
                    changed once created.

                    Example:

                    ```javascript
                    Ember.ObjectController.extend(Ember.PromiseProxyMixin).create({
                      promise: <thenable>
                    });
                    ```

                    @property promise
                  */
            promise: computed(function(key, promise) {
                if (arguments.length === 2) {
                    return tap(this, promise);
                } else {
                    throw new EmberError("PromiseProxy's promise must be set");
                }
            }),

            /**
                    An alias to the proxied promise's `then`.

                    See RSVP.Promise.then.

                    @method then
                    @param {Function} callback
                    @return {RSVP.Promise}
                  */
            then: promiseAlias('then'),

            /**
                    An alias to the proxied promise's `catch`.

                    See RSVP.Promise.catch.

                    @method catch
                    @param {Function} callback
                    @return {RSVP.Promise}
                    @since 1.3.0
                  */
            'catch': promiseAlias('catch'),

            /**
                    An alias to the proxied promise's `finally`.

                    See RSVP.Promise.finally.

                    @method finally
                    @param {Function} callback
                    @return {RSVP.Promise}
                    @since 1.3.0
                  */
            'finally': promiseAlias('finally')
        });

        function promiseAlias(name) {
            return function () {
                var promise = get(this, 'promise');
                return promise[name].apply(promise, arguments);
            };
        }
    });
    define("ember-runtime/mixins/sortable",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/enumerable_utils", "ember-metal/mixin", "ember-runtime/mixins/mutable_enumerable", "ember-runtime/compare", "ember-metal/observer", "ember-metal/computed", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-runtime
            */

        var Ember = __dependency1__["default"];
        // Ember.assert, Ember.A

        var get = __dependency2__.get;
        var set = __dependency3__.set;
        var forEach = __dependency4__.forEach;
        var Mixin = __dependency5__.Mixin;
        var MutableEnumerable = __dependency6__["default"];
        var compare = __dependency7__["default"];
        var addObserver = __dependency8__.addObserver;
        var removeObserver = __dependency8__.removeObserver;
        var computed = __dependency9__.computed;
        var beforeObserver = __dependency5__.beforeObserver;
        var observer = __dependency5__.observer;
        //ES6TODO: should we access these directly from their package or from how thier exposed in ember-metal?

        /**
              `Ember.SortableMixin` provides a standard interface for array proxies
              to specify a sort order and maintain this sorting when objects are added,
              removed, or updated without changing the implicit order of their underlying
              modelarray:

              ```javascript
              songs = [
                {trackNumber: 4, title: 'Ob-La-Di, Ob-La-Da'},
                {trackNumber: 2, title: 'Back in the U.S.S.R.'},
                {trackNumber: 3, title: 'Glass Onion'},
              ];

              songsController = Ember.ArrayController.create({
                model: songs,
                sortProperties: ['trackNumber'],
                sortAscending: true
              });

              songsController.get('firstObject');  // {trackNumber: 2, title: 'Back in the U.S.S.R.'}

              songsController.addObject({trackNumber: 1, title: 'Dear Prudence'});
              songsController.get('firstObject');  // {trackNumber: 1, title: 'Dear Prudence'}
              ```

              If you add or remove the properties to sort by or change the sort direction the model
              sort order will be automatically updated.

              ```javascript
              songsController.set('sortProperties', ['title']);
              songsController.get('firstObject'); // {trackNumber: 2, title: 'Back in the U.S.S.R.'}

              songsController.toggleProperty('sortAscending');
              songsController.get('firstObject'); // {trackNumber: 4, title: 'Ob-La-Di, Ob-La-Da'}
              ```

              SortableMixin works by sorting the arrangedContent array, which is the array that
              arrayProxy displays. Due to the fact that the underlying 'content' array is not changed, that
              array will not display the sorted list:

               ```javascript
              songsController.get('content').get('firstObject'); // Returns the unsorted original content
              songsController.get('firstObject'); // Returns the sorted content.
              ```

              Although the sorted content can also be accessed through the arrangedContent property,
              it is preferable to use the proxied class and not the arrangedContent array directly.

              @class SortableMixin
              @namespace Ember
              @uses Ember.MutableEnumerable
            */
        __exports__["default"] = Mixin.create(MutableEnumerable, {

            /**
                    Specifies which properties dictate the arrangedContent's sort order.

                    When specifying multiple properties the sorting will use properties
                    from the `sortProperties` array prioritized from first to last.

                    @property {Array} sortProperties
                  */
            sortProperties: null,

            /**
                    Specifies the arrangedContent's sort direction.
                    Sorts the content in ascending order by default. Set to `false` to
                    use descending order.

                    @property {Boolean} sortAscending
                    @default true
                  */
            sortAscending: true,

            /**
                    The function used to compare two values. You can override this if you
                    want to do custom comparisons. Functions must be of the type expected by
                    Array#sort, i.e.
                      return 0 if the two parameters are equal,
                      return a negative value if the first parameter is smaller than the second or
                      return a positive value otherwise:

                    ```javascript
                    function(x,y) { // These are assumed to be integers
                      if (x === y)
                        return 0;
                      return x < y ? -1 : 1;
                    }
                    ```

                    @property sortFunction
                    @type {Function}
                    @default Ember.compare
                  */
            sortFunction: compare,

            orderBy: function(item1, item2) {
                var result = 0,
                sortProperties = get(this, 'sortProperties'),
                sortAscending = get(this, 'sortAscending'),
                sortFunction = get(this, 'sortFunction');

                Ember.assert("you need to define `sortProperties`", !!sortProperties);

                forEach(sortProperties, function(propertyName) {
                    if (result === 0) {
                        result = sortFunction.call(this, get(item1, propertyName), get(item2, propertyName));
                        if ((result !== 0) && !sortAscending) {
                            result = (-1) * result;
                        }
                    }
                }, this);

                return result;
            },

            destroy: function() {
                var content = get(this, 'content'),
                sortProperties = get(this, 'sortProperties');

                if (content && sortProperties) {
                    forEach(content, function(item) {
                        forEach(sortProperties, function(sortProperty) {
                            removeObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
                        }, this);
                    }, this);
                }

                return this._super();
            },

            isSorted: computed.notEmpty('sortProperties'),

            /**
                    Overrides the default arrangedContent from arrayProxy in order to sort by sortFunction.
                    Also sets up observers for each sortProperty on each item in the content Array.

                    @property arrangedContent
                  */

            arrangedContent: computed('content', 'sortProperties.@each', function(key, value) {
                var content = get(this, 'content'),
                isSorted = get(this, 'isSorted'),
                sortProperties = get(this, 'sortProperties'),
                self = this;

                if (content && isSorted) {
                    content = content.slice();
                    content.sort(function(item1, item2) {
                        return self.orderBy(item1, item2);
                    });
                    forEach(content, function(item) {
                        forEach(sortProperties, function(sortProperty) {
                            addObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
                        }, this);
                    }, this);
                    return Ember.A(content);
                }

                return content;
            }),

            _contentWillChange: beforeObserver('content', function() {
                var content = get(this, 'content'),
                sortProperties = get(this, 'sortProperties');

                if (content && sortProperties) {
                    forEach(content, function(item) {
                        forEach(sortProperties, function(sortProperty) {
                            removeObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
                        }, this);
                    }, this);
                }

                this._super();
            }),

            sortPropertiesWillChange: beforeObserver('sortProperties', function() {
                this._lastSortAscending = undefined;
            }),

            sortPropertiesDidChange: observer('sortProperties', function() {
                this._lastSortAscending = undefined;
            }),

            sortAscendingWillChange: beforeObserver('sortAscending', function() {
                this._lastSortAscending = get(this, 'sortAscending');
            }),

            sortAscendingDidChange: observer('sortAscending', function() {
                if (this._lastSortAscending !== undefined && get(this, 'sortAscending') !== this._lastSortAscending) {
                    var arrangedContent = get(this, 'arrangedContent');
                    arrangedContent.reverseObjects();
                }
            }),

            contentArrayWillChange: function(array, idx, removedCount, addedCount) {
                var isSorted = get(this, 'isSorted');

                if (isSorted) {
                    var arrangedContent = get(this, 'arrangedContent');
                    var removedObjects = array.slice(idx, idx + removedCount);
                    var sortProperties = get(this, 'sortProperties');

                    forEach(removedObjects, function(item) {
                        arrangedContent.removeObject(item);

                        forEach(sortProperties, function(sortProperty) {
                            removeObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
                        }, this);
                    }, this);
                }

                return this._super(array, idx, removedCount, addedCount);
            },

            contentArrayDidChange: function(array, idx, removedCount, addedCount) {
                var isSorted = get(this, 'isSorted'),
                sortProperties = get(this, 'sortProperties');

                if (isSorted) {
                    var addedObjects = array.slice(idx, idx + addedCount);

                    forEach(addedObjects, function(item) {
                        this.insertItemSorted(item);

                        forEach(sortProperties, function(sortProperty) {
                            addObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
                        }, this);
                    }, this);
                }

                return this._super(array, idx, removedCount, addedCount);
            },

            insertItemSorted: function(item) {
                var arrangedContent = get(this, 'arrangedContent');
                var length = get(arrangedContent, 'length');

                var idx = this._binarySearch(item, 0, length);
                arrangedContent.insertAt(idx, item);
            },

            contentItemSortPropertyDidChange: function(item) {
                var arrangedContent = get(this, 'arrangedContent'),
                oldIndex = arrangedContent.indexOf(item),
                leftItem = arrangedContent.objectAt(oldIndex - 1),
                rightItem = arrangedContent.objectAt(oldIndex + 1),
                leftResult = leftItem && this.orderBy(item, leftItem),
                rightResult = rightItem && this.orderBy(item, rightItem);

                if (leftResult < 0 || rightResult > 0) {
                    arrangedContent.removeObject(item);
                    this.insertItemSorted(item);
                }
            },

            _binarySearch: function(item, low, high) {
                var mid, midItem, res, arrangedContent;

                if (low === high) {
                    return low;
                }

                arrangedContent = get(this, 'arrangedContent');

                mid = low + Math.floor((high - low) / 2);
                midItem = arrangedContent.objectAt(mid);

                res = this.orderBy(midItem, item);

                if (res < 0) {
                    return this._binarySearch(item, mid + 1, high);
                } else if (res > 0) {
                    return this._binarySearch(item, low, mid);
                }

                return mid;
            }
        });
    });
    define("ember-runtime/mixins/target_action_support",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/utils", "ember-metal/mixin", "ember-metal/computed", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-runtime
            */
        var Ember = __dependency1__["default"];
        // Ember.lookup, Ember.assert

        var get = __dependency2__.get;
        var set = __dependency3__.set;
        var typeOf = __dependency4__.typeOf;
        var Mixin = __dependency5__.Mixin;
        var computed = __dependency6__.computed;

        /**
            `Ember.TargetActionSupport` is a mixin that can be included in a class
            to add a `triggerAction` method with semantics similar to the Handlebars
            `{{action}}` helper. In normal Ember usage, the `{{action}}` helper is
            usually the best choice. This mixin is most often useful when you are
            doing more complex event handling in View objects.

            See also `Ember.ViewTargetActionSupport`, which has
            view-aware defaults for target and actionContext.

            @class TargetActionSupport
            @namespace Ember
            @extends Ember.Mixin
            */
        var TargetActionSupport = Mixin.create({
            target: null,
            action: null,
            actionContext: null,

            targetObject: computed(function() {
                var target = get(this, 'target');

                if (typeOf(target) === "string") {
                    var value = get(this, target);
                    if (value === undefined) {
                        value = get(Ember.lookup, target);
                    }
                    return value;
                } else {
                    return target;
                }
            }).property('target'),

            actionContextObject: computed(function() {
                var actionContext = get(this, 'actionContext');

                if (typeOf(actionContext) === "string") {
                    var value = get(this, actionContext);
                    if (value === undefined) {
                        value = get(Ember.lookup, actionContext);
                    }
                    return value;
                } else {
                    return actionContext;
                }
            }).property('actionContext'),

            /**
                  Send an `action` with an `actionContext` to a `target`. The action, actionContext
                  and target will be retrieved from properties of the object. For example:

                  ```javascript
                  App.SaveButtonView = Ember.View.extend(Ember.TargetActionSupport, {
                    target: Ember.computed.alias('controller'),
                    action: 'save',
                    actionContext: Ember.computed.alias('context'),
                    click: function() {
                      this.triggerAction(); // Sends the `save` action, along with the current context
                                            // to the current controller
                    }
                  });
                  ```

                  The `target`, `action`, and `actionContext` can be provided as properties of
                  an optional object argument to `triggerAction` as well.

                  ```javascript
                  App.SaveButtonView = Ember.View.extend(Ember.TargetActionSupport, {
                    click: function() {
                      this.triggerAction({
                        action: 'save',
                        target: this.get('controller'),
                        actionContext: this.get('context')
                      }); // Sends the `save` action, along with the current context
                          // to the current controller
                    }
                  });
                  ```

                  The `actionContext` defaults to the object you are mixing `TargetActionSupport` into.
                  But `target` and `action` must be specified either as properties or with the argument
                  to `triggerAction`, or a combination:

                  ```javascript
                  App.SaveButtonView = Ember.View.extend(Ember.TargetActionSupport, {
                    target: Ember.computed.alias('controller'),
                    click: function() {
                      this.triggerAction({
                        action: 'save'
                      }); // Sends the `save` action, along with a reference to `this`,
                          // to the current controller
                    }
                  });
                  ```

                  @method triggerAction
                  @param opts {Hash} (optional, with the optional keys action, target and/or actionContext)
                  @return {Boolean} true if the action was sent successfully and did not return false
                  */
            triggerAction: function(opts) {
                opts = opts || {};
                var action = opts.action || get(this, 'action'),
                target = opts.target || get(this, 'targetObject'),
                actionContext = opts.actionContext;

                function args(options, actionName) {
                    var ret = [];
                    if (actionName) {
                        ret.push(actionName);
                    }

                    return ret.concat(options);
                }

                if (typeof actionContext === 'undefined') {
                    actionContext = get(this, 'actionContextObject') || this;
                }

                if (target && action) {
                    var ret;

                    if (target.send) {
                        ret = target.send.apply(target, args(actionContext, action));
                    } else {
                        Ember.assert("The action '" + action + "' did not exist on " + target, typeof target[action] === 'function');
                        ret = target[action].apply(target, args(actionContext));
                    }

                    if (ret !== false) 
                        ret = true;

                    return ret;
                } else {
                    return false;
                }
            }
        });

        __exports__["default"] = TargetActionSupport;
    });
    define("ember-runtime/system/application",
    ["ember-runtime/system/namespace", "exports"],
    function(__dependency1__, __exports__) {
        "use strict";
        var Namespace = __dependency1__["default"];

        __exports__["default"] = Namespace.extend();
    });
    define("ember-runtime/system/array_proxy",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/utils", "ember-metal/computed", "ember-metal/mixin", "ember-metal/property_events", "ember-metal/error", "ember-runtime/system/object", "ember-runtime/mixins/mutable_array", "ember-runtime/mixins/enumerable", "ember-runtime/system/string", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // Ember.K, Ember.assert
        var get = __dependency2__.get;
        var set = __dependency3__.set;
        var isArray = __dependency4__.isArray;
        var apply = __dependency4__.apply;
        var computed = __dependency5__.computed;
        var beforeObserver = __dependency6__.beforeObserver;
        var observer = __dependency6__.observer;
        var beginPropertyChanges = __dependency7__.beginPropertyChanges;
        var endPropertyChanges = __dependency7__.endPropertyChanges;
        var EmberError = __dependency8__["default"];
        var EmberObject = __dependency9__["default"];
        var MutableArray = __dependency10__["default"];
        var Enumerable = __dependency11__["default"];
        var fmt = __dependency12__.fmt;

        /**
            @module ember
            @submodule ember-runtime
            */

        var OUT_OF_RANGE_EXCEPTION = "Index out of range";
        var EMPTY = [];
        var alias = computed.alias;
        var K = Ember.K;

        /**
              An ArrayProxy wraps any other object that implements `Ember.Array` and/or
              `Ember.MutableArray,` forwarding all requests. This makes it very useful for
              a number of binding use cases or other cases where being able to swap
              out the underlying array is useful.

              A simple example of usage:

              ```javascript
              var pets = ['dog', 'cat', 'fish'];
              var ap = Ember.ArrayProxy.create({ content: Ember.A(pets) });

              ap.get('firstObject');                        // 'dog'
              ap.set('content', ['amoeba', 'paramecium']);
              ap.get('firstObject');                        // 'amoeba'
              ```

              This class can also be useful as a layer to transform the contents of
              an array, as they are accessed. This can be done by overriding
              `objectAtContent`:

              ```javascript
              var pets = ['dog', 'cat', 'fish'];
              var ap = Ember.ArrayProxy.create({
                  content: Ember.A(pets),
                  objectAtContent: function(idx) {
                      return this.get('content').objectAt(idx).toUpperCase();
                  }
              });

              ap.get('firstObject'); // . 'DOG'
              ```

              @class ArrayProxy
              @namespace Ember
              @extends Ember.Object
              @uses Ember.MutableArray
            */
        var ArrayProxy = EmberObject.extend(MutableArray, {

            /**
                    The content array. Must be an object that implements `Ember.Array` and/or
                    `Ember.MutableArray.`

                    @property content
                    @type Ember.Array
                  */
            content: null,

            /**
                   The array that the proxy pretends to be. In the default `ArrayProxy`
                   implementation, this and `content` are the same. Subclasses of `ArrayProxy`
                   can override this property to provide things like sorting and filtering.

                   @property arrangedContent
                  */
            arrangedContent: alias('content'),

            /**
                    Should actually retrieve the object at the specified index from the
                    content. You can override this method in subclasses to transform the
                    content item to something new.

                    This method will only be called if content is non-`null`.

                    @method objectAtContent
                    @param {Number} idx The index to retrieve.
                    @return {Object} the value or undefined if none found
                  */
            objectAtContent: function(idx) {
                return get(this, 'arrangedContent').objectAt(idx);
            },

            /**
                    Should actually replace the specified objects on the content array.
                    You can override this method in subclasses to transform the content item
                    into something new.

                    This method will only be called if content is non-`null`.

                    @method replaceContent
                    @param {Number} idx The starting index
                    @param {Number} amt The number of items to remove from the content.
                    @param {Array} objects Optional array of objects to insert or null if no
                      objects.
                    @return {void}
                  */
            replaceContent: function(idx, amt, objects) {
                get(this, 'content').replace(idx, amt, objects);
            },

            /**
                    Invoked when the content property is about to change. Notifies observers that the
                    entire array content will change.

                    @private
                    @method _contentWillChange
                  */
            _contentWillChange: beforeObserver('content', function() {
                this._teardownContent();
            }),

            _teardownContent: function() {
                var content = get(this, 'content');

                if (content) {
                    content.removeArrayObserver(this, {
                        willChange: 'contentArrayWillChange',
                        didChange: 'contentArrayDidChange'
                    });
                }
            },

            contentArrayWillChange: K,
            contentArrayDidChange: K,

            /**
                    Invoked when the content property changes. Notifies observers that the
                    entire array content has changed.

                    @private
                    @method _contentDidChange
                  */
            _contentDidChange: observer('content', function() {
                var content = get(this, 'content');

                Ember.assert("Can't set ArrayProxy's content to itself", content !== this);

                this._setupContent();
            }),

            _setupContent: function() {
                var content = get(this, 'content');

                if (content) {
                    Ember.assert(fmt('ArrayProxy expects an Array or ' +
                    'Ember.ArrayProxy, but you passed %@', [typeof content]),
                    isArray(content) || content.isDestroyed);

                    content.addArrayObserver(this, {
                        willChange: 'contentArrayWillChange',
                        didChange: 'contentArrayDidChange'
                    });
                }
            },

            _arrangedContentWillChange: beforeObserver('arrangedContent', function() {
                var arrangedContent = get(this, 'arrangedContent'),
                len = arrangedContent ? get(arrangedContent, 'length') : 0;

                this.arrangedContentArrayWillChange(this, 0, len, undefined);
                this.arrangedContentWillChange(this);

                this._teardownArrangedContent(arrangedContent);
            }),

            _arrangedContentDidChange: observer('arrangedContent', function() {
                var arrangedContent = get(this, 'arrangedContent'),
                len = arrangedContent ? get(arrangedContent, 'length') : 0;

                Ember.assert("Can't set ArrayProxy's content to itself", arrangedContent !== this);

                this._setupArrangedContent();

                this.arrangedContentDidChange(this);
                this.arrangedContentArrayDidChange(this, 0, undefined, len);
            }),

            _setupArrangedContent: function() {
                var arrangedContent = get(this, 'arrangedContent');

                if (arrangedContent) {
                    Ember.assert(fmt('ArrayProxy expects an Array or ' +
                    'Ember.ArrayProxy, but you passed %@', [typeof arrangedContent]),
                    isArray(arrangedContent) || arrangedContent.isDestroyed);

                    arrangedContent.addArrayObserver(this, {
                        willChange: 'arrangedContentArrayWillChange',
                        didChange: 'arrangedContentArrayDidChange'
                    });
                }
            },

            _teardownArrangedContent: function() {
                var arrangedContent = get(this, 'arrangedContent');

                if (arrangedContent) {
                    arrangedContent.removeArrayObserver(this, {
                        willChange: 'arrangedContentArrayWillChange',
                        didChange: 'arrangedContentArrayDidChange'
                    });
                }
            },

            arrangedContentWillChange: K,
            arrangedContentDidChange: K,

            objectAt: function(idx) {
                return get(this, 'content') && this.objectAtContent(idx);
            },

            length: computed(function() {
                var arrangedContent = get(this, 'arrangedContent');
                return arrangedContent ? get(arrangedContent, 'length') : 0;
                // No dependencies since Enumerable notifies length of change
            }),

            _replace: function(idx, amt, objects) {
                var content = get(this, 'content');
                Ember.assert('The content property of ' + this.constructor + ' should be set before modifying it', content);
                if (content) 
                    this.replaceContent(idx, amt, objects);
                return this;
            },

            replace: function() {
                if (get(this, 'arrangedContent') === get(this, 'content')) {
                    apply(this, this._replace, arguments);
                } else {
                    throw new EmberError("Using replace on an arranged ArrayProxy is not allowed.");
                }
            },

            _insertAt: function(idx, object) {
                if (idx > get(this, 'content.length')) 
                    throw new EmberError(OUT_OF_RANGE_EXCEPTION);
                this._replace(idx, 0, [object]);
                return this;
            },

            insertAt: function(idx, object) {
                if (get(this, 'arrangedContent') === get(this, 'content')) {
                    return this._insertAt(idx, object);
                } else {
                    throw new EmberError("Using insertAt on an arranged ArrayProxy is not allowed.");
                }
            },

            removeAt: function(start, len) {
                if ('number' === typeof start) {
                    var content = get(this, 'content'),
                    arrangedContent = get(this, 'arrangedContent'),
                    indices = [], i;

                    if ((start < 0) || (start >= get(this, 'length'))) {
                        throw new EmberError(OUT_OF_RANGE_EXCEPTION);
                    }

                    if (len === undefined) 
                        len = 1;

                    // Get a list of indices in original content to remove
                    for (i = start; i < start + len; i++) {
                        // Use arrangedContent here so we avoid confusion with objects transformed by objectAtContent
                        indices.push(content.indexOf(arrangedContent.objectAt(i)));
                    }

                    // Replace in reverse order since indices will change
                    indices.sort(function(a, b) {
                        return b - a;
                    });

                    beginPropertyChanges();
                    for (i = 0; i < indices.length; i++) {
                        this._replace(indices[i], 1, EMPTY);
                    }
                    endPropertyChanges();
                }

                return this ;
            },

            pushObject: function(obj) {
                this._insertAt(get(this, 'content.length'), obj) ;
                return obj ;
            },

            pushObjects: function(objects) {
                if (!(Enumerable.detect(objects) || isArray(objects))) {
                    throw new TypeError("Must pass Ember.Enumerable to Ember.MutableArray#pushObjects");
                }
                this._replace(get(this, 'length'), 0, objects);
                return this;
            },

            setObjects: function(objects) {
                if (objects.length === 0) 
                    return this.clear();

                var len = get(this, 'length');
                this._replace(0, len, objects);
                return this;
            },

            unshiftObject: function(obj) {
                this._insertAt(0, obj) ;
                return obj ;
            },

            unshiftObjects: function(objects) {
                this._replace(0, 0, objects);
                return this;
            },

            slice: function() {
                var arr = this.toArray();
                return arr.slice.apply(arr, arguments);
            },

            arrangedContentArrayWillChange: function(item, idx, removedCnt, addedCnt) {
                this.arrayContentWillChange(idx, removedCnt, addedCnt);
            },

            arrangedContentArrayDidChange: function(item, idx, removedCnt, addedCnt) {
                this.arrayContentDidChange(idx, removedCnt, addedCnt);
            },

            init: function() {
                this._super();
                this._setupContent();
                this._setupArrangedContent();
            },

            willDestroy: function() {
                this._teardownArrangedContent();
                this._teardownContent();
            }
        });

        __exports__["default"] = ArrayProxy;
    });
    define("ember-runtime/system/container",
    ["ember-metal/property_set", "exports"],
    function(__dependency1__, __exports__) {
        "use strict";
        var set = __dependency1__["default"];

        var Container = requireModule('container')["default"];
        Container.set = set;

        __exports__["default"] = Container;
    });
    define("ember-runtime/system/core_object",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/utils", "ember-metal/platform", "ember-metal/watching", "ember-metal/chains", "ember-metal/events", "ember-metal/mixin", "ember-metal/enumerable_utils", "ember-metal/error", "ember-runtime/keys", "ember-runtime/mixins/action_handler", "ember-metal/properties", "ember-metal/binding", "ember-metal/computed", "ember-metal/run_loop", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __exports__) {
        "use strict";
        /**
              @module ember
              @submodule ember-runtime
            */

        var Ember = __dependency1__["default"];
        // Ember.ENV.MANDATORY_SETTER, Ember.assert, Ember.K, Ember.config

        // NOTE: this object should never be included directly. Instead use `Ember.Object`.
        // We only define this separately so that `Ember.Set` can depend on it.
        var get = __dependency2__.get;
        var set = __dependency3__.set;
        var guidFor = __dependency4__.guidFor;
        var apply = __dependency4__.apply;
        var o_create = __dependency5__.create;
        var generateGuid = __dependency4__.generateGuid;
        var GUID_KEY = __dependency4__.GUID_KEY;
        var meta = __dependency4__.meta;
        var META_KEY = __dependency4__.META_KEY;
        var makeArray = __dependency4__.makeArray;
        var rewatch = __dependency6__.rewatch;
        var finishChains = __dependency7__.finishChains;
        var sendEvent = __dependency8__.sendEvent;
        var IS_BINDING = __dependency9__.IS_BINDING;
        var Mixin = __dependency9__.Mixin;
        var required = __dependency9__.required;
        var indexOf = __dependency10__.indexOf;
        var EmberError = __dependency11__["default"];
        var platform = __dependency5__.platform;
        var keys = __dependency12__["default"];
        var ActionHandler = __dependency13__["default"];
        var defineProperty = __dependency14__.defineProperty;
        var Binding = __dependency15__.Binding;
        var ComputedProperty = __dependency16__.ComputedProperty;
        var run = __dependency17__["default"];
        var destroy = __dependency6__.destroy;

        var K = __dependency1__.K;
        var o_defineProperty = platform.defineProperty;
        var schedule = run.schedule;
        var applyMixin = Mixin._apply;
        var finishPartial = Mixin.finishPartial;
        var reopen = Mixin.prototype.reopen;
        var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER;
        var hasCachedComputedProperties = false;

        var undefinedDescriptor = {
            configurable: true,
            writable: true,
            enumerable: false,
            value: undefined
        };

        var nullDescriptor = {
            configurable: true,
            writable: true,
            enumerable: false,
            value: null
        };

        function makeCtor() {

            // Note: avoid accessing any properties on the object since it makes the
            // method a lot faster. This is glue code so we want it to be as fast as
            // possible.

            var wasApplied = false, initMixins, initProperties;

            var Class = function() {
                if (!wasApplied) {
                    Class.proto(); // prepare prototype...
                }
                o_defineProperty(this, GUID_KEY, nullDescriptor);
                o_defineProperty(this, '__nextSuper', undefinedDescriptor);
                var m = meta(this), proto = m.proto;
                m.proto = this;
                if (initMixins) {
                    // capture locally so we can clear the closed over variable
                    var mixins = initMixins;
                    initMixins = null;
                    apply(this, this.reopen, mixins);
                }
                if (initProperties) {
                    // capture locally so we can clear the closed over variable
                    var props = initProperties;
                    initProperties = null;

                    var concatenatedProperties = this.concatenatedProperties;

                    for (var i = 0, l = props.length; i < l; i++) {
                        var properties = props[i];

                        Ember.assert("Ember.Object.create no longer supports mixing in other definitions, use createWithMixins instead.", !(properties instanceof Mixin));

                        if (typeof properties !== 'object' && properties !== undefined) {
                            throw new EmberError("Ember.Object.create only accepts objects.");
                        }

                        if (!properties) {
                            continue;
                        }

                        var keyNames = keys(properties);

                        for (var j = 0, ll = keyNames.length; j < ll; j++) {
                            var keyName = keyNames[j];
                            if (!properties.hasOwnProperty(keyName)) {
                                continue;
                            }

                            var value = properties[keyName];

                            if (IS_BINDING.test(keyName)) {
                                var bindings = m.bindings;
                                if (!bindings) {
                                    bindings = m.bindings = {};
                                } else if (!m.hasOwnProperty('bindings')) {
                                    bindings = m.bindings = o_create(m.bindings);
                                }
                                bindings[keyName] = value;
                            }

                            var desc = m.descs[keyName];

                            Ember.assert("Ember.Object.create no longer supports defining computed properties. Define computed properties using extend() or reopen() before calling create().", !(value instanceof ComputedProperty));
                            Ember.assert("Ember.Object.create no longer supports defining methods that call _super.", !(typeof value === 'function' && value.toString().indexOf('._super') !== -1));
                            Ember.assert("`actions` must be provided at extend time, not at create " +
                            "time, when Ember.ActionHandler is used (i.e. views, " +
                            "controllers & routes).", !((keyName === 'actions') && ActionHandler.detect(this)));

                            if (concatenatedProperties && indexOf(concatenatedProperties, keyName) >= 0) {
                                var baseValue = this[keyName];

                                if (baseValue) {
                                    if ('function' === typeof baseValue.concat) {
                                        value = baseValue.concat(value);
                                    } else {
                                        value = makeArray(baseValue).concat(value);
                                    }
                                } else {
                                    value = makeArray(value);
                                }
                            }

                            if (desc) {
                                desc.set(this, keyName, value);
                            } else {
                                if (typeof this.setUnknownProperty === 'function' && !(keyName in this)) {
                                    this.setUnknownProperty(keyName, value);
                                } else if (MANDATORY_SETTER) {
                                    defineProperty(this, keyName, null, value); // setup mandatory setter
                                } else {
                                    this[keyName] = value;
                                }
                            }
                        }
                    }
                }
                finishPartial(this, m);
                apply(this, this.init, arguments);
                m.proto = proto;
                finishChains(this);
                sendEvent(this, "init");
            };

            Class.toString = Mixin.prototype.toString;
            Class.willReopen = function() {
                if (wasApplied) {
                    Class.PrototypeMixin = Mixin.create(Class.PrototypeMixin);
                }

                wasApplied = false;
            };
            Class._initMixins = function(args) {
                initMixins = args;
            };
            Class._initProperties = function(args) {
                initProperties = args;
            };

            Class.proto = function() {
                var superclass = Class.superclass;
                if (superclass) {
                    superclass.proto();
                }

                if (!wasApplied) {
                    wasApplied = true;
                    Class.PrototypeMixin.applyPartial(Class.prototype);
                    rewatch(Class.prototype);
                }

                return this.prototype;
            };

            return Class;

        }

        /**
              @class CoreObject
              @namespace Ember
            */
        var CoreObject = makeCtor();
        CoreObject.toString = function() {
            return "Ember.CoreObject";
        };

        CoreObject.PrototypeMixin = Mixin.create({
            reopen: function() {
                applyMixin(this, arguments, true);
                return this;
            },

            /**
                    An overridable method called when objects are instantiated. By default,
                    does nothing unless it is overridden during class definition.

                    Example:

                    ```javascript
                    App.Person = Ember.Object.extend({
                      init: function() {
                        alert('Name is ' + this.get('name'));
                      }
                    });

                    var steve = App.Person.create({
                      name: "Steve"
                    });

                    // alerts 'Name is Steve'.
                    ```

                    NOTE: If you do override `init` for a framework class like `Ember.View` or
                    `Ember.ArrayController`, be sure to call `this._super()` in your
                    `init` declaration! If you don't, Ember may not have an opportunity to
                    do important setup work, and you'll see strange behavior in your
                    application.

                    @method init
                  */
            init: function() {},

            /**
                    Defines the properties that will be concatenated from the superclass
                    (instead of overridden).

                    By default, when you extend an Ember class a property defined in
                    the subclass overrides a property with the same name that is defined
                    in the superclass. However, there are some cases where it is preferable
                    to build up a property's value by combining the superclass' property
                    value with the subclass' value. An example of this in use within Ember
                    is the `classNames` property of `Ember.View`.

                    Here is some sample code showing the difference between a concatenated
                    property and a normal one:

                    ```javascript
                    App.BarView = Ember.View.extend({
                      someNonConcatenatedProperty: ['bar'],
                      classNames: ['bar']
                    });

                    App.FooBarView = App.BarView.extend({
                      someNonConcatenatedProperty: ['foo'],
                      classNames: ['foo']
                    });

                    var fooBarView = App.FooBarView.create();
                    fooBarView.get('someNonConcatenatedProperty'); // ['foo']
                    fooBarView.get('classNames'); // ['ember-view', 'bar', 'foo']
                    ```

                    This behavior extends to object creation as well. Continuing the
                    above example:

                    ```javascript
                    var view = App.FooBarView.create({
                      someNonConcatenatedProperty: ['baz'],
                      classNames: ['baz']
                    })
                    view.get('someNonConcatenatedProperty'); // ['baz']
                    view.get('classNames'); // ['ember-view', 'bar', 'foo', 'baz']
                    ```
                    Adding a single property that is not an array will just add it in the array:

                    ```javascript
                    var view = App.FooBarView.create({
                      classNames: 'baz'
                    })
                    view.get('classNames'); // ['ember-view', 'bar', 'foo', 'baz']
                    ```

                    Using the `concatenatedProperties` property, we can tell to Ember that mix
                    the content of the properties.

                    In `Ember.View` the `classNameBindings` and `attributeBindings` properties
                    are also concatenated, in addition to `classNames`.

                    This feature is available for you to use throughout the Ember object model,
                    although typical app developers are likely to use it infrequently. Since
                    it changes expectations about behavior of properties, you should properly
                    document its usage in each individual concatenated property (to not
                    mislead your users to think they can override the property in a subclass).

                    @property concatenatedProperties
                    @type Array
                    @default null
                  */
            concatenatedProperties: null,

            /**
                    Destroyed object property flag.

                    if this property is `true` the observers and bindings were already
                    removed by the effect of calling the `destroy()` method.

                    @property isDestroyed
                    @default false
                  */
            isDestroyed: false,

            /**
                    Destruction scheduled flag. The `destroy()` method has been called.

                    The object stays intact until the end of the run loop at which point
                    the `isDestroyed` flag is set.

                    @property isDestroying
                    @default false
                  */
            isDestroying: false,

            /**
                    Destroys an object by setting the `isDestroyed` flag and removing its
                    metadata, which effectively destroys observers and bindings.

                    If you try to set a property on a destroyed object, an exception will be
                    raised.

                    Note that destruction is scheduled for the end of the run loop and does not
                    happen immediately.  It will set an isDestroying flag immediately.

                    @method destroy
                    @return {Ember.Object} receiver
                  */
            destroy: function() {
                if (this.isDestroying) {
                    return;
                }
                this.isDestroying = true;

                schedule('actions', this, this.willDestroy);
                schedule('destroy', this, this._scheduledDestroy);
                return this;
            },

            /**
                    Override to implement teardown.

                    @method willDestroy
                   */
            willDestroy: K,

            /**
                    Invoked by the run loop to actually destroy the object. This is
                    scheduled for execution by the `destroy` method.

                    @private
                    @method _scheduledDestroy
                  */
            _scheduledDestroy: function() {
                if (this.isDestroyed) {
                    return;
                }
                destroy(this);
                this.isDestroyed = true;
            },

            bind: function(to, from) {
                if (!(from instanceof Binding)) {
                    from = Binding.from(from);
                }
                from.to(to).connect(this);
                return from;
            },

            /**
                    Returns a string representation which attempts to provide more information
                    than Javascript's `toString` typically does, in a generic way for all Ember
                    objects.

                    ```javascript
                    App.Person = Em.Object.extend()
                    person = App.Person.create()
                    person.toString() //=> "<App.Person:ember1024>"
                    ```

                    If the object's class is not defined on an Ember namespace, it will
                    indicate it is a subclass of the registered superclass:

                   ```javascript
                    Student = App.Person.extend()
                    student = Student.create()
                    student.toString() //=> "<(subclass of App.Person):ember1025>"
                    ```

                    If the method `toStringExtension` is defined, its return value will be
                    included in the output.

                    ```javascript
                    App.Teacher = App.Person.extend({
                      toStringExtension: function() {
                        return this.get('fullName');
                      }
                    });
                    teacher = App.Teacher.create()
                    teacher.toString(); //=> "<App.Teacher:ember1026:Tom Dale>"
                    ```

                    @method toString
                    @return {String} string representation
                  */
            toString: function toString() {
                var hasToStringExtension = typeof this.toStringExtension === 'function',
                extension = hasToStringExtension ? ":" + this.toStringExtension() : '';
                var ret = '<' + this.constructor.toString() + ':' + guidFor(this) + extension + '>';
                this.toString = makeToString(ret);
                return ret;
            }
        });

        CoreObject.PrototypeMixin.ownerConstructor = CoreObject;

        function makeToString(ret) {
            return function() {
                return ret;
            };
        }

        if (Ember.config.overridePrototypeMixin) {
            Ember.config.overridePrototypeMixin(CoreObject.PrototypeMixin);
        }

        CoreObject.__super__ = null;

        var ClassMixin = Mixin.create({

            ClassMixin: required(),

            PrototypeMixin: required(),

            isClass: true,

            isMethod: false,

            /**
                    Creates a new subclass.

                    ```javascript
                    App.Person = Ember.Object.extend({
                      say: function(thing) {
                        alert(thing);
                       }
                    });
                    ```

                    This defines a new subclass of Ember.Object: `App.Person`. It contains one method: `say()`.

                    You can also create a subclass from any existing class by calling its `extend()`  method. For example, you might want to create a subclass of Ember's built-in `Ember.View` class:

                    ```javascript
                    App.PersonView = Ember.View.extend({
                      tagName: 'li',
                      classNameBindings: ['isAdministrator']
                    });
                    ```

                    When defining a subclass, you can override methods but still access the implementation of your parent class by calling the special `_super()` method:

                    ```javascript
                    App.Person = Ember.Object.extend({
                      say: function(thing) {
                        var name = this.get('name');
                        alert(name + ' says: ' + thing);
                      }
                    });

                    App.Soldier = App.Person.extend({
                      say: function(thing) {
                        this._super(thing + ", sir!");
                      },
                      march: function(numberOfHours) {
                        alert(this.get('name') + ' marches for ' + numberOfHours + ' hours.')
                      }
                    });

                    var yehuda = App.Soldier.create({
                      name: "Yehuda Katz"
                    });

                    yehuda.say("Yes");  // alerts "Yehuda Katz says: Yes, sir!"
                    ```

                    The `create()` on line #17 creates an *instance* of the `App.Soldier` class. The `extend()` on line #8 creates a *subclass* of `App.Person`. Any instance of the `App.Person` class will *not* have the `march()` method.

                    You can also pass `Mixin` classes to add additional properties to the subclass.

                    ```javascript
                    App.Person = Ember.Object.extend({
                      say: function(thing) {
                        alert(this.get('name') + ' says: ' + thing);
                      }
                    });

                    App.SingingMixin = Mixin.create({
                      sing: function(thing){
                        alert(this.get('name') + ' sings: la la la ' + thing);
                      }
                    });

                    App.BroadwayStar = App.Person.extend(App.SingingMixin, {
                      dance: function() {
                        alert(this.get('name') + ' dances: tap tap tap tap ');
                      }
                    });
                    ```

                    The `App.BroadwayStar` class contains three methods: `say()`, `sing()`, and `dance()`.

                    @method extend
                    @static

                    @param {Mixin} [mixins]* One or more Mixin classes
                    @param {Object} [arguments]* Object containing values to use within the new class
                  */
            extend: function() {
                var Class = makeCtor(), proto;
                Class.ClassMixin = Mixin.create(this.ClassMixin);
                Class.PrototypeMixin = Mixin.create(this.PrototypeMixin);

                Class.ClassMixin.ownerConstructor = Class;
                Class.PrototypeMixin.ownerConstructor = Class;

                reopen.apply(Class.PrototypeMixin, arguments);

                Class.superclass = this;
                Class.__super__ = this.prototype;

                proto = Class.prototype = o_create(this.prototype);
                proto.constructor = Class;
                generateGuid(proto);
                meta(proto).proto = proto; // this will disable observers on prototype

                Class.ClassMixin.apply(Class);
                return Class;
            },

            /**
                    Equivalent to doing `extend(arguments).create()`.
                    If possible use the normal `create` method instead.

                    @method createWithMixins
                    @static
                    @param [arguments]*
                  */
            createWithMixins: function() {
                var C = this;
                if (arguments.length > 0) {
                    this._initMixins(arguments);
                }
                return new C();
            },

            /**
                    Creates an instance of a class. Accepts either no arguments, or an object
                    containing values to initialize the newly instantiated object with.

                    ```javascript
                    App.Person = Ember.Object.extend({
                      helloWorld: function() {
                        alert("Hi, my name is " + this.get('name'));
                      }
                    });

                    var tom = App.Person.create({
                      name: 'Tom Dale'
                    });

                    tom.helloWorld(); // alerts "Hi, my name is Tom Dale".
                    ```

                    `create` will call the `init` function if defined during
                    `Ember.AnyObject.extend`

                    If no arguments are passed to `create`, it will not set values to the new
                    instance during initialization:

                    ```javascript
                    var noName = App.Person.create();
                    noName.helloWorld(); // alerts undefined
                    ```

                    NOTE: For performance reasons, you cannot declare methods or computed
                    properties during `create`. You should instead declare methods and computed
                    properties when using `extend` or use the `createWithMixins` shorthand.

                    @method create
                    @static
                    @param [arguments]*
                  */
            create: function() {
                var C = this;
                if (arguments.length > 0) {
                    this._initProperties(arguments);
                }
                return new C();
            },

            /**
                    Augments a constructor's prototype with additional
                    properties and functions:

                    ```javascript
                    MyObject = Ember.Object.extend({
                      name: 'an object'
                    });

                    o = MyObject.create();
                    o.get('name'); // 'an object'

                    MyObject.reopen({
                      say: function(msg){
                        console.log(msg);
                      }
                    })

                    o2 = MyObject.create();
                    o2.say("hello"); // logs "hello"

                    o.say("goodbye"); // logs "goodbye"
                    ```

                    To add functions and properties to the constructor itself,
                    see `reopenClass`

                    @method reopen
                  */
            reopen: function() {
                this.willReopen();
                apply(this.PrototypeMixin, reopen, arguments);
                return this;
            },

            /**
                    Augments a constructor's own properties and functions:

                    ```javascript
                    MyObject = Ember.Object.extend({
                      name: 'an object'
                    });

                    MyObject.reopenClass({
                      canBuild: false
                    });

                    MyObject.canBuild; // false
                    o = MyObject.create();
                    ```

                    In other words, this creates static properties and functions for the class. These are only available on the class
                    and not on any instance of that class.

                    ```javascript
                    App.Person = Ember.Object.extend({
                      name : "",
                      sayHello : function(){
                        alert("Hello. My name is " + this.get('name'));
                      }
                    });

                    App.Person.reopenClass({
                      species : "Homo sapiens",
                      createPerson: function(newPersonsName){
                        return App.Person.create({
                          name:newPersonsName
                        });
                      }
                    });

                    var tom = App.Person.create({
                      name : "Tom Dale"
                    });
                    var yehuda = App.Person.createPerson("Yehuda Katz");

                    tom.sayHello(); // "Hello. My name is Tom Dale"
                    yehuda.sayHello(); // "Hello. My name is Yehuda Katz"
                    alert(App.Person.species); // "Homo sapiens"
                    ```

                    Note that `species` and `createPerson` are *not* valid on the `tom` and `yehuda`
                    variables. They are only valid on `App.Person`.

                    To add functions and properties to instances of
                    a constructor by extending the constructor's prototype
                    see `reopen`

                    @method reopenClass
                  */
            reopenClass: function() {
                apply(this.ClassMixin, reopen, arguments);
                applyMixin(this, arguments, false);
                return this;
            },

            detect: function(obj) {
                if ('function' !== typeof obj) {
                    return false;
                }
                while (obj) {
                    if (obj === this) {
                        return true;
                    }
                    obj = obj.superclass;
                }
                return false;
            },

            detectInstance: function(obj) {
                return obj instanceof this;
            },

            /**
                    In some cases, you may want to annotate computed properties with additional
                    metadata about how they function or what values they operate on. For
                    example, computed property functions may close over variables that are then
                    no longer available for introspection.

                    You can pass a hash of these values to a computed property like this:

                    ```javascript
                    person: function() {
                      var personId = this.get('personId');
                      return App.Person.create({ id: personId });
                    }.property().meta({ type: App.Person })
                    ```

                    Once you've done this, you can retrieve the values saved to the computed
                    property from your class like this:

                    ```javascript
                    MyClass.metaForProperty('person');
                    ```

                    This will return the original hash that was passed to `meta()`.

                    @method metaForProperty
                    @param key {String} property name
                  */
            metaForProperty: function(key) {
                var meta = this.proto()[META_KEY],
                desc = meta && meta.descs[key];

                Ember.assert("metaForProperty() could not find a computed property with key '" + key + "'.", !!desc && desc instanceof ComputedProperty);
                return desc._meta || {};
            },

            _computedProperties: Ember.computed(function() {
                hasCachedComputedProperties = true;
                var proto = this.proto();
                var descs = meta(proto).descs;
                var property;
                var properties = [];

                for (var name in descs) {
                    property = descs[name];

                    if (property instanceof ComputedProperty) {
                        properties.push({
                            name: name,
                            meta: property._meta
                        });
                    }
                }
                return properties;
            }).readOnly(),

            /**
                    Iterate over each computed property for the class, passing its name
                    and any associated metadata (see `metaForProperty`) to the callback.

                    @method eachComputedProperty
                    @param {Function} callback
                    @param {Object} binding
                  */
            eachComputedProperty: function(callback, binding) {
                var property, name;
                var empty = {};

                var properties = get(this, '_computedProperties');

                for (var i = 0, length = properties.length; i < length; i++) {
                    property = properties[i];
                    name = property.name;
                    callback.call(binding || this, property.name, property.meta || empty);
                }
            }
        });

        ClassMixin.ownerConstructor = CoreObject;

        if (Ember.config.overrideClassMixin) {
            Ember.config.overrideClassMixin(ClassMixin);
        }

        CoreObject.ClassMixin = ClassMixin;

        ClassMixin.apply(CoreObject);

        CoreObject.reopen({
            didDefineProperty: function(proto, key, value) {
                if (hasCachedComputedProperties === false) {
                    return;
                }
                if (value instanceof Ember.ComputedProperty) {
                    var cache = Ember.meta(this.constructor).cache;

                    if (cache._computedProperties !== undefined) {
                        cache._computedProperties = undefined;
                    }
                }

                this._super();
            }
        });


        __exports__["default"] = CoreObject;
    });
    define("ember-runtime/system/deferred",
    ["ember-metal/core", "ember-runtime/mixins/deferred", "ember-metal/property_get", "ember-runtime/system/object", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        var DeferredMixin = __dependency2__["default"];
        var get = __dependency3__.get;
        var EmberObject = __dependency4__["default"];

        var Deferred = EmberObject.extend(DeferredMixin, {
            init: function() {
                Ember.deprecate('Usage of Ember.Deferred is deprecated.');
                this._super();
            }
        });

        Deferred.reopenClass({
            promise: function(callback, binding) {
                var deferred = Deferred.create();
                callback.call(binding, deferred);
                return deferred;
            }
        });

        __exports__["default"] = Deferred;
    });
    define("ember-runtime/system/each_proxy",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/utils", "ember-metal/enumerable_utils", "ember-metal/array", "ember-runtime/mixins/array", "ember-runtime/system/object", "ember-metal/computed", "ember-metal/observer", "ember-metal/events", "ember-metal/properties", "ember-metal/property_events", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-runtime
            */

        var Ember = __dependency1__["default"];
        // Ember.assert

        var get = __dependency2__.get;
        var set = __dependency3__.set;
        var guidFor = __dependency4__.guidFor;
        var forEach = __dependency5__.forEach;
        var indexOf = __dependency6__.indexOf;
        var EmberArray = __dependency7__["default"];
        // ES6TODO: WAT? Circular dep?
        var EmberObject = __dependency8__["default"];
        var computed = __dependency9__.computed;
        var addObserver = __dependency10__.addObserver;
        var addBeforeObserver = __dependency10__.addBeforeObserver;
        var removeBeforeObserver = __dependency10__.removeBeforeObserver;
        var removeObserver = __dependency10__.removeObserver;
        var typeOf = __dependency4__.typeOf;
        var watchedEvents = __dependency11__.watchedEvents;
        var defineProperty = __dependency12__.defineProperty;
        var beginPropertyChanges = __dependency13__.beginPropertyChanges;
        var propertyDidChange = __dependency13__.propertyDidChange;
        var propertyWillChange = __dependency13__.propertyWillChange;
        var endPropertyChanges = __dependency13__.endPropertyChanges;
        var changeProperties = __dependency13__.changeProperties;

        var EachArray = EmberObject.extend(EmberArray, {

            init: function(content, keyName, owner) {
                this._super();
                this._keyName = keyName;
                this._owner = owner;
                this._content = content;
            },

            objectAt: function(idx) {
                var item = this._content.objectAt(idx);
                return item && get(item, this._keyName);
            },

            length: computed(function() {
                var content = this._content;
                return content ? get(content, 'length') : 0;
            })
        });

        var IS_OBSERVER = /^.+:(before|change)$/;

        function addObserverForContentKey(content, keyName, proxy, idx, loc) {
            var objects = proxy._objects, guid;
            if (!objects) 
                objects = proxy._objects = {};

            while (--loc >= idx) {
                var item = content.objectAt(loc);
                if (item) {
                    Ember.assert('When using @each to observe the array ' + content + ', the array must return an object', typeOf(item) === 'instance' || typeOf(item) === 'object');
                    addBeforeObserver(item, keyName, proxy, 'contentKeyWillChange');
                    addObserver(item, keyName, proxy, 'contentKeyDidChange');

                    // keep track of the index each item was found at so we can map
                    // it back when the obj changes.
                    guid = guidFor(item);
                    if (!objects[guid]) 
                        objects[guid] = [];
                    objects[guid].push(loc);
                }
            }
        }

        function removeObserverForContentKey(content, keyName, proxy, idx, loc) {
            var objects = proxy._objects;
            if (!objects) 
                objects = proxy._objects = {};
            var indicies, guid;

            while (--loc >= idx) {
                var item = content.objectAt(loc);
                if (item) {
                    removeBeforeObserver(item, keyName, proxy, 'contentKeyWillChange');
                    removeObserver(item, keyName, proxy, 'contentKeyDidChange');

                    guid = guidFor(item);
                    indicies = objects[guid];
                    indicies[indexOf.call(indicies, loc)] = null;
                }
            }
        }

        /**
              This is the object instance returned when you get the `@each` property on an
              array. It uses the unknownProperty handler to automatically create
              EachArray instances for property names.

              @private
              @class EachProxy
              @namespace Ember
              @extends Ember.Object
            */
        var EachProxy = EmberObject.extend({

            init: function(content) {
                this._super();
                this._content = content;
                content.addArrayObserver(this);

                // in case someone is already observing some keys make sure they are
                // added
                forEach(watchedEvents(this), function(eventName) {
                    this.didAddListener(eventName);
                }, this);
            },

            /**
                    You can directly access mapped properties by simply requesting them.
                    The `unknownProperty` handler will generate an EachArray of each item.

                    @method unknownProperty
                    @param keyName {String}
                    @param value {*}
                  */
            unknownProperty: function(keyName, value) {
                var ret;
                ret = new EachArray(this._content, keyName, this);
                defineProperty(this, keyName, null, ret);
                this.beginObservingContentKey(keyName);
                return ret;
            },

            // ..........................................................
            // ARRAY CHANGES
            // Invokes whenever the content array itself changes.

            arrayWillChange: function(content, idx, removedCnt, addedCnt) {
                var keys = this._keys, key, lim;

                lim = removedCnt > 0 ? idx + removedCnt : -1;
                beginPropertyChanges(this);

                for (key in keys) {
                    if (!keys.hasOwnProperty(key)) {
                        continue;
                    }

                    if (lim > 0) {
                        removeObserverForContentKey(content, key, this, idx, lim);
                    }

                    propertyWillChange(this, key);
                }

                propertyWillChange(this._content, '@each');
                endPropertyChanges(this);
            },

            arrayDidChange: function(content, idx, removedCnt, addedCnt) {
                var keys = this._keys, lim;

                lim = addedCnt > 0 ? idx + addedCnt : -1;
                changeProperties(function() {
                    for (var key in keys) {
                        if (!keys.hasOwnProperty(key)) {
                            continue;
                        }

                        if (lim > 0) {
                            addObserverForContentKey(content, key, this, idx, lim);
                        }

                        propertyDidChange(this, key);
                    }

                    propertyDidChange(this._content, '@each');
                }, this);
            },

            // ..........................................................
            // LISTEN FOR NEW OBSERVERS AND OTHER EVENT LISTENERS
            // Start monitoring keys based on who is listening...

            didAddListener: function(eventName) {
                if (IS_OBSERVER.test(eventName)) {
                    this.beginObservingContentKey(eventName.slice(0, -7));
                }
            },

            didRemoveListener: function(eventName) {
                if (IS_OBSERVER.test(eventName)) {
                    this.stopObservingContentKey(eventName.slice(0, -7));
                }
            },

            // ..........................................................
            // CONTENT KEY OBSERVING
            // Actual watch keys on the source content.

            beginObservingContentKey: function(keyName) {
                var keys = this._keys;
                if (!keys) 
                    keys = this._keys = {};
                if (!keys[keyName]) {
                    keys[keyName] = 1;
                    var content = this._content,
                    len = get(content, 'length');
                    addObserverForContentKey(content, keyName, this, 0, len);
                } else {
                    keys[keyName]++;
                }
            },

            stopObservingContentKey: function(keyName) {
                var keys = this._keys;
                if (keys && (keys[keyName] > 0) && (--keys[keyName] <= 0)) {
                    var content = this._content,
                    len = get(content, 'length');
                    removeObserverForContentKey(content, keyName, this, 0, len);
                }
            },

            contentKeyWillChange: function(obj, keyName) {
                propertyWillChange(this, keyName);
            },

            contentKeyDidChange: function(obj, keyName) {
                propertyDidChange(this, keyName);
            }
        });

        __exports__.EachArray = EachArray;
        __exports__.EachProxy = EachProxy;
    });
    define("ember-runtime/system/lazy_load",
    ["ember-metal/core", "ember-metal/array", "ember-runtime/system/native_array", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        /*globals CustomEvent */

        var Ember = __dependency1__["default"];
        // Ember.ENV.EMBER_LOAD_HOOKS
        var forEach = __dependency2__.forEach;
        // make sure Ember.A is setup.

        /**
              @module ember
              @submodule ember-runtime
            */

        var loadHooks = Ember.ENV.EMBER_LOAD_HOOKS || {};
        var loaded = {};

        /**
              Detects when a specific package of Ember (e.g. 'Ember.Handlebars')
              has fully loaded and is available for extension.

              The provided `callback` will be called with the `name` passed
              resolved from a string into the object:

              ``` javascript
              Ember.onLoad('Ember.Handlebars' function(hbars) {
                hbars.registerHelper(...);
              });
              ```

              @method onLoad
              @for Ember
              @param name {String} name of hook
              @param callback {Function} callback to be called
            */
        function onLoad(name, callback) {
            var object;

            loadHooks[name] = loadHooks[name] || Ember.A();
            loadHooks[name].pushObject(callback);

            if (object = loaded[name]) {
                callback(object);
            }
        }

        __exports__.onLoad = onLoad; /**
              Called when an Ember.js package (e.g Ember.Handlebars) has finished
              loading. Triggers any callbacks registered for this event.

              @method runLoadHooks
              @for Ember
              @param name {String} name of hook
              @param object {Object} object to pass to callbacks
            */
        function runLoadHooks(name, object) {
            loaded[name] = object;

            if (typeof window === 'object' && typeof window.dispatchEvent === 'function' && typeof CustomEvent === "function") {
                var event = new CustomEvent(name, {
                    detail: object,
                    name: name
                });
                window.dispatchEvent(event);
            }

            if (loadHooks[name]) {
                forEach.call(loadHooks[name], function(callback) {
                    callback(object);
                });
            }
        }

        __exports__.runLoadHooks = runLoadHooks;
    });
    define("ember-runtime/system/namespace",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/array", "ember-metal/utils", "ember-metal/mixin", "ember-runtime/system/object", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-runtime
            */

        // Ember.lookup, Ember.BOOTED, Ember.deprecate, Ember.NAME_KEY, Ember.anyUnprocessedMixins
        var Ember = __dependency1__["default"];
        var get = __dependency2__.get;
        var indexOf = __dependency3__.indexOf;
        var GUID_KEY = __dependency4__.GUID_KEY;
        var guidFor = __dependency4__.guidFor;
        var Mixin = __dependency5__.Mixin;

        var EmberObject = __dependency6__["default"];

        /**
              A Namespace is an object usually used to contain other objects or methods
              such as an application or framework. Create a namespace anytime you want
              to define one of these new containers.

              # Example Usage

              ```javascript
              MyFramework = Ember.Namespace.create({
                VERSION: '1.0.0'
              });
              ```

              @class Namespace
              @namespace Ember
              @extends Ember.Object
            */
        var Namespace = EmberObject.extend({
            isNamespace: true,

            init: function() {
                Namespace.NAMESPACES.push(this);
                Namespace.PROCESSED = false;
            },

            toString: function() {
                var name = get(this, 'name');
                if (name) {
                    return name;
                }

                findNamespaces();
                return this[NAME_KEY];
            },

            nameClasses: function() {
                processNamespace([this.toString()], this, {});
            },

            destroy: function() {
                var namespaces = Namespace.NAMESPACES,
                toString = this.toString();

                if (toString) {
                    Ember.lookup[toString] = undefined;
                    delete Namespace.NAMESPACES_BY_ID[toString];
                }
                namespaces.splice(indexOf.call(namespaces, this), 1);
                this._super();
            }
        });

        Namespace.reopenClass({
            NAMESPACES: [Ember],
            NAMESPACES_BY_ID: {},
            PROCESSED: false,
            processAll: processAllNamespaces,
            byName: function(name) {
                if (!Ember.BOOTED) {
                    processAllNamespaces();
                }

                return NAMESPACES_BY_ID[name];
            }
        });

        var NAMESPACES_BY_ID = Namespace.NAMESPACES_BY_ID;

        var hasOwnProp = ({}).hasOwnProperty;

        function processNamespace(paths, root, seen) {
            var idx = paths.length;

            NAMESPACES_BY_ID[paths.join('.')] = root;

            // Loop over all of the keys in the namespace, looking for classes
            for (var key in root) {
                if (!hasOwnProp.call(root, key)) {
                    continue;
                }
                var obj = root[key];

                // If we are processing the `Ember` namespace, for example, the
                // `paths` will start with `["Ember"]`. Every iteration through
                // the loop will update the **second** element of this list with
                // the key, so processing `Ember.View` will make the Array
                // `['Ember', 'View']`.
                paths[idx] = key;

                // If we have found an unprocessed class
                if (obj && obj.toString === classToString) {
                    // Replace the class' `toString` with the dot-separated path
                    // and set its `NAME_KEY`
                    obj.toString = makeToString(paths.join('.'));
                    obj[NAME_KEY] = paths.join('.');

                    // Support nested namespaces
                } else if (obj && obj.isNamespace) {
                    // Skip aliased namespaces
                    if (seen[guidFor(obj)]) {
                        continue;
                    }
                    seen[guidFor(obj)] = true;

                    // Process the child namespace
                    processNamespace(paths, obj, seen);
                }
            }

            paths.length = idx; // cut out last item
        }

        var STARTS_WITH_UPPERCASE = /^[A-Z]/;

        function tryIsNamespace(lookup, prop) {
            try {
                var obj = lookup[prop];
                return obj && obj.isNamespace && obj;
            } catch (e) {
                // continue
            }
        }

        function findNamespaces() {
            var lookup = Ember.lookup, obj, isNamespace;

            if (Namespace.PROCESSED) {
                return;
            }

            for (var prop in lookup) {
                // Only process entities that start with uppercase A-Z
                if (!STARTS_WITH_UPPERCASE.test(prop)) {
                    continue;
                }

                // Unfortunately, some versions of IE don't support window.hasOwnProperty
                if (lookup.hasOwnProperty && !lookup.hasOwnProperty(prop)) {
                    continue;
                }

                // At times we are not allowed to access certain properties for security reasons.
                // There are also times where even if we can access them, we are not allowed to access their properties.
                obj = tryIsNamespace(lookup, prop);
                if (obj) {
                    obj[NAME_KEY] = prop;
                }
            }
        }

        var NAME_KEY = Ember.NAME_KEY = GUID_KEY + '_name';

        function superClassString(mixin) {
            var superclass = mixin.superclass;
            if (superclass) {
                if (superclass[NAME_KEY]) {
                    return superclass[NAME_KEY];
                } else {
                    return superClassString(superclass);
                }
            } else {
                return;
            }
        }

        function classToString() {
            if (!Ember.BOOTED && !this[NAME_KEY]) {
                processAllNamespaces();
            }

            var ret;

            if (this[NAME_KEY]) {
                ret = this[NAME_KEY];
            } else if (this._toString) {
                ret = this._toString;
            } else {
                var str = superClassString(this);
                if (str) {
                    ret = "(subclass of " + str + ")";
                } else {
                    ret = "(unknown mixin)";
                }
                this.toString = makeToString(ret);
            }

            return ret;
        }

        function processAllNamespaces() {
            var unprocessedNamespaces = !Namespace.PROCESSED,
            unprocessedMixins = Ember.anyUnprocessedMixins;

            if (unprocessedNamespaces) {
                findNamespaces();
                Namespace.PROCESSED = true;
            }

            if (unprocessedNamespaces || unprocessedMixins) {
                var namespaces = Namespace.NAMESPACES, namespace;
                for (var i = 0, l = namespaces.length; i < l; i++) {
                    namespace = namespaces[i];
                    processNamespace([namespace.toString()], namespace, {});
                }

                Ember.anyUnprocessedMixins = false;
            }
        }

        function makeToString(ret) {
            return function() {
                return ret;
            };
        }

        Mixin.prototype.toString = classToString; // ES6TODO: altering imported objects. SBB.

        __exports__["default"] = Namespace;
    });
    define("ember-runtime/system/native_array",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/enumerable_utils", "ember-metal/mixin", "ember-runtime/mixins/array", "ember-runtime/mixins/mutable_array", "ember-runtime/mixins/observable", "ember-runtime/mixins/copyable", "ember-runtime/mixins/freezable", "ember-runtime/copy", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-runtime
            */

        var Ember = __dependency1__["default"];
        // Ember.EXTEND_PROTOTYPES

        var get = __dependency2__.get;
        var set = __dependency3__.set;
        var replace = __dependency4__._replace;
        var forEach = __dependency4__.forEach;
        var Mixin = __dependency5__.Mixin;
        var EmberArray = __dependency6__["default"];
        var MutableArray = __dependency7__["default"];
        var Observable = __dependency8__["default"];
        var Copyable = __dependency9__["default"];
        var FROZEN_ERROR = __dependency10__.FROZEN_ERROR;
        var copy = __dependency11__["default"];

        // Add Ember.Array to Array.prototype. Remove methods with native
        // implementations and supply some more optimized versions of generic methods
        // because they are so common.

        /**
              The NativeArray mixin contains the properties needed to to make the native
              Array support Ember.MutableArray and all of its dependent APIs. Unless you
              have `Ember.EXTEND_PROTOTYPES` or `Ember.EXTEND_PROTOTYPES.Array` set to
              false, this will be applied automatically. Otherwise you can apply the mixin
              at anytime by calling `Ember.NativeArray.activate`.

              @class NativeArray
              @namespace Ember
              @uses Ember.MutableArray
              @uses Ember.Observable
              @uses Ember.Copyable
            */
        var NativeArray = Mixin.create(MutableArray, Observable, Copyable, {

            // because length is a built-in property we need to know to just get the
            // original property.
            get: function(key) {
                if (key === 'length') 
                    return this.length;
                else if ('number' === typeof key) 
                    return this[key];
                else 
                    return this._super(key);
            },

            objectAt: function(idx) {
                return this[idx];
            },

            // primitive for array support.
            replace: function(idx, amt, objects) {

                if (this.isFrozen) 
                    throw FROZEN_ERROR;

                // if we replaced exactly the same number of items, then pass only the
                // replaced range. Otherwise, pass the full remaining array length
                // since everything has shifted
                var len = objects ? get(objects, 'length') : 0;
                this.arrayContentWillChange(idx, amt, len);

                if (len === 0) {
                    this.splice(idx, amt);
                } else {
                    replace(this, idx, amt, objects);
                }

                this.arrayContentDidChange(idx, amt, len);
                return this;
            },

            // If you ask for an unknown property, then try to collect the value
            // from member items.
            unknownProperty: function(key, value) {
                var ret; // = this.reducedProperty(key, value) ;
                if ((value !== undefined) && ret === undefined) {
                    ret = this[key] = value;
                }
                return ret ;
            },

            // If browser did not implement indexOf natively, then override with
            // specialized version
            indexOf: function(object, startAt) {
                var idx, len = this.length;

                if (startAt === undefined) 
                    startAt = 0;
                else 
                    startAt = (startAt < 0) ? Math.ceil(startAt) : Math.floor(startAt);
                if (startAt < 0) 
                    startAt += len;

                for (idx = startAt; idx < len; idx++) {
                    if (this[idx] === object) 
                        return idx ;
                }
                return -1;
            },

            lastIndexOf: function(object, startAt) {
                var idx, len = this.length;

                if (startAt === undefined) 
                    startAt = len-1;
                else 
                    startAt = (startAt < 0) ? Math.ceil(startAt) : Math.floor(startAt);
                if (startAt < 0) 
                    startAt += len;

                for (idx = startAt; idx >= 0; idx--) {
                    if (this[idx] === object) 
                        return idx ;
                }
                return -1;
            },

            copy: function(deep) {
                if (deep) {
                    return this.map(function(item) {
                        return copy(item, true);
                    });
                }

                return this.slice();
            }
        });

        // Remove any methods implemented natively so we don't override them
        var ignore = ['length'];
        forEach(NativeArray.keys(), function(methodName) {
            if (Array.prototype[methodName]) 
                ignore.push(methodName);
        });

        if (ignore.length > 0) {
            NativeArray = NativeArray.without.apply(NativeArray, ignore);
        }

        /**
              Creates an `Ember.NativeArray` from an Array like object.
              Does not modify the original object. Ember.A is not needed if
              `Ember.EXTEND_PROTOTYPES` is `true` (the default value). However,
              it is recommended that you use Ember.A when creating addons for
              ember or when you can not guarantee that `Ember.EXTEND_PROTOTYPES`
              will be `true`.

              Example

              ```js
              var Pagination = Ember.CollectionView.extend({
                tagName: 'ul',
                classNames: ['pagination'],

                init: function() {
                  this._super();
                  if (!this.get('content')) {
                    this.set('content', Ember.A());
                  }
                }
              });
              ```

              @method A
              @for Ember
              @return {Ember.NativeArray}
            */
        var A = function(arr) {
            if (arr === undefined) {
                arr = [];
            }
            return EmberArray.detect(arr) ? arr : NativeArray.apply(arr);
        };

        /**
              Activates the mixin on the Array.prototype if not already applied. Calling
              this method more than once is safe. This will be called when ember is loaded
              unless you have `Ember.EXTEND_PROTOTYPES` or `Ember.EXTEND_PROTOTYPES.Array`
              set to `false`.

              Example

              ```js
              if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Array) {
                Ember.NativeArray.activate();
              }
              ```

              @method activate
              @for Ember.NativeArray
              @static
              @return {void}
            */
        NativeArray.activate = function() {
            NativeArray.apply(Array.prototype);

            A = function(arr) {
                return arr || [];
            };
        };

        if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Array) {
            NativeArray.activate();
        }

        Ember.A = A; // ES6TODO: Setting A onto the object returned by ember-metal/core to avoid circles
        __exports__.A = A;
        __exports__.NativeArray = NativeArray;
        __exports__["default"] = NativeArray;
    });
    define("ember-runtime/system/object",
    ["ember-runtime/system/core_object", "ember-runtime/mixins/observable", "exports"],
    function(__dependency1__, __dependency2__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-runtime
            */

        var CoreObject = __dependency1__["default"];
        var Observable = __dependency2__["default"];

        /**
              `Ember.Object` is the main base class for all Ember objects. It is a subclass
              of `Ember.CoreObject` with the `Ember.Observable` mixin applied. For details,
              see the documentation for each of these.

              @class Object
              @namespace Ember
              @extends Ember.CoreObject
              @uses Ember.Observable
            */
        var EmberObject = CoreObject.extend(Observable);
        EmberObject.toString = function() {
            return "Ember.Object";
        };

        __exports__["default"] = EmberObject;
    });
    define("ember-runtime/system/object_proxy",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/utils", "ember-metal/observer", "ember-metal/property_events", "ember-metal/computed", "ember-metal/properties", "ember-metal/mixin", "ember-runtime/system/string", "ember-runtime/system/object", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-runtime
            */
        var Ember = __dependency1__["default"];
        // Ember.assert
        var get = __dependency2__.get;
        var set = __dependency3__.set;
        var meta = __dependency4__.meta;
        var addObserver = __dependency5__.addObserver;
        var removeObserver = __dependency5__.removeObserver;
        var addBeforeObserver = __dependency5__.addBeforeObserver;
        var removeBeforeObserver = __dependency5__.removeBeforeObserver;
        var propertyWillChange = __dependency6__.propertyWillChange;
        var propertyDidChange = __dependency6__.propertyDidChange;
        var computed = __dependency7__.computed;
        var defineProperty = __dependency8__.defineProperty;
        var observer = __dependency9__.observer;
        var fmt = __dependency10__.fmt;
        var EmberObject = __dependency11__["default"];

        function contentPropertyWillChange(content, contentKey) {
            var key = contentKey.slice(8); // remove "content."
            if (key in this) {
                return;
            }
            // if shadowed in proxy
            propertyWillChange(this, key);
        }

        function contentPropertyDidChange(content, contentKey) {
            var key = contentKey.slice(8); // remove "content."
            if (key in this) {
                return;
            }
            // if shadowed in proxy
            propertyDidChange(this, key);
        }

        /**
              `Ember.ObjectProxy` forwards all properties not defined by the proxy itself
              to a proxied `content` object.

              ```javascript
              object = Ember.Object.create({
                name: 'Foo'
              });

              proxy = Ember.ObjectProxy.create({
                content: object
              });

              // Access and change existing properties
              proxy.get('name')          // 'Foo'
              proxy.set('name', 'Bar');
              object.get('name')         // 'Bar'

              // Create new 'description' property on `object`
              proxy.set('description', 'Foo is a whizboo baz');
              object.get('description')  // 'Foo is a whizboo baz'
              ```

              While `content` is unset, setting a property to be delegated will throw an
              Error.

              ```javascript
              proxy = Ember.ObjectProxy.create({
                content: null,
                flag: null
              });
              proxy.set('flag', true);
              proxy.get('flag');         // true
              proxy.get('foo');          // undefined
              proxy.set('foo', 'data');  // throws Error
              ```

              Delegated properties can be bound to and will change when content is updated.

              Computed properties on the proxy itself can depend on delegated properties.

              ```javascript
              ProxyWithComputedProperty = Ember.ObjectProxy.extend({
                fullName: function () {
                  var firstName = this.get('firstName'),
                      lastName = this.get('lastName');
                  if (firstName && lastName) {
                    return firstName + ' ' + lastName;
                  }
                  return firstName || lastName;
                }.property('firstName', 'lastName')
              });

              proxy = ProxyWithComputedProperty.create();

              proxy.get('fullName');  // undefined
              proxy.set('content', {
                firstName: 'Tom', lastName: 'Dale'
              }); // triggers property change for fullName on proxy

              proxy.get('fullName');  // 'Tom Dale'
              ```

              @class ObjectProxy
              @namespace Ember
              @extends Ember.Object
            */
        var ObjectProxy = EmberObject.extend({
            /**
                    The object whose properties will be forwarded.

                    @property content
                    @type Ember.Object
                    @default null
                  */
            content: null,
            _contentDidChange: observer('content', function() {
                Ember.assert("Can't set ObjectProxy's content to itself", get(this, 'content') !== this);
            }),

            isTruthy: computed.bool('content'),

            _debugContainerKey: null,

            willWatchProperty: function (key) {
                var contentKey = 'content.' + key;
                addBeforeObserver(this, contentKey, null, contentPropertyWillChange);
                addObserver(this, contentKey, null, contentPropertyDidChange);
            },

            didUnwatchProperty: function (key) {
                var contentKey = 'content.' + key;
                removeBeforeObserver(this, contentKey, null, contentPropertyWillChange);
                removeObserver(this, contentKey, null, contentPropertyDidChange);
            },

            unknownProperty: function (key) {
                var content = get(this, 'content');
                if (content) {
                    return get(content, key);
                }
            },

            setUnknownProperty: function (key, value) {
                var m = meta(this);
                if (m.proto === this) {
                    // if marked as prototype then just defineProperty
                    // rather than delegate
                    defineProperty(this, key, null, value);
                    return value;
                }

                var content = get(this, 'content');
                Ember.assert(fmt("Cannot delegate set('%@', %@) to the 'content' property of object proxy %@: its 'content' is undefined.", [key, value, this]), content);
                return set(content, key, value);
            }

        });

        __exports__["default"] = ObjectProxy;
    });
    define("ember-runtime/system/set",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/utils", "ember-metal/is_none", "ember-runtime/system/string", "ember-runtime/system/core_object", "ember-runtime/mixins/mutable_enumerable", "ember-runtime/mixins/enumerable", "ember-runtime/mixins/copyable", "ember-runtime/mixins/freezable", "ember-metal/error", "ember-metal/property_events", "ember-metal/mixin", "ember-metal/computed", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-runtime
            */
        var Ember = __dependency1__["default"];
        // Ember.isNone

        var get = __dependency2__.get;
        var set = __dependency3__.set;
        var guidFor = __dependency4__.guidFor;
        var isNone = __dependency5__.isNone;
        var fmt = __dependency6__.fmt;
        var CoreObject = __dependency7__["default"];
        var MutableEnumerable = __dependency8__["default"];
        var Enumerable = __dependency9__["default"];
        var Copyable = __dependency10__["default"];
        var Freezable = __dependency11__.Freezable;
        var FROZEN_ERROR = __dependency11__.FROZEN_ERROR;
        var EmberError = __dependency12__["default"];
        var propertyWillChange = __dependency13__.propertyWillChange;
        var propertyDidChange = __dependency13__.propertyDidChange;
        var aliasMethod = __dependency14__.aliasMethod;
        var computed = __dependency15__.computed;

        /**
              An unordered collection of objects.

              A Set works a bit like an array except that its items are not ordered. You
              can create a set to efficiently test for membership for an object. You can
              also iterate through a set just like an array, even accessing objects by
              index, however there is no guarantee as to their order.

              All Sets are observable via the Enumerable Observer API - which works
              on any enumerable object including both Sets and Arrays.

              ## Creating a Set

              You can create a set like you would most objects using
              `new Ember.Set()`. Most new sets you create will be empty, but you can
              also initialize the set with some content by passing an array or other
              enumerable of objects to the constructor.

              Finally, you can pass in an existing set and the set will be copied. You
              can also create a copy of a set by calling `Ember.Set#copy()`.

              ```javascript
              // creates a new empty set
              var foundNames = new Ember.Set();

              // creates a set with four names in it.
              var names = new Ember.Set(["Charles", "Tom", "Juan", "Alex"]); // :P

              // creates a copy of the names set.
              var namesCopy = new Ember.Set(names);

              // same as above.
              var anotherNamesCopy = names.copy();
              ```

              ## Adding/Removing Objects

              You generally add or remove objects from a set using `add()` or
              `remove()`. You can add any type of object including primitives such as
              numbers, strings, and booleans.

              Unlike arrays, objects can only exist one time in a set. If you call `add()`
              on a set with the same object multiple times, the object will only be added
              once. Likewise, calling `remove()` with the same object multiple times will
              remove the object the first time and have no effect on future calls until
              you add the object to the set again.

              NOTE: You cannot add/remove `null` or `undefined` to a set. Any attempt to do
              so will be ignored.

              In addition to add/remove you can also call `push()`/`pop()`. Push behaves
              just like `add()` but `pop()`, unlike `remove()` will pick an arbitrary
              object, remove it and return it. This is a good way to use a set as a job
              queue when you don't care which order the jobs are executed in.

              ## Testing for an Object

              To test for an object's presence in a set you simply call
              `Ember.Set#contains()`.

              ## Observing changes

              When using `Ember.Set`, you can observe the `"[]"` property to be
              alerted whenever the content changes. You can also add an enumerable
              observer to the set to be notified of specific objects that are added and
              removed from the set. See [Ember.Enumerable](/api/classes/Ember.Enumerable.html)
              for more information on enumerables.

              This is often unhelpful. If you are filtering sets of objects, for instance,
              it is very inefficient to re-filter all of the items each time the set
              changes. It would be better if you could just adjust the filtered set based
              on what was changed on the original set. The same issue applies to merging
              sets, as well.

              ## Other Methods

              `Ember.Set` primary implements other mixin APIs. For a complete reference
              on the methods you will use with `Ember.Set`, please consult these mixins.
              The most useful ones will be `Ember.Enumerable` and
              `Ember.MutableEnumerable` which implement most of the common iterator
              methods you are used to on Array.

              Note that you can also use the `Ember.Copyable` and `Ember.Freezable`
              APIs on `Ember.Set` as well. Once a set is frozen it can no longer be
              modified. The benefit of this is that when you call `frozenCopy()` on it,
              Ember will avoid making copies of the set. This allows you to write
              code that can know with certainty when the underlying set data will or
              will not be modified.

              @class Set
              @namespace Ember
              @extends Ember.CoreObject
              @uses Ember.MutableEnumerable
              @uses Ember.Copyable
              @uses Ember.Freezable
              @since Ember 0.9
            */
        __exports__["default"] = CoreObject.extend(MutableEnumerable, Copyable, Freezable, {

            // ..........................................................
            // IMPLEMENT ENUMERABLE APIS
            //

            /**
                    This property will change as the number of objects in the set changes.

                    @property length
                    @type number
                    @default 0
                  */
            length: 0,

            /**
                    Clears the set. This is useful if you want to reuse an existing set
                    without having to recreate it.

                    ```javascript
                    var colors = new Ember.Set(["red", "green", "blue"]);
                    colors.length;  // 3
                    colors.clear();
                    colors.length;  // 0
                    ```

                    @method clear
                    @return {Ember.Set} An empty Set
                  */
            clear: function() {
                if (this.isFrozen) {
                    throw new EmberError(FROZEN_ERROR);
                }

                var len = get(this, 'length');
                if (len === 0) {
                    return this;
                }

                var guid;

                this.enumerableContentWillChange(len, 0);
                propertyWillChange(this, 'firstObject');
                propertyWillChange(this, 'lastObject');

                for (var i = 0; i < len; i++) {
                    guid = guidFor(this[i]);
                    delete this[guid];
                    delete this[i];
                }

                set(this, 'length', 0);

                propertyDidChange(this, 'firstObject');
                propertyDidChange(this, 'lastObject');
                this.enumerableContentDidChange(len, 0);

                return this;
            },

            /**
                    Returns true if the passed object is also an enumerable that contains the
                    same objects as the receiver.

                    ```javascript
                    var colors = ["red", "green", "blue"],
                        same_colors = new Ember.Set(colors);

                    same_colors.isEqual(colors);               // true
                    same_colors.isEqual(["purple", "brown"]);  // false
                    ```

                    @method isEqual
                    @param {Ember.Set} obj the other object.
                    @return {Boolean}
                  */
            isEqual: function(obj) {
                // fail fast
                if (!Enumerable.detect(obj)) 
                    return false;

                var loc = get(this, 'length');
                if (get(obj, 'length') !== loc) 
                    return false;

                while (--loc >= 0) {
                    if (!obj.contains(this[loc])) 
                        return false;
                }

                return true;
            },

            /**
                    Adds an object to the set. Only non-`null` objects can be added to a set
                    and those can only be added once. If the object is already in the set or
                    the passed value is null this method will have no effect.

                    This is an alias for `Ember.MutableEnumerable.addObject()`.

                    ```javascript
                    var colors = new Ember.Set();
                    colors.add("blue");     // ["blue"]
                    colors.add("blue");     // ["blue"]
                    colors.add("red");      // ["blue", "red"]
                    colors.add(null);       // ["blue", "red"]
                    colors.add(undefined);  // ["blue", "red"]
                    ```

                    @method add
                    @param {Object} obj The object to add.
                    @return {Ember.Set} The set itself.
                  */
            add: aliasMethod('addObject'),

            /**
                    Removes the object from the set if it is found. If you pass a `null` value
                    or an object that is already not in the set, this method will have no
                    effect. This is an alias for `Ember.MutableEnumerable.removeObject()`.

                    ```javascript
                    var colors = new Ember.Set(["red", "green", "blue"]);
                    colors.remove("red");     // ["blue", "green"]
                    colors.remove("purple");  // ["blue", "green"]
                    colors.remove(null);      // ["blue", "green"]
                    ```

                    @method remove
                    @param {Object} obj The object to remove
                    @return {Ember.Set} The set itself.
                  */
            remove: aliasMethod('removeObject'),

            /**
                    Removes the last element from the set and returns it, or `null` if it's empty.

                    ```javascript
                    var colors = new Ember.Set(["green", "blue"]);
                    colors.pop();  // "blue"
                    colors.pop();  // "green"
                    colors.pop();  // null
                    ```

                    @method pop
                    @return {Object} The removed object from the set or null.
                  */
            pop: function() {
                if (get(this, 'isFrozen')) 
                    throw new EmberError(FROZEN_ERROR);
                var obj = this.length > 0 ? this[this.length-1] : null;
                this.remove(obj);
                return obj;
            },

            /**
                    Inserts the given object on to the end of the set. It returns
                    the set itself.

                    This is an alias for `Ember.MutableEnumerable.addObject()`.

                    ```javascript
                    var colors = new Ember.Set();
                    colors.push("red");   // ["red"]
                    colors.push("green"); // ["red", "green"]
                    colors.push("blue");  // ["red", "green", "blue"]
                    ```

                    @method push
                    @return {Ember.Set} The set itself.
                  */
            push: aliasMethod('addObject'),

            /**
                    Removes the last element from the set and returns it, or `null` if it's empty.

                    This is an alias for `Ember.Set.pop()`.

                    ```javascript
                    var colors = new Ember.Set(["green", "blue"]);
                    colors.shift();  // "blue"
                    colors.shift();  // "green"
                    colors.shift();  // null
                    ```

                    @method shift
                    @return {Object} The removed object from the set or null.
                  */
            shift: aliasMethod('pop'),

            /**
                    Inserts the given object on to the end of the set. It returns
                    the set itself.

                    This is an alias of `Ember.Set.push()`

                    ```javascript
                    var colors = new Ember.Set();
                    colors.unshift("red");    // ["red"]
                    colors.unshift("green");  // ["red", "green"]
                    colors.unshift("blue");   // ["red", "green", "blue"]
                    ```

                    @method unshift
                    @return {Ember.Set} The set itself.
                  */
            unshift: aliasMethod('push'),

            /**
                    Adds each object in the passed enumerable to the set.

                    This is an alias of `Ember.MutableEnumerable.addObjects()`

                    ```javascript
                    var colors = new Ember.Set();
                    colors.addEach(["red", "green", "blue"]);  // ["red", "green", "blue"]
                    ```

                    @method addEach
                    @param {Ember.Enumerable} objects the objects to add.
                    @return {Ember.Set} The set itself.
                  */
            addEach: aliasMethod('addObjects'),

            /**
                    Removes each object in the passed enumerable to the set.

                    This is an alias of `Ember.MutableEnumerable.removeObjects()`

                    ```javascript
                    var colors = new Ember.Set(["red", "green", "blue"]);
                    colors.removeEach(["red", "blue"]);  //  ["green"]
                    ```

                    @method removeEach
                    @param {Ember.Enumerable} objects the objects to remove.
                    @return {Ember.Set} The set itself.
                  */
            removeEach: aliasMethod('removeObjects'),

            // ..........................................................
            // PRIVATE ENUMERABLE SUPPORT
            //

            init: function(items) {
                this._super();
                if (items) 
                    this.addObjects(items);
            },

            // implement Ember.Enumerable
            nextObject: function(idx) {
                return this[idx];
            },

            // more optimized version
            firstObject: computed(function() {
                return this.length > 0 ? this[0] : undefined;
            }),

            // more optimized version
            lastObject: computed(function() {
                return this.length > 0 ? this[this.length-1] : undefined;
            }),

            // implements Ember.MutableEnumerable
            addObject: function(obj) {
                if (get(this, 'isFrozen')) 
                    throw new EmberError(FROZEN_ERROR);
                if (isNone(obj)) 
                    return this; // nothing to do

                var guid = guidFor(obj),
                idx = this[guid],
                len = get(this, 'length'),
                added ;

                if (idx >= 0 && idx < len && (this[idx] === obj)) 
                    return this; // added

                added = [obj];

                this.enumerableContentWillChange(null, added);
                propertyWillChange(this, 'lastObject');

                len = get(this, 'length');
                this[guid] = len;
                this[len] = obj;
                set(this, 'length', len + 1);

                propertyDidChange(this, 'lastObject');
                this.enumerableContentDidChange(null, added);

                return this;
            },

            // implements Ember.MutableEnumerable
            removeObject: function(obj) {
                if (get(this, 'isFrozen')) 
                    throw new EmberError(FROZEN_ERROR);
                if (isNone(obj)) 
                    return this; // nothing to do

                var guid = guidFor(obj),
                idx = this[guid],
                len = get(this, 'length'),
                isFirst = idx === 0,
                isLast = idx === len-1,
                last, removed;


                if (idx >= 0 && idx < len && (this[idx] === obj)) {
                    removed = [obj];

                    this.enumerableContentWillChange(removed, null);
                    if (isFirst) {
                        propertyWillChange(this, 'firstObject');
                    }
                    if (isLast) {
                        propertyWillChange(this, 'lastObject');
                    }

                    // swap items - basically move the item to the end so it can be removed
                    if (idx < len-1) {
                        last = this[len-1];
                        this[idx] = last;
                        this[guidFor(last)] = idx;
                    }

                    delete this[guid];
                    delete this[len-1];
                    set(this, 'length', len-1);

                    if (isFirst) {
                        propertyDidChange(this, 'firstObject');
                    }
                    if (isLast) {
                        propertyDidChange(this, 'lastObject');
                    }
                    this.enumerableContentDidChange(removed, null);
                }

                return this;
            },

            // optimized version
            contains: function(obj) {
                return this[guidFor(obj)] >= 0;
            },

            copy: function() {
                var C = this.constructor, ret = new C(), loc = get(this, 'length');
                set(ret, 'length', loc);
                while (--loc >= 0) {
                    ret[loc] = this[loc];
                    ret[guidFor(this[loc])] = loc;
                }
                return ret;
            },

            toString: function() {
                var len = this.length, idx, array = [];
                for (idx = 0; idx < len; idx++) {
                    array[idx] = this[idx];
                }
                return fmt("Ember.Set<%@>", [array.join(',')]);
            }
        });
    });
    define("ember-runtime/system/string",
    ["ember-metal/core", "ember-metal/utils", "exports"],
    function(__dependency1__, __dependency2__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-runtime
            */
        var Ember = __dependency1__["default"];
        // Ember.STRINGS, Ember.FEATURES
        var isArray = __dependency2__.isArray;
        var emberInspect = __dependency2__.inspect;

        var STRING_DASHERIZE_REGEXP = (/[ _]/g);
        var STRING_DASHERIZE_CACHE = {};
        var STRING_DECAMELIZE_REGEXP = (/([a-z\d])([A-Z])/g);
        var STRING_CAMELIZE_REGEXP = (/(\-|_|\.|\s)+(.)?/g);
        var STRING_UNDERSCORE_REGEXP_1 = (/([a-z\d])([A-Z]+)/g);
        var STRING_UNDERSCORE_REGEXP_2 = (/\-|\s+/g);

        function fmt(str, formats) {
            if (!isArray(formats) || arguments.length > 2) {
                formats = Array.prototype.slice.call(arguments, 1);
            }

            // first, replace any ORDERED replacements.
            var idx = 0; // the current index for non-numerical replacements
            return str.replace(/%@([0-9]+)?/g, function(s, argIndex) {
                argIndex = (argIndex) ? parseInt(argIndex, 10) - 1 : idx++;
                s = formats[argIndex];
                return (s === null) ? '(null)' : (s === undefined) ? '' : emberInspect(s);
            });
        }

        function loc(str, formats) {
            if (!isArray(formats) || arguments.length > 2) {
                formats = Array.prototype.slice.call(arguments, 1);
            }

            str = Ember.STRINGS[str] || str;
            return fmt(str, formats);
        }

        function w(str) {
            return str.split(/\s+/);
        }

        function decamelize(str) {
            return str.replace(STRING_DECAMELIZE_REGEXP, '$1_$2').toLowerCase();
        }

        function dasherize(str) {
            var cache = STRING_DASHERIZE_CACHE,
            hit = cache.hasOwnProperty(str),
            ret;

            if (hit) {
                return cache[str];
            } else {
                ret = decamelize(str).replace(STRING_DASHERIZE_REGEXP, '-');
                cache[str] = ret;
            }

            return ret;
        }

        function camelize(str) {
            return str.replace(STRING_CAMELIZE_REGEXP, function(match, separator, chr) {
                return chr ? chr.toUpperCase() : '';
            }).replace(/^([A-Z])/, function(match, separator, chr) {
                return match.toLowerCase();
            });
        }

        function classify(str) {
            var parts = str.split("."),
            out = [];

            for (var i = 0, l = parts.length; i < l; i++) {
                var camelized = camelize(parts[i]);
                out.push(camelized.charAt(0).toUpperCase() + camelized.substr(1));
            }

            return out.join(".");
        }

        function underscore(str) {
            return str.replace(STRING_UNDERSCORE_REGEXP_1, '$1_$2').
            replace(STRING_UNDERSCORE_REGEXP_2, '_').toLowerCase();
        }

        function capitalize(str) {
            return str.charAt(0).toUpperCase() + str.substr(1);
        }

        /**
              Defines the hash of localized strings for the current language. Used by
              the `Ember.String.loc()` helper. To localize, add string values to this
              hash.

              @property STRINGS
              @for Ember
              @type Hash
            */
        Ember.STRINGS = {};

        /**
              Defines string helper methods including string formatting and localization.
              Unless `Ember.EXTEND_PROTOTYPES.String` is `false` these methods will also be
              added to the `String.prototype` as well.

              @class String
              @namespace Ember
              @static
            */
        __exports__["default"] = {
            /**
                    Apply formatting options to the string. This will look for occurrences
                    of "%@" in your string and substitute them with the arguments you pass into
                    this method. If you want to control the specific order of replacement,
                    you can add a number after the key as well to indicate which argument
                    you want to insert.

                    Ordered insertions are most useful when building loc strings where values
                    you need to insert may appear in different orders.

                    ```javascript
                    "Hello %@ %@".fmt('John', 'Doe');     // "Hello John Doe"
                    "Hello %@2, %@1".fmt('John', 'Doe');  // "Hello Doe, John"
                    ```

                    @method fmt
                    @param {String} str The string to format
                    @param {Array} formats An array of parameters to interpolate into string.
                    @return {String} formatted string
                  */
            fmt: fmt,

            /**
                    Formats the passed string, but first looks up the string in the localized
                    strings hash. This is a convenient way to localize text. See
                    `Ember.String.fmt()` for more information on formatting.

                    Note that it is traditional but not required to prefix localized string
                    keys with an underscore or other character so you can easily identify
                    localized strings.

                    ```javascript
                    Ember.STRINGS = {
                      '_Hello World': 'Bonjour le monde',
                      '_Hello %@ %@': 'Bonjour %@ %@'
                    };

                    Ember.String.loc("_Hello World");  // 'Bonjour le monde';
                    Ember.String.loc("_Hello %@ %@", ["John", "Smith"]);  // "Bonjour John Smith";
                    ```

                    @method loc
                    @param {String} str The string to format
                    @param {Array} formats Optional array of parameters to interpolate into string.
                    @return {String} formatted string
                  */
            loc: loc,

            /**
                    Splits a string into separate units separated by spaces, eliminating any
                    empty strings in the process. This is a convenience method for split that
                    is mostly useful when applied to the `String.prototype`.

                    ```javascript
                    Ember.String.w("alpha beta gamma").forEach(function(key) {
                      console.log(key);
                    });

                    // > alpha
                    // > beta
                    // > gamma
                    ```

                    @method w
                    @param {String} str The string to split
                    @return {Array} array containing the split strings
                  */
            w: w,

            /**
                    Converts a camelized string into all lower case separated by underscores.

                    ```javascript
                    'innerHTML'.decamelize();           // 'inner_html'
                    'action_name'.decamelize();        // 'action_name'
                    'css-class-name'.decamelize();     // 'css-class-name'
                    'my favorite items'.decamelize();  // 'my favorite items'
                    ```

                    @method decamelize
                    @param {String} str The string to decamelize.
                    @return {String} the decamelized string.
                  */
            decamelize: decamelize,

            /**
                    Replaces underscores, spaces, or camelCase with dashes.

                    ```javascript
                    'innerHTML'.dasherize();          // 'inner-html'
                    'action_name'.dasherize();        // 'action-name'
                    'css-class-name'.dasherize();     // 'css-class-name'
                    'my favorite items'.dasherize();  // 'my-favorite-items'
                    ```

                    @method dasherize
                    @param {String} str The string to dasherize.
                    @return {String} the dasherized string.
                  */
            dasherize: dasherize,

            /**
                    Returns the lowerCamelCase form of a string.

                    ```javascript
                    'innerHTML'.camelize();          // 'innerHTML'
                    'action_name'.camelize();        // 'actionName'
                    'css-class-name'.camelize();     // 'cssClassName'
                    'my favorite items'.camelize();  // 'myFavoriteItems'
                    'My Favorite Items'.camelize();  // 'myFavoriteItems'
                    ```

                    @method camelize
                    @param {String} str The string to camelize.
                    @return {String} the camelized string.
                  */
            camelize: camelize,

            /**
                    Returns the UpperCamelCase form of a string.

                    ```javascript
                    'innerHTML'.classify();          // 'InnerHTML'
                    'action_name'.classify();        // 'ActionName'
                    'css-class-name'.classify();     // 'CssClassName'
                    'my favorite items'.classify();  // 'MyFavoriteItems'
                    ```

                    @method classify
                    @param {String} str the string to classify
                    @return {String} the classified string
                  */
            classify: classify,

            /**
                    More general than decamelize. Returns the lower\_case\_and\_underscored
                    form of a string.

                    ```javascript
                    'innerHTML'.underscore();          // 'inner_html'
                    'action_name'.underscore();        // 'action_name'
                    'css-class-name'.underscore();     // 'css_class_name'
                    'my favorite items'.underscore();  // 'my_favorite_items'
                    ```

                    @method underscore
                    @param {String} str The string to underscore.
                    @return {String} the underscored string.
                  */
            underscore: underscore,

            /**
                    Returns the Capitalized form of a string

                    ```javascript
                    'innerHTML'.capitalize()         // 'InnerHTML'
                    'action_name'.capitalize()       // 'Action_name'
                    'css-class-name'.capitalize()    // 'Css-class-name'
                    'my favorite items'.capitalize() // 'My favorite items'
                    ```

                    @method capitalize
                    @param {String} str The string to capitalize.
                    @return {String} The capitalized string.
                  */
            capitalize: capitalize
        };

        __exports__.fmt = fmt;
        __exports__.loc = loc;
        __exports__.w = w;
        __exports__.decamelize = decamelize;
        __exports__.dasherize = dasherize;
        __exports__.camelize = camelize;
        __exports__.classify = classify;
        __exports__.underscore = underscore;
        __exports__.capitalize = capitalize;
    });
    define("ember-runtime/system/subarray",
    ["ember-metal/property_get", "ember-metal/error", "ember-metal/enumerable_utils", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        var get = __dependency1__.get;
        var EmberError = __dependency2__["default"];
        var EnumerableUtils = __dependency3__["default"];

        var RETAIN = 'r';
        var FILTER = 'f';

        function Operation(type, count) {
            this.type = type;
            this.count = count;
        }

        __exports__["default"] = SubArray;

        /**
              An `Ember.SubArray` tracks an array in a way similar to, but more specialized
              than, `Ember.TrackedArray`.  It is useful for keeping track of the indexes of
              items within a filtered array.

              @class SubArray
              @namespace Ember
            */
        function SubArray (length) {
            if (arguments.length < 1) {
                length = 0;
            }

            if (length > 0) {
                this._operations = [new Operation(RETAIN, length)];
            } else {
                this._operations = [];
            }
        }


        SubArray.prototype = {
            /**
                    Track that an item was added to the tracked array.

                    @method addItem

                    @param {number} index The index of the item in the tracked array.
                    @param {boolean} match `true` iff the item is included in the subarray.

                    @return {number} The index of the item in the subarray.
                  */
            addItem: function(index, match) {
                var returnValue = -1,
                itemType = match ? RETAIN : FILTER,
                self = this;

                this._findOperation(index, function(operation, operationIndex, rangeStart, rangeEnd, seenInSubArray) {
                    var newOperation, splitOperation;

                    if (itemType === operation.type) {
                        ++operation.count;
                    } else if (index === rangeStart) {
                        // insert to the left of `operation`
                        self._operations.splice(operationIndex, 0, new Operation(itemType, 1));
                    } else {
                        newOperation = new Operation(itemType, 1);
                        splitOperation = new Operation(operation.type, rangeEnd - index + 1);
                        operation.count = index - rangeStart;

                        self._operations.splice(operationIndex + 1, 0, newOperation, splitOperation);
                    }

                    if (match) {
                        if (operation.type === RETAIN) {
                            returnValue = seenInSubArray + (index - rangeStart);
                        } else {
                            returnValue = seenInSubArray;
                        }
                    }

                    self._composeAt(operationIndex);
                }, function(seenInSubArray) {
                    self._operations.push(new Operation(itemType, 1));

                    if (match) {
                        returnValue = seenInSubArray;
                    }

                    self._composeAt(self._operations.length-1);
                });

                return returnValue;
            },

            /**
                    Track that an item was removed from the tracked array.

                    @method removeItem

                    @param {number} index The index of the item in the tracked array.

                    @return {number} The index of the item in the subarray, or `-1` if the item
                    was not in the subarray.
                  */
            removeItem: function(index) {
                var returnValue = -1,
                self = this;

                this._findOperation(index, function (operation, operationIndex, rangeStart, rangeEnd, seenInSubArray) {
                    if (operation.type === RETAIN) {
                        returnValue = seenInSubArray + (index - rangeStart);
                    }

                    if (operation.count > 1) {
                        --operation.count;
                    } else {
                        self._operations.splice(operationIndex, 1);
                        self._composeAt(operationIndex);
                    }
                }, function() {
                    throw new EmberError("Can't remove an item that has never been added.");
                });

                return returnValue;
            },


            _findOperation: function (index, foundCallback, notFoundCallback) {
                var operationIndex,
                len,
                operation,
                rangeStart,
                rangeEnd,
                seenInSubArray = 0;

                // OPTIMIZE: change to balanced tree
                // find leftmost operation to the right of `index`
                for (operationIndex = rangeStart = 0, len = this._operations.length; operationIndex < len; rangeStart = rangeEnd + 1, ++operationIndex) {
                    operation = this._operations[operationIndex];
                    rangeEnd = rangeStart + operation.count - 1;

                    if (index >= rangeStart && index <= rangeEnd) {
                        foundCallback(operation, operationIndex, rangeStart, rangeEnd, seenInSubArray);
                        return;
                    } else if (operation.type === RETAIN) {
                        seenInSubArray += operation.count;
                    }
                }

                notFoundCallback(seenInSubArray);
            },

            _composeAt: function(index) {
                var op = this._operations[index],
                otherOp;

                if (!op) {
                    // Composing out of bounds is a no-op, as when removing the last operation
                    // in the list.
                    return;
                }

                if (index > 0) {
                    otherOp = this._operations[index-1];
                    if (otherOp.type === op.type) {
                        op.count += otherOp.count;
                        this._operations.splice(index-1, 1);
                        --index;
                    }
                }

                if (index < this._operations.length-1) {
                    otherOp = this._operations[index + 1];
                    if (otherOp.type === op.type) {
                        op.count += otherOp.count;
                        this._operations.splice(index + 1, 1);
                    }
                }
            },

            toString: function () {
                var str = "";
                EnumerableUtils.forEach(this._operations, function (operation) {
                    str += " " + operation.type + ":" + operation.count;
                });
                return str.substring(1);
            }
        };
    });
    define("ember-runtime/system/tracked_array",
    ["ember-metal/property_get", "ember-metal/enumerable_utils", "exports"],
    function(__dependency1__, __dependency2__, __exports__) {
        "use strict";
        var get = __dependency1__.get;
        var forEach = __dependency2__.forEach;

        var RETAIN = 'r';
        var INSERT = 'i';
        var DELETE = 'd';

        __exports__["default"] = TrackedArray;

        /**
              An `Ember.TrackedArray` tracks array operations.  It's useful when you want to
              lazily compute the indexes of items in an array after they've been shifted by
              subsequent operations.

              @class TrackedArray
              @namespace Ember
              @param {array} [items=[]] The array to be tracked.  This is used just to get
              the initial items for the starting state of retain:n.
            */
        function TrackedArray(items) {
            if (arguments.length < 1) {
                items = [];
            }

            var length = get(items, 'length');

            if (length) {
                this._operations = [new ArrayOperation(RETAIN, length, items)];
            } else {
                this._operations = [];
            }
        }

        TrackedArray.RETAIN = RETAIN;
        TrackedArray.INSERT = INSERT;
        TrackedArray.DELETE = DELETE;

        TrackedArray.prototype = {

            /**
                    Track that `newItems` were added to the tracked array at `index`.

                    @method addItems
                    @param index
                    @param newItems
                  */
            addItems: function (index, newItems) {
                var count = get(newItems, 'length');
                if (count < 1) {
                    return;
                }

                var match = this._findArrayOperation(index),
                arrayOperation = match.operation,
                arrayOperationIndex = match.index,
                arrayOperationRangeStart = match.rangeStart,
                composeIndex,
                splitIndex,
                splitItems,
                splitArrayOperation,
                newArrayOperation;

                newArrayOperation = new ArrayOperation(INSERT, count, newItems);

                if (arrayOperation) {
                    if (!match.split) {
                        // insert left of arrayOperation
                        this._operations.splice(arrayOperationIndex, 0, newArrayOperation);
                        composeIndex = arrayOperationIndex;
                    } else {
                        this._split(arrayOperationIndex, index - arrayOperationRangeStart, newArrayOperation);
                        composeIndex = arrayOperationIndex + 1;
                    }
                } else {
                    // insert at end
                    this._operations.push(newArrayOperation);
                    composeIndex = arrayOperationIndex;
                }

                this._composeInsert(composeIndex);
            },

            /**
                    Track that `count` items were removed at `index`.

                    @method removeItems
                    @param index
                    @param count
                  */
            removeItems: function (index, count) {
                if (count < 1) {
                    return;
                }

                var match = this._findArrayOperation(index),
                arrayOperation = match.operation,
                arrayOperationIndex = match.index,
                arrayOperationRangeStart = match.rangeStart,
                newArrayOperation,
                composeIndex;

                newArrayOperation = new ArrayOperation(DELETE, count);
                if (!match.split) {
                    // insert left of arrayOperation
                    this._operations.splice(arrayOperationIndex, 0, newArrayOperation);
                    composeIndex = arrayOperationIndex;
                } else {
                    this._split(arrayOperationIndex, index - arrayOperationRangeStart, newArrayOperation);
                    composeIndex = arrayOperationIndex + 1;
                }

                return this._composeDelete(composeIndex);
            },

            /**
                    Apply all operations, reducing them to retain:n, for `n`, the number of
                    items in the array.

                    `callback` will be called for each operation and will be passed the following arguments:

                    * {array} items The items for the given operation
                    * {number} offset The computed offset of the items, ie the index in the
                    array of the first item for this operation.
                    * {string} operation The type of the operation.  One of
                    `Ember.TrackedArray.{RETAIN, DELETE, INSERT}`

                    @method apply
                    @param {function} callback
                  */
            apply: function (callback) {
                var items = [],
                offset = 0;

                forEach(this._operations, function (arrayOperation, operationIndex) {
                    callback(arrayOperation.items, offset, arrayOperation.type, operationIndex);

                    if (arrayOperation.type !== DELETE) {
                        offset += arrayOperation.count;
                        items = items.concat(arrayOperation.items);
                    }
                });

                this._operations = [new ArrayOperation(RETAIN, items.length, items)];
            },

            /**
                    Return an `ArrayOperationMatch` for the operation that contains the item at `index`.

                    @method _findArrayOperation

                    @param {number} index the index of the item whose operation information
                    should be returned.
                    @private
                  */
            _findArrayOperation: function (index) {
                var arrayOperationIndex,
                len,
                split = false,
                arrayOperation,
                arrayOperationRangeStart,
                arrayOperationRangeEnd;

                // OPTIMIZE: we could search these faster if we kept a balanced tree.
                // find leftmost arrayOperation to the right of `index`
                for (arrayOperationIndex = arrayOperationRangeStart = 0, len = this._operations.length; arrayOperationIndex < len; ++arrayOperationIndex) {
                    arrayOperation = this._operations[arrayOperationIndex];

                    if (arrayOperation.type === DELETE) {
                        continue;
                    }

                    arrayOperationRangeEnd = arrayOperationRangeStart + arrayOperation.count - 1;

                    if (index === arrayOperationRangeStart) {
                        break;
                    } else if (index > arrayOperationRangeStart && index <= arrayOperationRangeEnd) {
                        split = true;
                        break;
                    } else {
                        arrayOperationRangeStart = arrayOperationRangeEnd + 1;
                    }
                }

                return new ArrayOperationMatch(arrayOperation, arrayOperationIndex, split, arrayOperationRangeStart);
            },

            _split: function (arrayOperationIndex, splitIndex, newArrayOperation) {
                var arrayOperation = this._operations[arrayOperationIndex];
                var splitItems = arrayOperation.items.slice(splitIndex);
                var splitArrayOperation = new ArrayOperation(arrayOperation.type, splitItems.length, splitItems);

                // truncate LHS
                arrayOperation.count = splitIndex;
                arrayOperation.items = arrayOperation.items.slice(0, splitIndex);

                this._operations.splice(arrayOperationIndex + 1, 0, newArrayOperation, splitArrayOperation);
            },

            // see SubArray for a better implementation.
            _composeInsert: function (index) {
                var newArrayOperation = this._operations[index],
                leftArrayOperation = this._operations[index-1], // may be undefined
                rightArrayOperation = this._operations[index + 1], // may be undefined
                leftOp = leftArrayOperation && leftArrayOperation.type,
                rightOp = rightArrayOperation && rightArrayOperation.type;

                if (leftOp === INSERT) {
                    // merge left
                    leftArrayOperation.count += newArrayOperation.count;
                    leftArrayOperation.items = leftArrayOperation.items.concat(newArrayOperation.items);

                    if (rightOp === INSERT) {
                        // also merge right (we have split an insert with an insert)
                        leftArrayOperation.count += rightArrayOperation.count;
                        leftArrayOperation.items = leftArrayOperation.items.concat(rightArrayOperation.items);
                        this._operations.splice(index, 2);
                    } else {
                        // only merge left
                        this._operations.splice(index, 1);
                    }
                } else if (rightOp === INSERT) {
                    // merge right
                    newArrayOperation.count += rightArrayOperation.count;
                    newArrayOperation.items = newArrayOperation.items.concat(rightArrayOperation.items);
                    this._operations.splice(index + 1, 1);
                }
            },

            _composeDelete: function (index) {
                var arrayOperation = this._operations[index],
                deletesToGo = arrayOperation.count,
                leftArrayOperation = this._operations[index-1], // may be undefined
                leftOp = leftArrayOperation && leftArrayOperation.type,
                nextArrayOperation,
                nextOp,
                nextCount,
                removeNewAndNextOp = false,
                removedItems = [];

                if (leftOp === DELETE) {
                    arrayOperation = leftArrayOperation;
                    index -= 1;
                }

                for (var i = index + 1; deletesToGo > 0; ++i) {
                    nextArrayOperation = this._operations[i];
                    nextOp = nextArrayOperation.type;
                    nextCount = nextArrayOperation.count;

                    if (nextOp === DELETE) {
                        arrayOperation.count += nextCount;
                        continue;
                    }

                    if (nextCount > deletesToGo) {
                        // d:2 {r,i}:5  we reduce the retain or insert, but it stays
                        removedItems = removedItems.concat(nextArrayOperation.items.splice(0, deletesToGo));
                        nextArrayOperation.count -= deletesToGo;

                        // In the case where we truncate the last arrayOperation, we don't need to
                        // remove it; also the deletesToGo reduction is not the entirety of
                        // nextCount
                        i -= 1;
                        nextCount = deletesToGo;

                        deletesToGo = 0;
                    } else {
                        if (nextCount === deletesToGo) {
                            // Handle edge case of d:2 i:2 in which case both operations go away
                            // during composition.
                            removeNewAndNextOp = true;
                        }
                        removedItems = removedItems.concat(nextArrayOperation.items);
                        deletesToGo -= nextCount;
                    }

                    if (nextOp === INSERT) {
                        // d:2 i:3 will result in delete going away
                        arrayOperation.count -= nextCount;
                    }
                }

                if (arrayOperation.count > 0) {
                    // compose our new delete with possibly several operations to the right of
                    // disparate types
                    this._operations.splice(index + 1, i-1 - index);
                } else {
                    // The delete operation can go away; it has merely reduced some other
                    // operation, as in d:3 i:4; it may also have eliminated that operation,
                    // as in d:3 i:3.
                    this._operations.splice(index, removeNewAndNextOp ? 2 : 1);
                }

                return removedItems;
            },

            toString: function () {
                var str = "";
                forEach(this._operations, function (operation) {
                    str += " " + operation.type + ":" + operation.count;
                });
                return str.substring(1);
            }
        };

        /**
              Internal data structure to represent an array operation.

              @method ArrayOperation
              @private
              @param {string} type The type of the operation.  One of
              `Ember.TrackedArray.{RETAIN, INSERT, DELETE}`
              @param {number} count The number of items in this operation.
              @param {array} items The items of the operation, if included.  RETAIN and
              INSERT include their items, DELETE does not.
            */
        function ArrayOperation (operation, count, items) {
            this.type = operation; // RETAIN | INSERT | DELETE
            this.count = count;
            this.items = items;
        }

        /**
              Internal data structure used to include information when looking up operations
              by item index.

              @method ArrayOperationMatch
              @private
              @param {ArrayOperation} operation
              @param {number} index The index of `operation` in the array of operations.
              @param {boolean} split Whether or not the item index searched for would
              require a split for a new operation type.
              @param {number} rangeStart The index of the first item in the operation,
              with respect to the tracked array.  The index of the last item can be computed
              from `rangeStart` and `operation.count`.
            */
        function ArrayOperationMatch(operation, index, split, rangeStart) {
            this.operation = operation;
            this.index = index;
            this.split = split;
            this.rangeStart = rangeStart;
        }
    });
    define("ember-testing",
    ["ember-metal/core", "ember-testing/initializers", "ember-testing/support", "ember-testing/setup_for_testing", "ember-testing/test", "ember-testing/adapters/adapter", "ember-testing/adapters/qunit", "ember-testing/helpers"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__) {
        "use strict";
        var Ember = __dependency1__["default"];

        // to setup initializer
        // to handle various edge cases

        var setupForTesting = __dependency4__["default"];
        var Test = __dependency5__["default"];
        var Adapter = __dependency6__["default"];
        var QUnitAdapter = __dependency7__["default"];
        // adds helpers to helpers object in Test

        /**
              Ember Testing

              @module ember
              @submodule ember-testing
              @requires ember-application
            */

        Ember.Test = Test;
        Ember.Test.Adapter = Adapter;
        Ember.Test.QUnitAdapter = QUnitAdapter;
        Ember.setupForTesting = setupForTesting;
    });
    define("ember-testing/adapters/adapter",
    ["ember-metal/core", "ember-metal/utils", "ember-runtime/system/object", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // Ember.K
        var inspect = __dependency2__.inspect;
        var EmberObject = __dependency3__["default"];

        /**
             @module ember
             @submodule ember-testing
            */

        /**
              The primary purpose of this class is to create hooks that can be implemented
              by an adapter for various test frameworks.

              @class Adapter
              @namespace Ember.Test
            */
        var Adapter = EmberObject.extend({
            /**
                    This callback will be called whenever an async operation is about to start.

                    Override this to call your framework's methods that handle async
                    operations.

                    @public
                    @method asyncStart
                  */
            asyncStart: Ember.K,

            /**
                    This callback will be called whenever an async operation has completed.

                    @public
                    @method asyncEnd
                  */
            asyncEnd: Ember.K,

            /**
                    Override this method with your testing framework's false assertion.
                    This function is called whenever an exception occurs causing the testing
                    promise to fail.

                    QUnit example:

                    ```javascript
                      exception: function(error) {
                        ok(false, error);
                      };
                    ```

                    @public
                    @method exception
                    @param {String} error The exception to be raised.
                  */
            exception: function(error) {
                throw error;
            }
        });

        __exports__["default"] = Adapter;
    });
    define("ember-testing/adapters/qunit",
    ["ember-testing/adapters/adapter", "ember-metal/utils", "exports"],
    function(__dependency1__, __dependency2__, __exports__) {
        "use strict";
        var Adapter = __dependency1__["default"];
        var inspect = __dependency2__.inspect;

        /**
              This class implements the methods defined by Ember.Test.Adapter for the
              QUnit testing framework.

              @class QUnitAdapter
              @namespace Ember.Test
              @extends Ember.Test.Adapter
            */
        __exports__["default"] = Adapter.extend({
            asyncStart: function() {
                QUnit.stop();
            },
            asyncEnd: function() {
                QUnit.start();
            },
            exception: function(error) {
                ok(false, inspect(error));
            }
        });
    });
    define("ember-testing/helpers",
    ["ember-metal/property_get", "ember-metal/error", "ember-metal/run_loop", "ember-views/system/jquery", "ember-testing/test"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__) {
        "use strict";
        var get = __dependency1__.get;
        var EmberError = __dependency2__["default"];
        var run = __dependency3__["default"];
        var jQuery = __dependency4__["default"];
        var Test = __dependency5__["default"];

        /**
            * @module ember
            * @submodule ember-testing
            */

        var helper = Test.registerHelper;
        var asyncHelper = Test.registerAsyncHelper;
        var countAsync = 0;

        function currentRouteName(app) {
            var appController = app.__container__.lookup('controller:application');

            return get(appController, 'currentRouteName');
        }

        function currentPath(app) {
            var appController = app.__container__.lookup('controller:application');

            return get(appController, 'currentPath');
        }

        function currentURL(app) {
            var router = app.__container__.lookup('router:main');

            return get(router, 'location').getURL();
        }

        function visit(app, url) {
            var router = app.__container__.lookup('router:main');
            router.location.setURL(url);

            if (app._readinessDeferrals > 0) {
                router['initialURL'] = url;
                run(app, 'advanceReadiness');
                delete router['initialURL'];
            } else {
                run(app, app.handleURL, url);
            }

            return app.testHelpers.wait();
        }

        function click(app, selector, context) {
            var $el = app.testHelpers.findWithAssert(selector, context);
            run($el, 'mousedown');

            if ($el.is(':input')) {
                var type = $el.prop('type');
                if (type !== 'checkbox' && type !== 'radio' && type !== 'hidden') {
                    run($el, function() {
                        // Firefox does not trigger the `focusin` event if the window
                        // does not have focus. If the document doesn't have focus just
                        // use trigger('focusin') instead.
                        if (!document.hasFocus || document.hasFocus()) {
                            this.focus();
                        } else {
                            this.trigger('focusin');
                        }
                    });
                }
            }

            run($el, 'mouseup');
            run($el, 'click');

            return app.testHelpers.wait();
        }

        function triggerEvent(app, selector, context, type, options) {
            if (arguments.length === 3) {
                options = type;
                type = context;
                context = null;
            }

            if (typeof options === 'undefined') {
                options = {};
            }

            var $el = app.testHelpers.findWithAssert(selector, context);

            var event = jQuery.Event(type, options);

            run($el, 'trigger', event);

            return app.testHelpers.wait();
        }

        function keyEvent(app, selector, context, type, keyCode) {
            if (typeof keyCode === 'undefined') {
                keyCode = type;
                type = context;
                context = null;
            }

            return app.testHelpers.triggerEvent(selector, context, type, {
                keyCode: keyCode,
                which: keyCode 
            });
        }

        function fillIn(app, selector, context, text) {
            var $el;
            if (typeof text === 'undefined') {
                text = context;
                context = null;
            }
            $el = app.testHelpers.findWithAssert(selector, context);
            run(function() {
                $el.val(text).change();
            });
            return app.testHelpers.wait();
        }

        function findWithAssert(app, selector, context) {
            var $el = app.testHelpers.find(selector, context);
            if ($el.length === 0) {
                throw new EmberError("Element " + selector + " not found.");
            }
            return $el;
        }

        function find(app, selector, context) {
            var $el;
            context = context || get(app, 'rootElement');
            $el = app.$(selector, context);

            return $el;
        }

        function andThen(app, callback) {
            return app.testHelpers.wait(callback(app));
        }

        function wait(app, value) {
            return Test.promise(function(resolve) {
                // If this is the first async promise, kick off the async test
                if (++countAsync === 1) {
                    Test.adapter.asyncStart();
                }

                // Every 10ms, poll for the async thing to have finished
                var watcher = setInterval(function() {
                    // 1. If the router is loading, keep polling
                    var routerIsLoading = !!app.__container__.lookup('router:main').router.activeTransition;
                    if (routerIsLoading) {
                        return;
                    }

                    // 2. If there are pending Ajax requests, keep polling
                    if (Test.pendingAjaxRequests) {
                        return;
                    }

                    // 3. If there are scheduled timers or we are inside of a run loop, keep polling
                    if (run.hasScheduledTimers() || run.currentRunLoop) {
                        return;
                    }
                    if (Test.waiters && Test.waiters.any(function(waiter) {
                        var context = waiter[0];
                        var callback = waiter[1];
                        return !callback.call(context);
                    })) {
                        return;
                    }
                    // Stop polling
                    clearInterval(watcher);

                    // If this is the last async promise, end the async test
                    if (--countAsync === 0) {
                        Test.adapter.asyncEnd();
                    }

                    // Synchronously resolve the promise
                    run(null, resolve, value);
                }, 10);
            });

        }


        /**
            * Loads a route, sets up any controllers, and renders any templates associated
            * with the route as though a real user had triggered the route change while
            * using your app.
            *
            * Example:
            *
            * ```javascript
            * visit('posts/index').then(function() {
            *   // assert something
            * });
            * ```
            *
            * @method visit
            * @param {String} url the name of the route
            * @return {RSVP.Promise}
            */
        asyncHelper('visit', visit);

        /**
            * Clicks an element and triggers any actions triggered by the element's `click`
            * event.
            *
            * Example:
            *
            * ```javascript
            * click('.some-jQuery-selector').then(function() {
            *   // assert something
            * });
            * ```
            *
            * @method click
            * @param {String} selector jQuery selector for finding element on the DOM
            * @return {RSVP.Promise}
            */
        asyncHelper('click', click);

        /**
            * Simulates a key event, e.g. `keypress`, `keydown`, `keyup` with the desired keyCode
            *
            * Example:
            *
            * ```javascript
            * keyEvent('.some-jQuery-selector', 'keypress', 13).then(function() {
            *  // assert something
            * });
            * ```
            *
            * @method keyEvent
            * @param {String} selector jQuery selector for finding element on the DOM
            * @param {String} type the type of key event, e.g. `keypress`, `keydown`, `keyup`
            * @param {Number} keyCode the keyCode of the simulated key event
            * @return {RSVP.Promise}
            * @since 1.5.0
            */
        asyncHelper('keyEvent', keyEvent);

        /**
            * Fills in an input element with some text.
            *
            * Example:
            *
            * ```javascript
            * fillIn('#email', 'you@example.com').then(function() {
            *   // assert something
            * });
            * ```
            *
            * @method fillIn
            * @param {String} selector jQuery selector finding an input element on the DOM
            * to fill text with
            * @param {String} text text to place inside the input element
            * @return {RSVP.Promise}
            */
        asyncHelper('fillIn', fillIn);

        /**
            * Finds an element in the context of the app's container element. A simple alias
            * for `app.$(selector)`.
            *
            * Example:
            *
            * ```javascript
            * var $el = find('.my-selector');
            * ```
            *
            * @method find
            * @param {String} selector jQuery string selector for element lookup
            * @return {Object} jQuery object representing the results of the query
            */
        helper('find', find);

        /**
            * Like `find`, but throws an error if the element selector returns no results.
            *
            * Example:
            *
            * ```javascript
            * var $el = findWithAssert('.doesnt-exist'); // throws error
            * ```
            *
            * @method findWithAssert
            * @param {String} selector jQuery selector string for finding an element within
            * the DOM
            * @return {Object} jQuery object representing the results of the query
            * @throws {Error} throws error if jQuery object returned has a length of 0
            */
        helper('findWithAssert', findWithAssert);

        /**
              Causes the run loop to process any pending events. This is used to ensure that
              any async operations from other helpers (or your assertions) have been processed.

              This is most often used as the return value for the helper functions (see 'click',
              'fillIn','visit',etc).

              Example:

              ```javascript
              Ember.Test.registerAsyncHelper('loginUser', function(app, username, password) {
                visit('secured/path/here')
                .fillIn('#username', username)
                .fillIn('#password', username)
                .click('.submit')

                return app.testHelpers.wait();
              });

              @method wait
              @param {Object} value The value to be returned.
              @return {RSVP.Promise}
            */
        asyncHelper('wait', wait);
        asyncHelper('andThen', andThen);


        /**
              Returns the currently active route name.

            Example:

            ```javascript
            function validateRouteName(){
            equal(currentRouteName(), 'some.path', "correct route was transitioned into.");
            }

            visit('/some/path').then(validateRouteName)
            ```

            @method currentRouteName
            @return {Object} The name of the currently active route.
            @since 1.5.0
            */
        helper('currentRouteName', currentRouteName);

        /**
              Returns the current path.

            Example:

            ```javascript
            function validateURL(){
            equal(currentPath(), 'some.path.index', "correct path was transitioned into.");
            }

            click('#some-link-id').then(validateURL);
            ```

            @method currentPath
            @return {Object} The currently active path.
            @since 1.5.0
            */
        helper('currentPath', currentPath);

        /**
              Returns the current URL.

            Example:

            ```javascript
            function validateURL(){
            equal(currentURL(), '/some/path', "correct URL was transitioned into.");
            }

            click('#some-link-id').then(validateURL);
            ```

            @method currentURL
            @return {Object} The currently active URL.
            @since 1.5.0
            */
        helper('currentURL', currentURL);

        /**
              Triggers the given DOM event on the element identified by the provided selector.

              Example:

              ```javascript
              triggerEvent('#some-elem-id', 'blur');
              ```

              This is actually used internally by the `keyEvent` helper like so:

              ```javascript
              triggerEvent('#some-elem-id', 'keypress', { keyCode: 13 });
              ```

             @method triggerEvent
             @param {String} selector jQuery selector for finding element on the DOM
             @param {String} [context] jQuery selector that will limit the selector
                                       argument to find only within the context's children
             @param {String} type The event type to be triggered.
             @param {Object} options The options to be passed to jQuery.Event.
             @return {RSVP.Promise}
             @since 1.5.0
            */
        asyncHelper('triggerEvent', triggerEvent);
    });
    define("ember-testing/initializers",
    ["ember-runtime/system/lazy_load"],
    function(__dependency1__) {
        "use strict";
        var onLoad = __dependency1__.onLoad;

        var name = 'deferReadiness in `testing` mode';

        onLoad('Ember.Application', function(Application) {
            if (!Application.initializers[name]) {
                Application.initializer({
                    name: name,

                    initialize: function(container, application) {
                        if (application.testing) {
                            application.deferReadiness();
                        }
                    }
                });
            }
        });
    });
    define("ember-testing/setup_for_testing",
    ["ember-metal/core", "ember-testing/adapters/qunit", "ember-views/system/jquery", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // import Test from "ember-testing/test";  // ES6TODO: fix when cycles are supported
        var QUnitAdapter = __dependency2__["default"];
        var jQuery = __dependency3__["default"];

        var Test, requests;

        function incrementAjaxPendingRequests(_, xhr) {
            requests.push(xhr);
            Test.pendingAjaxRequests = requests.length;
        }

        function decrementAjaxPendingRequests(_, xhr) {
            for (var i = 0; i < requests.length; i++) {
                if (xhr === requests[i]) {
                    requests.splice(i, 1);
                }
            }
            Test.pendingAjaxRequests = requests.length;
        }

        /**
              Sets Ember up for testing. This is useful to perform
              basic setup steps in order to unit test.

              Use `App.setupForTesting` to perform integration tests (full
              application testing).

              @method setupForTesting
              @namespace Ember
              @since 1.5.0
            */
        __exports__["default"] = function setupForTesting() {
            if (!Test) {
                Test = requireModule('ember-testing/test')['default'];
            }

            Ember.testing = true;

            // if adapter is not manually set default to QUnit
            if (!Test.adapter) {
                Test.adapter = QUnitAdapter.create();
            }

            requests = [];
            Test.pendingAjaxRequests = requests.length;

            jQuery(document).off('ajaxSend', incrementAjaxPendingRequests);
            jQuery(document).off('ajaxComplete', decrementAjaxPendingRequests);
            jQuery(document).on('ajaxSend', incrementAjaxPendingRequests);
            jQuery(document).on('ajaxComplete', decrementAjaxPendingRequests);
        }
    });
    define("ember-testing/support",
    ["ember-metal/core", "ember-views/system/jquery"],
    function(__dependency1__, __dependency2__) {
        "use strict";
        var Ember = __dependency1__["default"];
        var jQuery = __dependency2__["default"];

        /**
              @module ember
              @submodule ember-testing
             */

        var $ = jQuery;

        /**
              This method creates a checkbox and triggers the click event to fire the
              passed in handler. It is used to correct for a bug in older versions
              of jQuery (e.g 1.8.3).

              @private
              @method testCheckboxClick
            */
        function testCheckboxClick(handler) {
            $('<input type="checkbox">')
            .css({
                position: 'absolute',
                left: '-1000px',
                top: '-1000px' 
            })
            .appendTo('body')
            .on('click', handler)
            .trigger('click')
            .remove();
        }

        $(function() {
            /*
                    Determine whether a checkbox checked using jQuery's "click" method will have
                    the correct value for its checked property.

                    If we determine that the current jQuery version exhibits this behavior,
                    patch it to work correctly as in the commit for the actual fix:
                    https://github.com/jquery/jquery/commit/1fb2f92.
                  */
            testCheckboxClick(function() {
                if (!this.checked && !$.event.special.click) {
                    $.event.special.click = {
                        // For checkbox, fire native event so checked state will be right
                        trigger: function() {
                            if ($.nodeName( this, "input" ) && this.type === "checkbox" && this.click) {
                                this.click();
                                return false;
                            }
                        }
                    };
                }
            });

            // Try again to verify that the patch took effect or blow up.
            testCheckboxClick(function() {
                Ember.warn("clicked checkboxes should be checked! the jQuery patch didn't work", this.checked);
            });
        });
    });
    define("ember-testing/test",
    ["ember-metal/core", "ember-metal/run_loop", "ember-metal/platform", "ember-runtime/compare", "ember-runtime/ext/rsvp", "ember-testing/setup_for_testing", "ember-application/system/application", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        var emberRun = __dependency2__["default"];
        var create = __dependency3__.create;
        var compare = __dependency4__["default"];
        var RSVP = __dependency5__["default"];
        var setupForTesting = __dependency6__["default"];
        var EmberApplication = __dependency7__["default"];

        /**
              @module ember
              @submodule ember-testing
             */
        var slice = [].slice;
        var helpers = {};
        var injectHelpersCallbacks = [];

        /**
              This is a container for an assortment of testing related functionality:

              * Choose your default test adapter (for your framework of choice).
              * Register/Unregister additional test helpers.
              * Setup callbacks to be fired when the test helpers are injected into
                your application.

              @class Test
              @namespace Ember
            */
        var Test = {
            /**
                    Hash containing all known test helpers.

                    @property _helpers
                    @private
                  */
            _helpers: helpers,

            /**
                    `registerHelper` is used to register a test helper that will be injected
                    when `App.injectTestHelpers` is called.

                    The helper method will always be called with the current Application as
                    the first parameter.

                    For example:

                    ```javascript
                    Ember.Test.registerHelper('boot', function(app) {
                      Ember.run(app, app.advanceReadiness);
                    });
                    ```

                    This helper can later be called without arguments because it will be
                    called with `app` as the first parameter.

                    ```javascript
                    App = Ember.Application.create();
                    App.injectTestHelpers();
                    boot();
                    ```

                    @public
                    @method registerHelper
                    @param {String} name The name of the helper method to add.
                    @param {Function} helperMethod
                    @param options {Object}
                  */
            registerHelper: function(name, helperMethod) {
                helpers[name] = {
                    method: helperMethod,
                    meta: {
                        wait: false 
                    }
                };
            },

            /**
                    `registerAsyncHelper` is used to register an async test helper that will be injected
                    when `App.injectTestHelpers` is called.

                    The helper method will always be called with the current Application as
                    the first parameter.

                    For example:

                    ```javascript
                    Ember.Test.registerAsyncHelper('boot', function(app) {
                      Ember.run(app, app.advanceReadiness);
                    });
                    ```

                    The advantage of an async helper is that it will not run
                    until the last async helper has completed.  All async helpers
                    after it will wait for it complete before running.


                    For example:

                    ```javascript
                    Ember.Test.registerAsyncHelper('deletePost', function(app, postId) {
                      click('.delete-' + postId);
                    });

                    // ... in your test
                    visit('/post/2');
                    deletePost(2);
                    visit('/post/3');
                    deletePost(3);
                    ```

                    @public
                    @method registerAsyncHelper
                    @param {String} name The name of the helper method to add.
                    @param {Function} helperMethod
                    @since 1.2.0
                  */
            registerAsyncHelper: function(name, helperMethod) {
                helpers[name] = {
                    method: helperMethod,
                    meta: {
                        wait: true 
                    }
                };
            },

            /**
                    Remove a previously added helper method.

                    Example:

                    ```javascript
                    Ember.Test.unregisterHelper('wait');
                    ```

                    @public
                    @method unregisterHelper
                    @param {String} name The helper to remove.
                  */
            unregisterHelper: function(name) {
                delete helpers[name];
                delete Test.Promise.prototype[name];
            },

            /**
                    Used to register callbacks to be fired whenever `App.injectTestHelpers`
                    is called.

                    The callback will receive the current application as an argument.

                    Example:

                    ```javascript
                    Ember.Test.onInjectHelpers(function() {
                      Ember.$(document).ajaxSend(function() {
                        Test.pendingAjaxRequests++;
                      });

                      Ember.$(document).ajaxComplete(function() {
                        Test.pendingAjaxRequests--;
                      });
                    });
                    ```

                    @public
                    @method onInjectHelpers
                    @param {Function} callback The function to be called.
                  */
            onInjectHelpers: function(callback) {
                injectHelpersCallbacks.push(callback);
            },

            /**
                    This returns a thenable tailored for testing.  It catches failed
                    `onSuccess` callbacks and invokes the `Ember.Test.adapter.exception`
                    callback in the last chained then.

                    This method should be returned by async helpers such as `wait`.

                    @public
                    @method promise
                    @param {Function} resolver The function used to resolve the promise.
                  */
            promise: function(resolver) {
                return new Test.Promise(resolver);
            },

            /**
                   Used to allow ember-testing to communicate with a specific testing
                   framework.

                   You can manually set it before calling `App.setupForTesting()`.

                   Example:

                   ```javascript
                   Ember.Test.adapter = MyCustomAdapter.create()
                   ```

                   If you do not set it, ember-testing will default to `Ember.Test.QUnitAdapter`.

                   @public
                   @property adapter
                   @type {Class} The adapter to be used.
                   @default Ember.Test.QUnitAdapter
                  */
            adapter: null,

            /**
                    Replacement for `Ember.RSVP.resolve`
                    The only difference is this uses
                    an instance of `Ember.Test.Promise`

                    @public
                    @method resolve
                    @param {Mixed} The value to resolve
                    @since 1.2.0
                  */
            resolve: function(val) {
                return Test.promise(function(resolve) {
                    return resolve(val);
                });
            },

            /**
                     This allows ember-testing to play nicely with other asynchronous
                     events, such as an application that is waiting for a CSS3
                     transition or an IndexDB transaction.

                     For example:

                     ```javascript
                     Ember.Test.registerWaiter(function() {
                       return myPendingTransactions() == 0;
                     });
                     ```
                     The `context` argument allows you to optionally specify the `this`
                     with which your callback will be invoked.

                     For example:

                     ```javascript
                     Ember.Test.registerWaiter(MyDB, MyDB.hasPendingTransactions);
                     ```

                     @public
                     @method registerWaiter
                     @param {Object} context (optional)
                     @param {Function} callback
                     @since 1.2.0
                  */
            registerWaiter: function(context, callback) {
                if (arguments.length === 1) {
                    callback = context;
                    context = null;
                }
                if (!this.waiters) {
                    this.waiters = Ember.A();
                }
                this.waiters.push([context, callback]);
            },
            /**
                     `unregisterWaiter` is used to unregister a callback that was
                     registered with `registerWaiter`.

                     @public
                     @method unregisterWaiter
                     @param {Object} context (optional)
                     @param {Function} callback
                     @since 1.2.0
                  */
            unregisterWaiter: function(context, callback) {
                var pair;
                if (!this.waiters) {
                    return;
                }
                if (arguments.length === 1) {
                    callback = context;
                    context = null;
                }
                pair = [context, callback];
                this.waiters = Ember.A(this.waiters.filter(function(elt) {
                    return compare(elt, pair) !== 0;
                }));
            }
        };

        function helper(app, name) {
            var fn = helpers[name].method,
            meta = helpers[name].meta;

            return function() {
                var args = slice.call(arguments),
                lastPromise = Test.lastPromise;

                args.unshift(app);

                // some helpers are not async and
                // need to return a value immediately.
                // example: `find`
                if (!meta.wait) {
                    return fn.apply(app, args);
                }

                if (!lastPromise) {
                    // It's the first async helper in current context
                    lastPromise = fn.apply(app, args);
                } else {
                    // wait for last helper's promise to resolve
                    // and then execute
                    run(function() {
                        lastPromise = Test.resolve(lastPromise).then(function() {
                            return fn.apply(app, args);
                        });
                    });
                }

                return lastPromise;
            };
        }

        function run(fn) {
            if (!emberRun.currentRunLoop) {
                emberRun(fn);
            } else {
                fn();
            }
        }

        EmberApplication.reopen({
            /**
                   This property contains the testing helpers for the current application. These
                   are created once you call `injectTestHelpers` on your `Ember.Application`
                   instance. The included helpers are also available on the `window` object by
                   default, but can be used from this object on the individual application also.

                    @property testHelpers
                    @type {Object}
                    @default {}
                  */
            testHelpers: {},

            /**
                   This property will contain the original methods that were registered
                   on the `helperContainer` before `injectTestHelpers` is called.

                   When `removeTestHelpers` is called, these methods are restored to the
                   `helperContainer`.

                    @property originalMethods
                    @type {Object}
                    @default {}
                    @private
                    @since 1.3.0
                  */
            originalMethods: {},


            /**
                  This property indicates whether or not this application is currently in
                  testing mode. This is set when `setupForTesting` is called on the current
                  application.

                  @property testing
                  @type {Boolean}
                  @default false
                  @since 1.3.0
                  */
            testing: false,

            /**
                   This hook defers the readiness of the application, so that you can start
                   the app when your tests are ready to run. It also sets the router's
                   location to 'none', so that the window's location will not be modified
                   (preventing both accidental leaking of state between tests and interference
                   with your testing framework).

                   Example:

                  ```
                  App.setupForTesting();
                  ```

                    @method setupForTesting
                  */
            setupForTesting: function() {
                setupForTesting();

                this.testing = true;

                this.Router.reopen({
                    location: 'none'
                });
            },

            /**
                    This will be used as the container to inject the test helpers into. By
                    default the helpers are injected into `window`.

                    @property helperContainer
                    @type {Object} The object to be used for test helpers.
                    @default window
                    @since 1.2.0
                  */
            helperContainer: window,

            /**
                    This injects the test helpers into the `helperContainer` object. If an object is provided
                    it will be used as the helperContainer. If `helperContainer` is not set it will default
                    to `window`. If a function of the same name has already been defined it will be cached
                    (so that it can be reset if the helper is removed with `unregisterHelper` or
                    `removeTestHelpers`).

                   Any callbacks registered with `onInjectHelpers` will be called once the
                   helpers have been injected.

                  Example:
                  ```
                  App.injectTestHelpers();
                  ```

                    @method injectTestHelpers
                  */
            injectTestHelpers: function(helperContainer) {
                if (helperContainer) {
                    this.helperContainer = helperContainer;
                }

                this.testHelpers = {};
                for (var name in helpers) {
                    this.originalMethods[name] = this.helperContainer[name];
                    this.testHelpers[name] = this.helperContainer[name] = helper(this, name);
                    protoWrap(Test.Promise.prototype, name, helper(this, name), helpers[name].meta.wait);
                }

                for (var i = 0, l = injectHelpersCallbacks.length; i < l; i++) {
                    injectHelpersCallbacks[i](this);
                }
            },

            /**
                    This removes all helpers that have been registered, and resets and functions
                    that were overridden by the helpers.

                    Example:

                    ```javascript
                    App.removeTestHelpers();
                    ```

                    @public
                    @method removeTestHelpers
                  */
            removeTestHelpers: function() {
                for (var name in helpers) {
                    this.helperContainer[name] = this.originalMethods[name];
                    delete this.testHelpers[name];
                    delete this.originalMethods[name];
                }
            }
        });

        // This method is no longer needed
        // But still here for backwards compatibility
        // of helper chaining
        function protoWrap(proto, name, callback, isAsync) {
            proto[name] = function() {
                var args = arguments;
                if (isAsync) {
                    return callback.apply(this, args);
                } else {
                    return this.then(function() {
                        return callback.apply(this, args);
                    });
                }
            };
        }

        Test.Promise = function() {
            RSVP.Promise.apply(this, arguments);
            Test.lastPromise = this;
        };

        Test.Promise.prototype = create(RSVP.Promise.prototype);
        Test.Promise.prototype.constructor = Test.Promise;

        // Patch `then` to isolate async methods
        // specifically `Ember.Test.lastPromise`
        var originalThen = RSVP.Promise.prototype.then;
        Test.Promise.prototype.then = function(onSuccess, onFailure) {
            return originalThen.call(this, function(val) {
                return isolate(onSuccess, val);
            }, onFailure);
        };

        // This method isolates nested async methods
        // so that they don't conflict with other last promises.
        //
        // 1. Set `Ember.Test.lastPromise` to null
        // 2. Invoke method
        // 3. Return the last promise created during method
        // 4. Restore `Ember.Test.lastPromise` to original value
        function isolate(fn, val) {
            var value, lastPromise;

            // Reset lastPromise for nested helpers
            Test.lastPromise = null;

            value = fn(val);

            lastPromise = Test.lastPromise;

            // If the method returned a promise
            // return that promise. If not,
            // return the last async helper's promise
            if ((value && (value instanceof Test.Promise)) || !lastPromise) {
                return value;
            } else {
                run(function() {
                    lastPromise = Test.resolve(lastPromise).then(function() {
                        return value;
                    });
                });
                return lastPromise;
            }
        }

        __exports__["default"] = Test;
    });
    define("ember-views",
    ["ember-runtime", "ember-views/system/jquery", "ember-views/system/utils", "ember-views/system/render_buffer", "ember-views/system/ext", "ember-views/views/states", "ember-views/views/core_view", "ember-views/views/view", "ember-views/views/view_collection", "ember-views/views/container_view", "ember-views/views/collection_view", "ember-views/views/component", "ember-views/system/event_dispatcher", "ember-views/mixins/view_target_action_support", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __exports__) {
        "use strict";
        /**
            Ember Views

            @module ember
            @submodule ember-views
            @requires ember-runtime
            @main ember-views
            */

        // BEGIN IMPORTS
        var Ember = __dependency1__["default"];
        var jQuery = __dependency2__["default"];
        var setInnerHTML = __dependency3__.setInnerHTML;
        var isSimpleClick = __dependency3__.isSimpleClick;
        var RenderBuffer = __dependency4__["default"];
        // for the side effect of extending Ember.run.queues
        var cloneStates = __dependency6__.cloneStates;
        var states = __dependency6__.states;

        var CoreView = __dependency7__["default"];
        var View = __dependency8__["default"];
        var ViewCollection = __dependency9__["default"];
        var ContainerView = __dependency10__["default"];
        var CollectionView = __dependency11__["default"];
        var Component = __dependency12__["default"];

        var EventDispatcher = __dependency13__["default"];
        var ViewTargetActionSupport = __dependency14__["default"];
        // END IMPORTS

        /**
              Alias for jQuery

              @method $
              @for Ember
            */

        // BEGIN EXPORTS
        Ember.$ = jQuery;

        Ember.ViewTargetActionSupport = ViewTargetActionSupport;
        Ember.RenderBuffer = RenderBuffer;

        var ViewUtils = Ember.ViewUtils = {};
        ViewUtils.setInnerHTML = setInnerHTML;
        ViewUtils.isSimpleClick = isSimpleClick;

        Ember.CoreView = CoreView;
        Ember.View = View;
        Ember.View.states = states;
        Ember.View.cloneStates = cloneStates;

        Ember._ViewCollection = ViewCollection;
        Ember.ContainerView = ContainerView;
        Ember.CollectionView = CollectionView;
        Ember.Component = Component;
        Ember.EventDispatcher = EventDispatcher;
        // END EXPORTS

        __exports__["default"] = Ember;
    });
    define("ember-views/mixins/component_template_deprecation",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/mixin", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // Ember.deprecate
        var get = __dependency2__.get;
        var Mixin = __dependency3__.Mixin;

        /**
              The ComponentTemplateDeprecation mixin is used to provide a useful
              deprecation warning when using either `template` or `templateName` with
              a component. The `template` and `templateName` properties specified at
              extend time are moved to `layout` and `layoutName` respectively.

              `Ember.ComponentTemplateDeprecation` is used internally by Ember in
              `Ember.Component`.

              @class ComponentTemplateDeprecation
              @namespace Ember
            */
        __exports__["default"] = Mixin.create({
            /**
                    @private

                    Moves `templateName` to `layoutName` and `template` to `layout` at extend
                    time if a layout is not also specified.

                    Note that this currently modifies the mixin themselves, which is technically
                    dubious but is practically of little consequence. This may change in the
                    future.

                    @method willMergeMixin
                    @since 1.4.0
                  */
            willMergeMixin: function(props) {
                // must call _super here to ensure that the ActionHandler
                // mixin is setup properly (moves actions -> _actions)
                //
                // Calling super is only OK here since we KNOW that
                // there is another Mixin loaded first.
                this._super.apply(this, arguments);

                var deprecatedProperty, replacementProperty,
                layoutSpecified = (props.layoutName || props.layout || get(this, 'layoutName'));

                if (props.templateName && !layoutSpecified) {
                    deprecatedProperty = 'templateName';
                    replacementProperty = 'layoutName';

                    props.layoutName = props.templateName;
                    delete props['templateName'];
                }

                if (props.template && !layoutSpecified) {
                    deprecatedProperty = 'template';
                    replacementProperty = 'layout';

                    props.layout = props.template;
                    delete props['template'];
                }

                if (deprecatedProperty) {
                    Ember.deprecate('Do not specify ' + deprecatedProperty + ' on a Component, use ' + replacementProperty + ' instead.', false);
                }
            }
        });
    });
    define("ember-views/mixins/view_target_action_support",
    ["ember-metal/mixin", "ember-runtime/mixins/target_action_support", "ember-metal/computed", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        var Mixin = __dependency1__.Mixin;
        var TargetActionSupport = __dependency2__["default"];

        // ES6TODO: computed should have its own export path so you can do import {defaultTo} from computed
        var computed = __dependency3__.computed;
        var alias = computed.alias;

        /**
            `Ember.ViewTargetActionSupport` is a mixin that can be included in a
            view class to add a `triggerAction` method with semantics similar to
            the Handlebars `{{action}}` helper. It provides intelligent defaults
            for the action's target: the view's controller; and the context that is
            sent with the action: the view's context.

            Note: In normal Ember usage, the `{{action}}` helper is usually the best
            choice. This mixin is most often useful when you are doing more complex
            event handling in custom View subclasses.

            For example:

            ```javascript
            App.SaveButtonView = Ember.View.extend(Ember.ViewTargetActionSupport, {
              action: 'save',
              click: function() {
                this.triggerAction(); // Sends the `save` action, along with the current context
                                      // to the current controller
              }
            });
            ```

            The `action` can be provided as properties of an optional object argument
            to `triggerAction` as well.

            ```javascript
            App.SaveButtonView = Ember.View.extend(Ember.ViewTargetActionSupport, {
              click: function() {
                this.triggerAction({
                  action: 'save'
                }); // Sends the `save` action, along with the current context
                    // to the current controller
              }
            });
            ```

            @class ViewTargetActionSupport
            @namespace Ember
            @extends Ember.TargetActionSupport
            */
        __exports__["default"] = Mixin.create(TargetActionSupport, {
            /**
                  @property target
                  */
            target: alias('controller'),
            /**
                  @property actionContext
                  */
            actionContext: alias('context')
        });
    });
    define("ember-views/system/event_dispatcher",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/is_none", "ember-metal/run_loop", "ember-metal/utils", "ember-runtime/system/string", "ember-runtime/system/object", "ember-views/system/jquery", "ember-views/views/view", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-views
            */
        var Ember = __dependency1__["default"];
        // Ember.assert

        var get = __dependency2__.get;
        var set = __dependency3__.set;
        var isNone = __dependency4__.isNone;
        var run = __dependency5__["default"];
        var typeOf = __dependency6__.typeOf;
        var fmt = __dependency7__.fmt;
        var EmberObject = __dependency8__["default"];
        var jQuery = __dependency9__["default"];
        var View = __dependency10__["default"];

        var ActionHelper;

        //ES6TODO:
        // find a better way to do Ember.View.views without global state

        /**
              `Ember.EventDispatcher` handles delegating browser events to their
              corresponding `Ember.Views.` For example, when you click on a view,
              `Ember.EventDispatcher` ensures that that view's `mouseDown` method gets
              called.

              @class EventDispatcher
              @namespace Ember
              @private
              @extends Ember.Object
            */
        __exports__["default"] = EmberObject.extend({

            /**
                    The set of events names (and associated handler function names) to be setup
                    and dispatched by the `EventDispatcher`. Custom events can added to this list at setup
                    time, generally via the `Ember.Application.customEvents` hash. Only override this
                    default set to prevent the EventDispatcher from listening on some events all together.

                    This set will be modified by `setup` to also include any events added at that time.

                    @property events
                    @type Object
                  */
            events: {
                touchstart : 'touchStart',
                touchmove : 'touchMove',
                touchend : 'touchEnd',
                touchcancel : 'touchCancel',
                keydown : 'keyDown',
                keyup : 'keyUp',
                keypress : 'keyPress',
                mousedown : 'mouseDown',
                mouseup : 'mouseUp',
                contextmenu : 'contextMenu',
                click : 'click',
                dblclick : 'doubleClick',
                mousemove : 'mouseMove',
                focusin : 'focusIn',
                focusout : 'focusOut',
                mouseenter : 'mouseEnter',
                mouseleave : 'mouseLeave',
                submit : 'submit',
                input : 'input',
                change : 'change',
                dragstart : 'dragStart',
                drag : 'drag',
                dragenter : 'dragEnter',
                dragleave : 'dragLeave',
                dragover : 'dragOver',
                drop : 'drop',
                dragend : 'dragEnd'
            },

            /**
                    The root DOM element to which event listeners should be attached. Event
                    listeners will be attached to the document unless this is overridden.

                    Can be specified as a DOMElement or a selector string.

                    The default body is a string since this may be evaluated before document.body
                    exists in the DOM.

                    @private
                    @property rootElement
                    @type DOMElement
                    @default 'body'
                  */
            rootElement: 'body',

            /**
                    It enables events to be dispatched to the view's `eventManager.` When present,
                    this object takes precedence over handling of events on the view itself.

                    Note that most Ember applications do not use this feature. If your app also
                    does not use it, consider setting this property to false to gain some performance
                    improvement by allowing the EventDispatcher to skip the search for the
                    `eventManager` on the view tree.

                    ```javascript
                    var EventDispatcher = Em.EventDispatcher.extend({
                      events: {
                          click       : 'click',
                          focusin     : 'focusIn',
                          focusout    : 'focusOut',
                          change      : 'change'
                      },
                      canDispatchToEventManager: false
                    });
                    container.register('event_dispatcher:main', EventDispatcher);
                    ```

                    @property canDispatchToEventManager
                    @type boolean
                    @default 'true'
                  */
            canDispatchToEventManager: true,

            /**
                    Sets up event listeners for standard browser events.

                    This will be called after the browser sends a `DOMContentReady` event. By
                    default, it will set up all of the listeners on the document body. If you
                    would like to register the listeners on a different element, set the event
                    dispatcher's `root` property.

                    @private
                    @method setup
                    @param addedEvents {Hash}
                  */
            setup: function(addedEvents, rootElement) {
                var event, events = get(this, 'events');

                jQuery.extend(events, addedEvents || {});

                if (!isNone(rootElement)) {
                    set(this, 'rootElement', rootElement);
                }

                rootElement = jQuery(get(this, 'rootElement'));

                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'));
                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);
                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);

                rootElement.addClass('ember-application');

                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'));

                for (event in events) {
                    if (events.hasOwnProperty(event)) {
                        this.setupHandler(rootElement, event, events[event]);
                    }
                }
            },

            /**
                    Registers an event listener on the rootElement. If the given event is
                    triggered, the provided event handler will be triggered on the target view.

                    If the target view does not implement the event handler, or if the handler
                    returns `false`, the parent view will be called. The event will continue to
                    bubble to each successive parent view until it reaches the top.

                    @private
                    @method setupHandler
                    @param {Element} rootElement
                    @param {String} event the browser-originated event to listen to
                    @param {String} eventName the name of the method to call on the view
                  */
            setupHandler: function(rootElement, event, eventName) {
                var self = this;

                rootElement.on(event + '.ember', '.ember-view', function(evt, triggeringManager) {
                    var view = View.views[this.id],
                    result = true;

                    var manager = self.canDispatchToEventManager ? self._findNearestEventManager(view, eventName) : null;

                    if (manager && manager !== triggeringManager) {
                        result = self._dispatchEvent(manager, evt, eventName, view);
                    } else if (view) {
                        result = self._bubbleEvent(view, evt, eventName);
                    }

                    return result;
                });

                rootElement.on(event + '.ember', '[data-ember-action]', function(evt) {
                    //ES6TODO: Needed for ActionHelper (generally not available in ember-views test suite)
                    if (!ActionHelper) {
                        ActionHelper = requireModule("ember-routing-handlebars/helpers/action")["ActionHelper"];
                    }

                    var actionId = jQuery(evt.currentTarget).attr('data-ember-action'),
                    action = ActionHelper.registeredActions[actionId];

                    // We have to check for action here since in some cases, jQuery will trigger
                    // an event on `removeChild` (i.e. focusout) after we've already torn down the
                    // action handlers for the view.
                    if (action && action.eventName === eventName) {
                        return action.handler(evt);
                    }
                });
            },

            _findNearestEventManager: function(view, eventName) {
                var manager = null;

                while (view) {
                    manager = get(view, 'eventManager');
                    if (manager && manager[eventName]) {
                        break;
                    }

                    view = get(view, 'parentView');
                }

                return manager;
            },

            _dispatchEvent: function(object, evt, eventName, view) {
                var result = true;

                var handler = object[eventName];
                if (typeOf(handler) === 'function') {
                    result = run(object, handler, evt, view);
                    // Do not preventDefault in eventManagers.
                    evt.stopPropagation();
                } else {
                    result = this._bubbleEvent(view, evt, eventName);
                }

                return result;
            },

            _bubbleEvent: function(view, evt, eventName) {
                return run(view, view.handleEvent, eventName, evt);
            },

            destroy: function() {
                var rootElement = get(this, 'rootElement');
                jQuery(rootElement).off('.ember', '**').removeClass('ember-application');
                return this._super();
            },

            toString: function() {
                return '(EventDisptacher)';
            }
        });
    });
    define("ember-views/system/ext",
    ["ember-metal/run_loop"],
    function(__dependency1__) {
        "use strict";
        /**
            @module ember
            @submodule ember-views
            */

        var run = __dependency1__["default"];

        // Add a new named queue for rendering views that happens
        // after bindings have synced, and a queue for scheduling actions
        // that that should occur after view rendering.
        var queues = run.queues;
        run._addQueue('render', 'actions');
        run._addQueue('afterRender', 'render');
    });
    define("ember-views/system/jquery",
    ["ember-metal/core", "ember-runtime/system/string", "ember-metal/enumerable_utils", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // Ember.assert
        var w = __dependency2__.w;

        // ES6TODO: the functions on EnumerableUtils need their own exports
        var forEach = __dependency3__.forEach;

        /**
            Ember Views

            @module ember
            @submodule ember-views
            @requires ember-runtime
            @main ember-views
            */

        var jQuery = (Ember.imports && Ember.imports.jQuery) || (this && this.jQuery);
        if (!jQuery && typeof require === 'function') {
            jQuery = require('jquery');
        }

        Ember.assert("Ember Views require jQuery between 1.7 and 2.1", jQuery && (jQuery().jquery.match(/^((1\.(7|8|9|10|11))|(2\.(0|1)))(\.\d+)?(pre|rc\d?)?/) || Ember.ENV.FORCE_JQUERY));

        /**
            @module ember
            @submodule ember-views
            */
        if (jQuery) {
            // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#dndevents
            var dragEvents = w('dragstart drag dragenter dragleave dragover drop dragend');

            // Copies the `dataTransfer` property from a browser event object onto the
            // jQuery event object for the specified events
            forEach(dragEvents, function(eventName) {
                jQuery.event.fixHooks[eventName] = {
                    props: ['dataTransfer'] 
                };
            });
        }

        __exports__["default"] = jQuery;
    });
    define("ember-views/system/render_buffer",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/property_set", "ember-views/system/utils", "ember-views/system/jquery", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
        "use strict";
        /**
            @module ember
            @submodule ember-views
            */

        var Ember = __dependency1__["default"];
        // jQuery

        var get = __dependency2__.get;
        var set = __dependency3__.set;
        var setInnerHTML = __dependency4__.setInnerHTML;
        var jQuery = __dependency5__["default"];

        function ClassSet() {
            this.seen = {};
            this.list = [];
        }

        ClassSet.prototype = {
            add: function(string) {
                if (string in this.seen) {
                    return;
                }
                this.seen[string] = true;

                this.list.push(string);
            },

            toDOM: function() {
                return this.list.join(" ");
            }
        };

        var BAD_TAG_NAME_TEST_REGEXP = /[^a-zA-Z0-9\-]/;
        var BAD_TAG_NAME_REPLACE_REGEXP = /[^a-zA-Z0-9\-]/g;

        function stripTagName(tagName) {
            if (!tagName) {
                return tagName;
            }

            if (!BAD_TAG_NAME_TEST_REGEXP.test(tagName)) {
                return tagName;
            }

            return tagName.replace(BAD_TAG_NAME_REPLACE_REGEXP, '');
        }

        var BAD_CHARS_REGEXP = /&(?!\w+;)|[<>"'`]/g;
        var POSSIBLE_CHARS_REGEXP = /[&<>"'`]/;

        function escapeAttribute(value) {
            // Stolen shamelessly from Handlebars

            var escape = {
                "<": "&lt;",
                ">": "&gt;",
                '"': "&quot;",
                "'": "&#x27;",
                "`": "&#x60;"
            };

            var escapeChar = function(chr) {
                return escape[chr] || "&amp;";
            };

            var string = value.toString();

            if (!POSSIBLE_CHARS_REGEXP.test(string)) {
                return string;
            }
            return string.replace(BAD_CHARS_REGEXP, escapeChar);
        }

        // IE 6/7 have bugs around setting names on inputs during creation.
        // From http://msdn.microsoft.com/en-us/library/ie/ms536389(v=vs.85).aspx:
        // "To include the NAME attribute at run time on objects created with the createElement method, use the eTag."
        var canSetNameOnInputs = (function() {
            var div = document.createElement('div'),
            el = document.createElement('input');

            el.setAttribute('name', 'foo');
            div.appendChild(el);

            return !!div.innerHTML.match('foo');
        })();

        /**
              `Ember.RenderBuffer` gathers information regarding the view and generates the
              final representation. `Ember.RenderBuffer` will generate HTML which can be pushed
              to the DOM.

               ```javascript
               var buffer = Ember.RenderBuffer('div');
              ```

              @class RenderBuffer
              @namespace Ember
              @constructor
              @param {String} tagName tag name (such as 'div' or 'p') used for the buffer
            */
        __exports__["default"] = function RenderBuffer(tagName) {
            return new _RenderBuffer(tagName); // jshint ignore:line
        }

        function _RenderBuffer(tagName) {
            this.tagNames = [tagName || null];
            this.buffer = "";
        }

        _RenderBuffer.prototype = {

            // The root view's element
            _element: null,

            _hasElement: true,

            /**
                    An internal set used to de-dupe class names when `addClass()` is
                    used. After each call to `addClass()`, the `classes` property
                    will be updated.

                    @private
                    @property elementClasses
                    @type Array
                    @default null
                  */
            elementClasses: null,

            /**
                    Array of class names which will be applied in the class attribute.

                    You can use `setClasses()` to set this property directly. If you
                    use `addClass()`, it will be maintained for you.

                    @property classes
                    @type Array
                    @default null
                  */
            classes: null,

            /**
                    The id in of the element, to be applied in the id attribute.

                    You should not set this property yourself, rather, you should use
                    the `id()` method of `Ember.RenderBuffer`.

                    @property elementId
                    @type String
                    @default null
                  */
            elementId: null,

            /**
                    A hash keyed on the name of the attribute and whose value will be
                    applied to that attribute. For example, if you wanted to apply a
                    `data-view="Foo.bar"` property to an element, you would set the
                    elementAttributes hash to `{'data-view':'Foo.bar'}`.

                    You should not maintain this hash yourself, rather, you should use
                    the `attr()` method of `Ember.RenderBuffer`.

                    @property elementAttributes
                    @type Hash
                    @default {}
                  */
            elementAttributes: null,

            /**
                    A hash keyed on the name of the properties and whose value will be
                    applied to that property. For example, if you wanted to apply a
                    `checked=true` property to an element, you would set the
                    elementProperties hash to `{'checked':true}`.

                    You should not maintain this hash yourself, rather, you should use
                    the `prop()` method of `Ember.RenderBuffer`.

                    @property elementProperties
                    @type Hash
                    @default {}
                  */
            elementProperties: null,

            /**
                    The tagname of the element an instance of `Ember.RenderBuffer` represents.

                    Usually, this gets set as the first parameter to `Ember.RenderBuffer`. For
                    example, if you wanted to create a `p` tag, then you would call

                    ```javascript
                    Ember.RenderBuffer('p')
                    ```

                    @property elementTag
                    @type String
                    @default null
                  */
            elementTag: null,

            /**
                    A hash keyed on the name of the style attribute and whose value will
                    be applied to that attribute. For example, if you wanted to apply a
                    `background-color:black;` style to an element, you would set the
                    elementStyle hash to `{'background-color':'black'}`.

                    You should not maintain this hash yourself, rather, you should use
                    the `style()` method of `Ember.RenderBuffer`.

                    @property elementStyle
                    @type Hash
                    @default {}
                  */
            elementStyle: null,

            /**
                    Adds a string of HTML to the `RenderBuffer`.

                    @method push
                    @param {String} string HTML to push into the buffer
                    @chainable
                  */
            push: function(string) {
                this.buffer += string;
                return this;
            },

            /**
                    Adds a class to the buffer, which will be rendered to the class attribute.

                    @method addClass
                    @param {String} className Class name to add to the buffer
                    @chainable
                  */
            addClass: function(className) {
                // lazily create elementClasses
                this.elementClasses = (this.elementClasses || new ClassSet());
                this.elementClasses.add(className);
                this.classes = this.elementClasses.list;

                return this;
            },

            setClasses: function(classNames) {
                this.elementClasses = null;
                var len = classNames.length, i;
                for (i = 0; i < len; i++) {
                    this.addClass(classNames[i]);
                }
            },

            /**
                    Sets the elementID to be used for the element.

                    @method id
                    @param {String} id
                    @chainable
                  */
            id: function(id) {
                this.elementId = id;
                return this;
            },

            // duck type attribute functionality like jQuery so a render buffer
            // can be used like a jQuery object in attribute binding scenarios.

            /**
                    Adds an attribute which will be rendered to the element.

                    @method attr
                    @param {String} name The name of the attribute
                    @param {String} value The value to add to the attribute
                    @chainable
                    @return {Ember.RenderBuffer|String} this or the current attribute value
                  */
            attr: function(name, value) {
                var attributes = this.elementAttributes = (this.elementAttributes || {});

                if (arguments.length === 1) {
                    return attributes[name];
                } else {
                    attributes[name] = value;
                }

                return this;
            },

            /**
                    Remove an attribute from the list of attributes to render.

                    @method removeAttr
                    @param {String} name The name of the attribute
                    @chainable
                  */
            removeAttr: function(name) {
                var attributes = this.elementAttributes;
                if (attributes) {
                    delete attributes[name];
                }

                return this;
            },

            /**
                    Adds a property which will be rendered to the element.

                    @method prop
                    @param {String} name The name of the property
                    @param {String} value The value to add to the property
                    @chainable
                    @return {Ember.RenderBuffer|String} this or the current property value
                  */
            prop: function(name, value) {
                var properties = this.elementProperties = (this.elementProperties || {});

                if (arguments.length === 1) {
                    return properties[name];
                } else {
                    properties[name] = value;
                }

                return this;
            },

            /**
                    Remove an property from the list of properties to render.

                    @method removeProp
                    @param {String} name The name of the property
                    @chainable
                  */
            removeProp: function(name) {
                var properties = this.elementProperties;
                if (properties) {
                    delete properties[name];
                }

                return this;
            },

            /**
                    Adds a style to the style attribute which will be rendered to the element.

                    @method style
                    @param {String} name Name of the style
                    @param {String} value
                    @chainable
                  */
            style: function(name, value) {
                this.elementStyle = (this.elementStyle || {});

                this.elementStyle[name] = value;
                return this;
            },

            begin: function(tagName) {
                this.tagNames.push(tagName || null);
                return this;
            },

            pushOpeningTag: function() {
                var tagName = this.currentTagName();
                if (!tagName) {
                    return;
                }

                if (this._hasElement && !this._element && this.buffer.length === 0) {
                    this._element = this.generateElement();
                    return;
                }

                var buffer = this.buffer,
                id = this.elementId,
                classes = this.classes,
                attrs = this.elementAttributes,
                props = this.elementProperties,
                style = this.elementStyle,
                attr, prop;

                buffer += '<' + stripTagName(tagName);

                if (id) {
                    buffer += ' id="' + escapeAttribute(id) + '"';
                    this.elementId = null;
                }
                if (classes) {
                    buffer += ' class="' + escapeAttribute(classes.join(' ')) + '"';
                    this.classes = null;
                    this.elementClasses = null;
                }

                if (style) {
                    buffer += ' style="';

                    for (prop in style) {
                        if (style.hasOwnProperty(prop)) {
                            buffer += prop + ':' + escapeAttribute(style[prop]) + ';';
                        }
                    }

                    buffer += '"';

                    this.elementStyle = null;
                }

                if (attrs) {
                    for (attr in attrs) {
                        if (attrs.hasOwnProperty(attr)) {
                            buffer += ' ' + attr + '="' + escapeAttribute(attrs[attr]) + '"';
                        }
                    }

                    this.elementAttributes = null;
                }

                if (props) {
                    for (prop in props) {
                        if (props.hasOwnProperty(prop)) {
                            var value = props[prop];
                            if (value || typeof(value) === 'number') {
                                if (value === true) {
                                    buffer += ' ' + prop + '="' + prop + '"';
                                } else {
                                    buffer += ' ' + prop + '="' + escapeAttribute(props[prop]) + '"';
                                }
                            }
                        }
                    }

                    this.elementProperties = null;
                }

                buffer += '>';
                this.buffer = buffer;
            },

            pushClosingTag: function() {
                var tagName = this.tagNames.pop();
                if (tagName) {
                    this.buffer += '</' + stripTagName(tagName) + '>';
                }
            },

            currentTagName: function() {
                return this.tagNames[this.tagNames.length-1];
            },

            generateElement: function() {
                var tagName = this.tagNames.pop(), // pop since we don't need to close
                id = this.elementId,
                classes = this.classes,
                attrs = this.elementAttributes,
                props = this.elementProperties,
                style = this.elementStyle,
                styleBuffer = '', attr, prop, tagString;

                if (attrs && attrs.name && !canSetNameOnInputs) {
                    // IE allows passing a tag to createElement. See note on `canSetNameOnInputs` above as well.
                    tagString = '<' + stripTagName(tagName) + ' name="' + escapeAttribute(attrs.name) + '">';
                } else {
                    tagString = tagName;
                }

                var element = document.createElement(tagString),
                $element = jQuery(element);

                if (id) {
                    $element.attr('id', id);
                    this.elementId = null;
                }
                if (classes) {
                    $element.attr('class', classes.join(' '));
                    this.classes = null;
                    this.elementClasses = null;
                }

                if (style) {
                    for (prop in style) {
                        if (style.hasOwnProperty(prop)) {
                            styleBuffer += (prop + ':' + style[prop] + ';');
                        }
                    }

                    $element.attr('style', styleBuffer);

                    this.elementStyle = null;
                }

                if (attrs) {
                    for (attr in attrs) {
                        if (attrs.hasOwnProperty(attr)) {
                            $element.attr(attr, attrs[attr]);
                        }
                    }

                    this.elementAttributes = null;
                }

                if (props) {
                    for (prop in props) {
                        if (props.hasOwnProperty(prop)) {
                            $element.prop(prop, props[prop]);
                        }
                    }

                    this.elementProperties = null;
                }

                return element;
            },

            /**
                    @method element
                    @return {DOMElement} The element corresponding to the generated HTML
                      of this buffer
                  */
            element: function() {
                var html = this.innerString();

                if (html) {
                    this._element = setInnerHTML(this._element, html);
                }

                return this._element;
            },

            /**
                    Generates the HTML content for this buffer.

                    @method string
                    @return {String} The generated HTML
                  */
            string: function() {
                if (this._hasElement && this._element) {
                    // Firefox versions < 11 do not have support for element.outerHTML.
                    var thisElement = this.element(), outerHTML = thisElement.outerHTML;
                    if (typeof outerHTML === 'undefined') {
                        return jQuery('<div/>').append(thisElement).html();
                    }
                    return outerHTML;
                } else {
                    return this.innerString();
                }
            },

            innerString: function() {
                return this.buffer;
            }
        };
    });
    define("ember-views/system/utils",
    ["ember-metal/core", "exports"],
    function(__dependency1__, __exports__) {
        "use strict";
        /* globals XMLSerializer */

        var Ember = __dependency1__["default"];
        // Ember.assert

        /**
            @module ember
            @submodule ember-views
            */

        /* BEGIN METAMORPH HELPERS */

        // Internet Explorer prior to 9 does not allow setting innerHTML if the first element
        // is a "zero-scope" element. This problem can be worked around by making
        // the first node an invisible text node. We, like Modernizr, use &shy;

        var needsShy = typeof document !== 'undefined' && (function() {
            var testEl = document.createElement('div');
            testEl.innerHTML = "<div></div>";
            testEl.firstChild.innerHTML = "<script></script>";
            return testEl.firstChild.innerHTML === '';
        })();

        // IE 8 (and likely earlier) likes to move whitespace preceeding
        // a script tag to appear after it. This means that we can
        // accidentally remove whitespace when updating a morph.
        var movesWhitespace = typeof document !== 'undefined' && (function() {
            var testEl = document.createElement('div');
            testEl.innerHTML = "Test: <script type='text/x-placeholder'></script>Value";
            return testEl.childNodes[0].nodeValue === 'Test:' &&
            testEl.childNodes[2].nodeValue === ' Value';
        })();

        // Use this to find children by ID instead of using jQuery
        var findChildById = function(element, id) {
            if (element.getAttribute('id') === id) {
                return element;
            }

            var len = element.childNodes.length, idx, node, found;
            for (idx = 0; idx < len; idx++) {
                node = element.childNodes[idx];
                found = node.nodeType === 1 && findChildById(node, id);
                if (found) {
                    return found;
                }
            }
        };

        var setInnerHTMLWithoutFix = function(element, html) {
            if (needsShy) {
                html = '&shy;' + html;
            }

            var matches = [];
            if (movesWhitespace) {
                // Right now we only check for script tags with ids with the
                // goal of targeting morphs.
                html = html.replace(/(\s+)(<script id='([^']+)')/g, function(match, spaces, tag, id) {
                    matches.push([id, spaces]);
                    return tag;
                });
            }

            element.innerHTML = html;

            // If we have to do any whitespace adjustments do them now
            if (matches.length > 0) {
                var len = matches.length, idx;
                for (idx = 0; idx < len; idx++) {
                    var script = findChildById(element, matches[idx][0]),
                    node = document.createTextNode(matches[idx][1]);
                    script.parentNode.insertBefore(node, script);
                }
            }

            if (needsShy) {
                var shyElement = element.firstChild;
                while (shyElement.nodeType === 1 && !shyElement.nodeName) {
                    shyElement = shyElement.firstChild;
                }
                if (shyElement.nodeType === 3 && shyElement.nodeValue.charAt(0) === "\u00AD") {
                    shyElement.nodeValue = shyElement.nodeValue.slice(1);
                }
            }
        };

        /* END METAMORPH HELPERS */


        var innerHTMLTags = {};
        var canSetInnerHTML = function(tagName) {
            if (innerHTMLTags[tagName] !== undefined) {
                return innerHTMLTags[tagName];
            }

            var canSet = true;

            // IE 8 and earlier don't allow us to do innerHTML on select
            if (tagName.toLowerCase() === 'select') {
                var el = document.createElement('select');
                setInnerHTMLWithoutFix(el, '<option value="test">Test</option>');
                canSet = el.options.length === 1;
            }

            innerHTMLTags[tagName] = canSet;

            return canSet;
        };

        function setInnerHTML(element, html) {
            var tagName = element.tagName;

            if (canSetInnerHTML(tagName)) {
                setInnerHTMLWithoutFix(element, html);
            } else {
                // Firefox versions < 11 do not have support for element.outerHTML.
                var outerHTML = element.outerHTML || new XMLSerializer().serializeToString(element);
                Ember.assert("Can't set innerHTML on " + element.tagName + " in this browser", outerHTML);

                var startTag = outerHTML.match(new RegExp("<" + tagName + "([^>]*)>", 'i'))[0],
                endTag = '</' + tagName + '>';

                var wrapper = document.createElement('div');
                setInnerHTMLWithoutFix(wrapper, startTag + html + endTag);
                element = wrapper.firstChild;
                while (element.tagName !== tagName) {
                    element = element.nextSibling;
                }
            }

            return element;
        }

        __exports__.setInnerHTML = setInnerHTML;
        function isSimpleClick(event) {
            var modifier = event.shiftKey || event.metaKey || event.altKey || event.ctrlKey,
            secondaryClick = event.which > 1; // IE9 may return undefined

            return !modifier && !secondaryClick;
        }

        __exports__.isSimpleClick = isSimpleClick;
    });
    define("ember-views/views/collection_view",
    ["ember-metal/core", "ember-metal/platform", "ember-metal/binding", "ember-metal/merge", "ember-metal/property_get", "ember-metal/property_set", "ember-runtime/system/string", "ember-views/views/container_view", "ember-views/views/core_view", "ember-views/views/view", "ember-metal/mixin", "ember-runtime/mixins/array", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __exports__) {
        "use strict";

        /**
            @module ember
            @submodule ember-views
            */

        var Ember = __dependency1__["default"];
        // Ember.assert
        var create = __dependency2__.create;
        var isGlobalPath = __dependency3__.isGlobalPath;
        var merge = __dependency4__["default"];
        var get = __dependency5__.get;
        var set = __dependency6__.set;
        var fmt = __dependency7__.fmt;
        var ContainerView = __dependency8__["default"];
        var CoreView = __dependency9__["default"];
        var View = __dependency10__["default"];
        var observer = __dependency11__.observer;
        var beforeObserver = __dependency11__.beforeObserver;
        var EmberArray = __dependency12__["default"];

        /**
              `Ember.CollectionView` is an `Ember.View` descendent responsible for managing
              a collection (an array or array-like object) by maintaining a child view object
              and associated DOM representation for each item in the array and ensuring
              that child views and their associated rendered HTML are updated when items in
              the array are added, removed, or replaced.

              ## Setting content

              The managed collection of objects is referenced as the `Ember.CollectionView`
              instance's `content` property.

              ```javascript
              someItemsView = Ember.CollectionView.create({
                content: ['A', 'B','C']
              })
              ```

              The view for each item in the collection will have its `content` property set
              to the item.

              ## Specifying itemViewClass

              By default the view class for each item in the managed collection will be an
              instance of `Ember.View`. You can supply a different class by setting the
              `CollectionView`'s `itemViewClass` property.

              Given an empty `<body>` and the following code:

              ```javascript
              someItemsView = Ember.CollectionView.create({
                classNames: ['a-collection'],
                content: ['A','B','C'],
                itemViewClass: Ember.View.extend({
                  template: Ember.Handlebars.compile("the letter: {{view.content}}")
                })
              });

              someItemsView.appendTo('body');
              ```

              Will result in the following HTML structure

              ```html
              <div class="ember-view a-collection">
                <div class="ember-view">the letter: A</div>
                <div class="ember-view">the letter: B</div>
                <div class="ember-view">the letter: C</div>
              </div>
              ```

              ## Automatic matching of parent/child tagNames

              Setting the `tagName` property of a `CollectionView` to any of
              "ul", "ol", "table", "thead", "tbody", "tfoot", "tr", or "select" will result
              in the item views receiving an appropriately matched `tagName` property.

              Given an empty `<body>` and the following code:

              ```javascript
              anUnorderedListView = Ember.CollectionView.create({
                tagName: 'ul',
                content: ['A','B','C'],
                itemViewClass: Ember.View.extend({
                  template: Ember.Handlebars.compile("the letter: {{view.content}}")
                })
              });

              anUnorderedListView.appendTo('body');
              ```

              Will result in the following HTML structure

              ```html
              <ul class="ember-view a-collection">
                <li class="ember-view">the letter: A</li>
                <li class="ember-view">the letter: B</li>
                <li class="ember-view">the letter: C</li>
              </ul>
              ```

              Additional `tagName` pairs can be provided by adding to
              `Ember.CollectionView.CONTAINER_MAP `

              ```javascript
              Ember.CollectionView.CONTAINER_MAP['article'] = 'section'
              ```

              ## Programmatic creation of child views

              For cases where additional customization beyond the use of a single
              `itemViewClass` or `tagName` matching is required CollectionView's
              `createChildView` method can be overidden:

              ```javascript
              CustomCollectionView = Ember.CollectionView.extend({
                createChildView: function(viewClass, attrs) {
                  if (attrs.content.kind == 'album') {
                    viewClass = App.AlbumView;
                  } else {
                    viewClass = App.SongView;
                  }
                  return this._super(viewClass, attrs);
                }
              });
              ```

              ## Empty View

              You can provide an `Ember.View` subclass to the `Ember.CollectionView`
              instance as its `emptyView` property. If the `content` property of a
              `CollectionView` is set to `null` or an empty array, an instance of this view
              will be the `CollectionView`s only child.

              ```javascript
              aListWithNothing = Ember.CollectionView.create({
                classNames: ['nothing']
                content: null,
                emptyView: Ember.View.extend({
                  template: Ember.Handlebars.compile("The collection is empty")
                })
              });

              aListWithNothing.appendTo('body');
              ```

              Will result in the following HTML structure

              ```html
              <div class="ember-view nothing">
                <div class="ember-view">
                  The collection is empty
                </div>
              </div>
              ```

              ## Adding and Removing items

              The `childViews` property of a `CollectionView` should not be directly
              manipulated. Instead, add, remove, replace items from its `content` property.
              This will trigger appropriate changes to its rendered HTML.


              @class CollectionView
              @namespace Ember
              @extends Ember.ContainerView
              @since Ember 0.9
            */
        var CollectionView = ContainerView.extend({

            /**
                    A list of items to be displayed by the `Ember.CollectionView`.

                    @property content
                    @type Ember.Array
                    @default null
                  */
            content: null,

            /**
                    This provides metadata about what kind of empty view class this
                    collection would like if it is being instantiated from another
                    system (like Handlebars)

                    @private
                    @property emptyViewClass
                  */
            emptyViewClass: View,

            /**
                    An optional view to display if content is set to an empty array.

                    @property emptyView
                    @type Ember.View
                    @default null
                  */
            emptyView: null,

            /**
                    @property itemViewClass
                    @type Ember.View
                    @default Ember.View
                  */
            itemViewClass: View,

            /**
                    Setup a CollectionView

                    @method init
                  */
            init: function() {
                var ret = this._super();
                this._contentDidChange();
                return ret;
            },

            /**
                    Invoked when the content property is about to change. Notifies observers that the
                    entire array content will change.

                    @private
                    @method _contentWillChange
                  */
            _contentWillChange: beforeObserver('content', function() {
                var content = this.get('content');

                if (content) {
                    content.removeArrayObserver(this);
                }
                var len = content ? get(content, 'length') : 0;
                this.arrayWillChange(content, 0, len);
            }),

            /**
                    Check to make sure that the content has changed, and if so,
                    update the children directly. This is always scheduled
                    asynchronously, to allow the element to be created before
                    bindings have synchronized and vice versa.

                    @private
                    @method _contentDidChange
                  */
            _contentDidChange: observer('content', function() {
                var content = get(this, 'content');

                if (content) {
                    this._assertArrayLike(content);
                    content.addArrayObserver(this);
                }

                var len = content ? get(content, 'length') : 0;
                this.arrayDidChange(content, 0, null, len);
            }),

            /**
                    Ensure that the content implements Ember.Array

                    @private
                    @method _assertArrayLike
                  */
            _assertArrayLike: function(content) {
                Ember.assert(fmt("an Ember.CollectionView's content must implement Ember.Array. You passed %@", [content]), EmberArray.detect(content));
            },

            /**
                    Removes the content and content observers.

                    @method destroy
                  */
            destroy: function() {
                if (!this._super()) {
                    return;
                }

                var content = get(this, 'content');
                if (content) {
                    content.removeArrayObserver(this);
                }

                if (this._createdEmptyView) {
                    this._createdEmptyView.destroy();
                }

                return this;
            },

            /**
                    Called when a mutation to the underlying content array will occur.

                    This method will remove any views that are no longer in the underlying
                    content array.

                    Invokes whenever the content array itself will change.

                    @method arrayWillChange
                    @param {Array} content the managed collection of objects
                    @param {Number} start the index at which the changes will occurr
                    @param {Number} removed number of object to be removed from content
                  */
            arrayWillChange: function(content, start, removedCount) {
                // If the contents were empty before and this template collection has an
                // empty view remove it now.
                var emptyView = get(this, 'emptyView');
                if (emptyView && emptyView instanceof View) {
                    emptyView.removeFromParent();
                }

                // Loop through child views that correspond with the removed items.
                // Note that we loop from the end of the array to the beginning because
                // we are mutating it as we go.
                var childViews = this._childViews, childView, idx, len;

                len = this._childViews.length;

                var removingAll = removedCount === len;

                if (removingAll) {
                    this.currentState.empty(this);
                    this.invokeRecursively(function(view) {
                        view.removedFromDOM = true;
                    }, false);
                }

                for (idx = start + removedCount - 1; idx >= start; idx--) {
                    childView = childViews[idx];
                    childView.destroy();
                }
            },

            /**
                    Called when a mutation to the underlying content array occurs.

                    This method will replay that mutation against the views that compose the
                    `Ember.CollectionView`, ensuring that the view reflects the model.

                    This array observer is added in `contentDidChange`.

                    @method arrayDidChange
                    @param {Array} content the managed collection of objects
                    @param {Number} start the index at which the changes occurred
                    @param {Number} removed number of object removed from content
                    @param {Number} added number of object added to content
                  */
            arrayDidChange: function(content, start, removed, added) {
                var addedViews = [], view, item, idx, len, itemViewClass,
                emptyView;

                len = content ? get(content, 'length') : 0;

                if (len) {
                    itemViewClass = get(this, 'itemViewClass');

                    if ('string' === typeof itemViewClass && isGlobalPath(itemViewClass)) {
                        itemViewClass = get(itemViewClass) || itemViewClass;
                    }

                    Ember.assert(fmt("itemViewClass must be a subclass of Ember.View, not %@",
                    [itemViewClass]),
                    'string' === typeof itemViewClass || View.detect(itemViewClass));

                    for (idx = start; idx < start + added; idx++) {
                        item = content.objectAt(idx);

                        view = this.createChildView(itemViewClass, {
                            content: item,
                            contentIndex: idx
                        });

                        addedViews.push(view);
                    }
                } else {
                    emptyView = get(this, 'emptyView');

                    if (!emptyView) {
                        return;
                    }

                    if ('string' === typeof emptyView && isGlobalPath(emptyView)) {
                        emptyView = get(emptyView) || emptyView;
                    }

                    emptyView = this.createChildView(emptyView);
                    addedViews.push(emptyView);
                    set(this, 'emptyView', emptyView);

                    if (CoreView.detect(emptyView)) {
                        this._createdEmptyView = emptyView;
                    }
                }

                this.replace(start, 0, addedViews);
            },

            /**
                    Instantiates a view to be added to the childViews array during view
                    initialization. You generally will not call this method directly unless
                    you are overriding `createChildViews()`. Note that this method will
                    automatically configure the correct settings on the new view instance to
                    act as a child of the parent.

                    The tag name for the view will be set to the tagName of the viewClass
                    passed in.

                    @method createChildView
                    @param {Class} viewClass
                    @param {Hash} [attrs] Attributes to add
                    @return {Ember.View} new instance
                  */
            createChildView: function(view, attrs) {
                view = this._super(view, attrs);

                var itemTagName = get(view, 'tagName');

                if (itemTagName === null || itemTagName === undefined) {
                    itemTagName = CollectionView.CONTAINER_MAP[get(this, 'tagName')];
                    set(view, 'tagName', itemTagName);
                }

                return view;
            }
        });

        /**
              A map of parent tags to their default child tags. You can add
              additional parent tags if you want collection views that use
              a particular parent tag to default to a child tag.

              @property CONTAINER_MAP
              @type Hash
              @static
              @final
            */
        CollectionView.CONTAINER_MAP = {
            ul: 'li',
            ol: 'li',
            table: 'tr',
            thead: 'tr',
            tbody: 'tr',
            tfoot: 'tr',
            tr: 'td',
            select: 'option'
        };

        __exports__["default"] = CollectionView;
    });
    define("ember-views/views/component",
    ["ember-metal/core", "ember-views/mixins/component_template_deprecation", "ember-runtime/mixins/target_action_support", "ember-views/views/view", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/is_none", "ember-metal/computed", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // Ember.assert, Ember.Handlebars

        var ComponentTemplateDeprecation = __dependency2__["default"];
        var TargetActionSupport = __dependency3__["default"];
        var View = __dependency4__["default"];

        var get = __dependency5__.get;
        var set = __dependency6__.set;
        var isNone = __dependency7__.isNone;

        var computed = __dependency8__.computed;

        var a_slice = Array.prototype.slice;

        /**
            @module ember
            @submodule ember-views
            */

        /**
              An `Ember.Component` is a view that is completely
              isolated. Property access in its templates go
              to the view object and actions are targeted at
              the view object. There is no access to the
              surrounding context or outer controller; all
              contextual information must be passed in.

              The easiest way to create an `Ember.Component` is via
              a template. If you name a template
              `components/my-foo`, you will be able to use
              `{{my-foo}}` in other templates, which will make
              an instance of the isolated component.

              ```handlebars
              {{app-profile person=currentUser}}
              ```

              ```handlebars
              <!-- app-profile template -->
              <h1>{{person.title}}</h1>
              <img {{bind-attr src=person.avatar}}>
              <p class='signature'>{{person.signature}}</p>
              ```

              You can use `yield` inside a template to
              include the **contents** of any block attached to
              the component. The block will be executed in the
              context of the surrounding context or outer controller:

              ```handlebars
              {{#app-profile person=currentUser}}
                <p>Admin mode</p>
                {{! Executed in the controller's context. }}
              {{/app-profile}}
              ```

              ```handlebars
              <!-- app-profile template -->
              <h1>{{person.title}}</h1>
              {{! Executed in the components context. }}
              {{yield}} {{! block contents }}
              ```

              If you want to customize the component, in order to
              handle events or actions, you implement a subclass
              of `Ember.Component` named after the name of the
              component. Note that `Component` needs to be appended to the name of
              your subclass like `AppProfileComponent`.

              For example, you could implement the action
              `hello` for the `app-profile` component:

              ```javascript
              App.AppProfileComponent = Ember.Component.extend({
                actions: {
                  hello: function(name) {
                    console.log("Hello", name);
                  }
                }
              });
              ```

              And then use it in the component's template:

              ```handlebars
              <!-- app-profile template -->

              <h1>{{person.title}}</h1>
              {{yield}} <!-- block contents -->

              <button {{action 'hello' person.name}}>
                Say Hello to {{person.name}}
              </button>
              ```

              Components must have a `-` in their name to avoid
              conflicts with built-in controls that wrap HTML
              elements. This is consistent with the same
              requirement in web components.

              @class Component
              @namespace Ember
              @extends Ember.View
            */
        var Component = View.extend(TargetActionSupport, ComponentTemplateDeprecation, {
            instrumentName: 'component',
            instrumentDisplay: computed(function() {
                if (this._debugContainerKey) {
                    return '{{' + this._debugContainerKey.split(':')[1] + '}}';
                }
            }),

            init: function() {
                this._super();
                set(this, 'origContext', get(this, 'context'));
                set(this, 'context', this);
                set(this, 'controller', this);
            },

            defaultLayout: function(context, options) {
                Ember.Handlebars.helpers['yield'].call(context, options);
            },

            /**
                  A components template property is set by passing a block
                  during its invocation. It is executed within the parent context.

                  Example:

                  ```handlebars
                  {{#my-component}}
                    // something that is run in the context
                    // of the parent context
                  {{/my-component}}
                  ```

                  Specifying a template directly to a component is deprecated without
                  also specifying the layout property.

                  @deprecated
                  @property template
                  */
            template: computed(function(key, value) {
                if (value !== undefined) {
                    return value;
                }

                var templateName = get(this, 'templateName'),
                template = this.templateForName(templateName, 'template');

                Ember.assert("You specified the templateName " + templateName + " for " + this + ", but it did not exist.", !templateName || template);

                return template || get(this, 'defaultTemplate');
            }).property('templateName'),

            /**
                  Specifying a components `templateName` is deprecated without also
                  providing the `layout` or `layoutName` properties.

                  @deprecated
                  @property templateName
                  */
            templateName: null,

            // during render, isolate keywords
            cloneKeywords: function() {
                return {
                    view: this,
                    controller: this
                };
            },

            _yield: function(context, options) {
                var view = options.data.view,
                parentView = this._parentView,
                template = get(this, 'template');

                if (template) {
                    Ember.assert("A Component must have a parent view in order to yield.", parentView);

                    view.appendChild(View, {
                        isVirtual: true,
                        tagName: '',
                        _contextView: parentView,
                        template: template,
                        context: options.data.insideGroup ? get(this, 'origContext') : get(parentView, 'context'),
                        controller: get(parentView, 'controller'),
                        templateData: {
                            keywords: parentView.cloneKeywords(),
                            insideGroup: options.data.insideGroup 
                        }
                    });
                }
            },

            /**
                    If the component is currently inserted into the DOM of a parent view, this
                    property will point to the controller of the parent view.

                    @property targetObject
                    @type Ember.Controller
                    @default null
                  */
            targetObject: computed(function(key) {
                var parentView = get(this, '_parentView');
                return parentView ? get(parentView, 'controller') : null;
            }).property('_parentView'),

            /**
                    Triggers a named action on the controller context where the component is used if
                    this controller has registered for notifications of the action.

                    For example a component for playing or pausing music may translate click events
                    into action notifications of "play" or "stop" depending on some internal state
                    of the component:


                    ```javascript
                    App.PlayButtonComponent = Ember.Component.extend({
                      click: function(){
                        if (this.get('isPlaying')) {
                          this.sendAction('play');
                        } else {
                          this.sendAction('stop');
                        }
                      }
                    });
                    ```

                    When used inside a template these component actions are configured to
                    trigger actions in the outer application context:

                    ```handlebars
                    {{! application.hbs }}
                    {{play-button play="musicStarted" stop="musicStopped"}}
                    ```

                    When the component receives a browser `click` event it translate this
                    interaction into application-specific semantics ("play" or "stop") and
                    triggers the specified action name on the controller for the template
                    where the component is used:


                    ```javascript
                    App.ApplicationController = Ember.Controller.extend({
                      actions: {
                        musicStarted: function(){
                          // called when the play button is clicked
                          // and the music started playing
                        },
                        musicStopped: function(){
                          // called when the play button is clicked
                          // and the music stopped playing
                        }
                      }
                    });
                    ```

                    If no action name is passed to `sendAction` a default name of "action"
                    is assumed.

                    ```javascript
                    App.NextButtonComponent = Ember.Component.extend({
                      click: function(){
                        this.sendAction();
                      }
                    });
                    ```

                    ```handlebars
                    {{! application.hbs }}
                    {{next-button action="playNextSongInAlbum"}}
                    ```

                    ```javascript
                    App.ApplicationController = Ember.Controller.extend({
                      actions: {
                        playNextSongInAlbum: function(){
                          ...
                        }
                      }
                    });
                    ```

                    @method sendAction
                    @param [action] {String} the action to trigger
                    @param [context] {*} a context to send with the action
                  */
            sendAction: function(action) {
                var actionName,
                contexts = a_slice.call(arguments, 1);

                // Send the default action
                if (action === undefined) {
                    actionName = get(this, 'action');
                    Ember.assert("The default action was triggered on the component " + this.toString() +
                    ", but the action name (" + actionName + ") was not a string.",
                    isNone(actionName) || typeof actionName === 'string');
                } else {
                    actionName = get(this, action);
                    Ember.assert("The " + action + " action was triggered on the component " +
                    this.toString() + ", but the action name (" + actionName +
                    ") was not a string.",
                    isNone(actionName) || typeof actionName === 'string');
                }

                // If no action name for that action could be found, just abort.
                if (actionName === undefined) {
                    return;
                }

                this.triggerAction({
                    action: actionName,
                    actionContext: contexts
                });
            }
        });

        __exports__["default"] = Component;
    });
    define("ember-views/views/container_view",
    ["ember-metal/core", "ember-metal/merge", "ember-runtime/mixins/mutable_array", "ember-metal/property_get", "ember-metal/property_set", "ember-views/views/view", "ember-views/views/view_collection", "ember-views/views/states", "ember-metal/error", "ember-metal/enumerable_utils", "ember-metal/computed", "ember-metal/run_loop", "ember-metal/properties", "ember-views/system/render_buffer", "ember-metal/mixin", "ember-runtime/system/native_array", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // Ember.assert, Ember.K

        var merge = __dependency2__["default"];
        var MutableArray = __dependency3__["default"];
        var get = __dependency4__.get;
        var set = __dependency5__.set;

        var View = __dependency6__["default"];
        var ViewCollection = __dependency7__["default"];

        var cloneStates = __dependency8__.cloneStates;
        var EmberViewStates = __dependency8__.states;

        var EmberError = __dependency9__["default"];

        var forEach = __dependency10__.forEach;

        var computed = __dependency11__.computed;
        var run = __dependency12__["default"];
        var defineProperty = __dependency13__.defineProperty;
        var renderBuffer = __dependency14__["default"];
        var observer = __dependency15__.observer;
        var beforeObserver = __dependency15__.beforeObserver;
        var emberA = __dependency16__.A;

        /**
            @module ember
            @submodule ember-views
            */

        var states = cloneStates(EmberViewStates);

        /**
              A `ContainerView` is an `Ember.View` subclass that implements `Ember.MutableArray`
              allowing programmatic management of its child views.

              ## Setting Initial Child Views

              The initial array of child views can be set in one of two ways. You can
              provide a `childViews` property at creation time that contains instance of
              `Ember.View`:

              ```javascript
              aContainer = Ember.ContainerView.create({
                childViews: [Ember.View.create(), Ember.View.create()]
              });
              ```

              You can also provide a list of property names whose values are instances of
              `Ember.View`:

              ```javascript
              aContainer = Ember.ContainerView.create({
                childViews: ['aView', 'bView', 'cView'],
                aView: Ember.View.create(),
                bView: Ember.View.create(),
                cView: Ember.View.create()
              });
              ```

              The two strategies can be combined:

              ```javascript
              aContainer = Ember.ContainerView.create({
                childViews: ['aView', Ember.View.create()],
                aView: Ember.View.create()
              });
              ```

              Each child view's rendering will be inserted into the container's rendered
              HTML in the same order as its position in the `childViews` property.

              ## Adding and Removing Child Views

              The container view implements `Ember.MutableArray` allowing programmatic management of its child views.

              To remove a view, pass that view into a `removeObject` call on the container view.

              Given an empty `<body>` the following code

              ```javascript
              aContainer = Ember.ContainerView.create({
                classNames: ['the-container'],
                childViews: ['aView', 'bView'],
                aView: Ember.View.create({
                  template: Ember.Handlebars.compile("A")
                }),
                bView: Ember.View.create({
                  template: Ember.Handlebars.compile("B")
                })
              });

              aContainer.appendTo('body');
              ```

              Results in the HTML

              ```html
              <div class="ember-view the-container">
                <div class="ember-view">A</div>
                <div class="ember-view">B</div>
              </div>
              ```

              Removing a view

              ```javascript
              aContainer.toArray();  // [aContainer.aView, aContainer.bView]
              aContainer.removeObject(aContainer.get('bView'));
              aContainer.toArray();  // [aContainer.aView]
              ```

              Will result in the following HTML

              ```html
              <div class="ember-view the-container">
                <div class="ember-view">A</div>
              </div>
              ```

              Similarly, adding a child view is accomplished by adding `Ember.View` instances to the
              container view.

              Given an empty `<body>` the following code

              ```javascript
              aContainer = Ember.ContainerView.create({
                classNames: ['the-container'],
                childViews: ['aView', 'bView'],
                aView: Ember.View.create({
                  template: Ember.Handlebars.compile("A")
                }),
                bView: Ember.View.create({
                  template: Ember.Handlebars.compile("B")
                })
              });

              aContainer.appendTo('body');
              ```

              Results in the HTML

              ```html
              <div class="ember-view the-container">
                <div class="ember-view">A</div>
                <div class="ember-view">B</div>
              </div>
              ```

              Adding a view

              ```javascript
              AnotherViewClass = Ember.View.extend({
                template: Ember.Handlebars.compile("Another view")
              });

              aContainer.toArray();  // [aContainer.aView, aContainer.bView]
              aContainer.pushObject(AnotherViewClass.create());
              aContainer.toArray(); // [aContainer.aView, aContainer.bView, <AnotherViewClass instance>]
              ```

              Will result in the following HTML

              ```html
              <div class="ember-view the-container">
                <div class="ember-view">A</div>
                <div class="ember-view">B</div>
                <div class="ember-view">Another view</div>
              </div>
              ```

              ## Templates and Layout

              A `template`, `templateName`, `defaultTemplate`, `layout`, `layoutName` or
              `defaultLayout` property on a container view will not result in the template
              or layout being rendered. The HTML contents of a `Ember.ContainerView`'s DOM
              representation will only be the rendered HTML of its child views.

              @class ContainerView
              @namespace Ember
              @extends Ember.View
            */
        var ContainerView = View.extend(MutableArray, {
            _states: states,

            init: function() {
                this._super();

                var childViews = get(this, 'childViews');

                // redefine view's childViews property that was obliterated
                defineProperty(this, 'childViews', View.childViewsProperty);

                var _childViews = this._childViews;

                forEach(childViews, function(viewName, idx) {
                    var view;

                    if ('string' === typeof viewName) {
                        view = get(this, viewName);
                        view = this.createChildView(view);
                        set(this, viewName, view);
                    } else {
                        view = this.createChildView(viewName);
                    }

                    _childViews[idx] = view;
                }, this);

                var currentView = get(this, 'currentView');
                if (currentView) {
                    if (!_childViews.length) {
                        _childViews = this._childViews = this._childViews.slice();
                    }
                    _childViews.push(this.createChildView(currentView));
                }
            },

            replace: function(idx, removedCount, addedViews) {
                var addedCount = addedViews ? get(addedViews, 'length') : 0;
                var self = this;
                Ember.assert("You can't add a child to a container - the child is already a child of another view", emberA(addedViews).every(function(item) {
                    return !get(item, '_parentView') || get(item, '_parentView') === self;
                }));

                this.arrayContentWillChange(idx, removedCount, addedCount);
                this.childViewsWillChange(this._childViews, idx, removedCount);

                if (addedCount === 0) {
                    this._childViews.splice(idx, removedCount) ;
                } else {
                    var args = [idx, removedCount].concat(addedViews);
                    if (addedViews.length && !this._childViews.length) {
                        this._childViews = this._childViews.slice();
                    }
                    this._childViews.splice.apply(this._childViews, args);
                }

                this.arrayContentDidChange(idx, removedCount, addedCount);
                this.childViewsDidChange(this._childViews, idx, removedCount, addedCount);

                return this;
            },

            objectAt: function(idx) {
                return this._childViews[idx];
            },

            length: computed(function () {
                return this._childViews.length;
            })["volatile"](),

            /**
                    Instructs each child view to render to the passed render buffer.

                    @private
                    @method render
                    @param {Ember.RenderBuffer} buffer the buffer to render to
                  */
            render: function(buffer) {
                this.forEachChildView(function(view) {
                    view.renderToBuffer(buffer);
                });
            },

            instrumentName: 'container',

            /**
                    When a child view is removed, destroy its element so that
                    it is removed from the DOM.

                    The array observer that triggers this action is set up in the
                    `renderToBuffer` method.

                    @private
                    @method childViewsWillChange
                    @param {Ember.Array} views the child views array before mutation
                    @param {Number} start the start position of the mutation
                    @param {Number} removed the number of child views removed
                  **/
            childViewsWillChange: function(views, start, removed) {
                this.propertyWillChange('childViews');

                if (removed > 0) {
                    var changedViews = views.slice(start, start + removed);
                    // transition to preRender before clearing parentView
                    this.currentState.childViewsWillChange(this, views, start, removed);
                    this.initializeViews(changedViews, null, null);
                }
            },

            removeChild: function(child) {
                this.removeObject(child);
                return this;
            },

            /**
                    When a child view is added, make sure the DOM gets updated appropriately.

                    If the view has already rendered an element, we tell the child view to
                    create an element and insert it into the DOM. If the enclosing container
                    view has already written to a buffer, but not yet converted that buffer
                    into an element, we insert the string representation of the child into the
                    appropriate place in the buffer.

                    @private
                    @method childViewsDidChange
                    @param {Ember.Array} views the array of child views after the mutation has occurred
                    @param {Number} start the start position of the mutation
                    @param {Number} removed the number of child views removed
                    @param {Number} added the number of child views added
                  */
            childViewsDidChange: function(views, start, removed, added) {
                if (added > 0) {
                    var changedViews = views.slice(start, start + added);
                    this.initializeViews(changedViews, this, get(this, 'templateData'));
                    this.currentState.childViewsDidChange(this, views, start, added);
                }
                this.propertyDidChange('childViews');
            },

            initializeViews: function(views, parentView, templateData) {
                forEach(views, function(view) {
                    set(view, '_parentView', parentView);

                    if (!view.container && parentView) {
                        set(view, 'container', parentView.container);
                    }

                    if (!get(view, 'templateData')) {
                        set(view, 'templateData', templateData);
                    }
                });
            },

            currentView: null,

            _currentViewWillChange: beforeObserver('currentView', function() {
                var currentView = get(this, 'currentView');
                if (currentView) {
                    currentView.destroy();
                }
            }),

            _currentViewDidChange: observer('currentView', function() {
                var currentView = get(this, 'currentView');
                if (currentView) {
                    Ember.assert("You tried to set a current view that already has a parent. Make sure you don't have multiple outlets in the same view.", !get(currentView, '_parentView'));
                    this.pushObject(currentView);
                }
            }),

            _ensureChildrenAreInDOM: function () {
                this.currentState.ensureChildrenAreInDOM(this);
            }
        });

        merge(states._default, {
            childViewsWillChange: Ember.K,
            childViewsDidChange: Ember.K,
            ensureChildrenAreInDOM: Ember.K
        });

        merge(states.inBuffer, {
            childViewsDidChange: function(parentView, views, start, added) {
                throw new EmberError('You cannot modify child views while in the inBuffer state');
            }
        });

        merge(states.hasElement, {
            childViewsWillChange: function(view, views, start, removed) {
                for (var i = start; i < start + removed; i++) {
                    views[i].remove();
                }
            },

            childViewsDidChange: function(view, views, start, added) {
                run.scheduleOnce('render', view, '_ensureChildrenAreInDOM');
            },

            ensureChildrenAreInDOM: function(view) {
                var childViews = view._childViews, i, len, childView, previous, buffer, viewCollection = new ViewCollection();

                for (i = 0, len = childViews.length; i < len; i++) {
                    childView = childViews[i];

                    if (!buffer) {
                        buffer = renderBuffer();
                        buffer._hasElement = false;
                    }

                    if (childView.renderToBufferIfNeeded(buffer)) {
                        viewCollection.push(childView);
                    } else if (viewCollection.length) {
                        insertViewCollection(view, viewCollection, previous, buffer);
                        buffer = null;
                        previous = childView;
                        viewCollection.clear();
                    } else {
                        previous = childView;
                    }
                }

                if (viewCollection.length) {
                    insertViewCollection(view, viewCollection, previous, buffer);
                }
            }
        });

        function insertViewCollection(view, viewCollection, previous, buffer) {
            viewCollection.triggerRecursively('willInsertElement');

            if (previous) {
                previous.domManager.after(previous, buffer.string());
            } else {
                view.domManager.prepend(view, buffer.string());
            }

            viewCollection.forEach(function(v) {
                v._transitionTo('inDOM');
                v.propertyDidChange('element');
                v.triggerRecursively('didInsertElement');
            });
        }


        __exports__["default"] = ContainerView;
    });
    define("ember-views/views/core_view",
    ["ember-views/views/states", "ember-runtime/system/object", "ember-runtime/mixins/evented", "ember-runtime/mixins/action_handler", "ember-metal/properties", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/computed", "ember-metal/utils", "ember-metal/instrumentation", "ember-views/system/render_buffer", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __exports__) {
        "use strict";
        var cloneStates = __dependency1__.cloneStates;
        var states = __dependency1__.states;
        var EmberObject = __dependency2__["default"];
        var Evented = __dependency3__["default"];
        var ActionHandler = __dependency4__["default"];

        var defineProperty = __dependency5__.defineProperty;
        var deprecateProperty = __dependency5__.deprecateProperty;
        var get = __dependency6__.get;
        var set = __dependency7__.set;
        var computed = __dependency8__.computed;

        var typeOf = __dependency9__.typeOf;

        var instrument = __dependency10__.instrument;


        var renderBuffer = __dependency11__["default"];

        /**
              `Ember.CoreView` is an abstract class that exists to give view-like behavior
              to both Ember's main view class `Ember.View` and other classes like
              `Ember._SimpleMetamorphView` that don't need the fully functionaltiy of
              `Ember.View`.

              Unless you have specific needs for `CoreView`, you will use `Ember.View`
              in your applications.

              @class CoreView
              @namespace Ember
              @extends Ember.Object
              @uses Ember.Evented
              @uses Ember.ActionHandler
            */
        var CoreView = EmberObject.extend(Evented, ActionHandler, {
            isView: true,

            _states: cloneStates(states),

            init: function() {
                this._super();
                this._transitionTo('preRender');
                this._isVisible = get(this, 'isVisible');

                deprecateProperty(this, 'states', '_states');
                deprecateProperty(this, 'state', '_state');
            },

            /**
                    If the view is currently inserted into the DOM of a parent view, this
                    property will point to the parent of the view.

                    @property parentView
                    @type Ember.View
                    @default null
                  */
            parentView: computed('_parentView', function() {
                var parent = this._parentView;

                if (parent && parent.isVirtual) {
                    return get(parent, 'parentView');
                } else {
                    return parent;
                }
            }),

            _state: null,

            _parentView: null,

            // return the current view, not including virtual views
            concreteView: computed('parentView', function() {
                if (!this.isVirtual) {
                    return this;
                } else {
                    return get(this, 'parentView.concreteView');
                }
            }),

            instrumentName: 'core_view',

            instrumentDetails: function(hash) {
                hash.object = this.toString();
                hash.containerKey = this._debugContainerKey;
                hash.view = this;
            },

            /**
                    Invoked by the view system when this view needs to produce an HTML
                    representation. This method will create a new render buffer, if needed,
                    then apply any default attributes, such as class names and visibility.
                    Finally, the `render()` method is invoked, which is responsible for
                    doing the bulk of the rendering.

                    You should not need to override this method; instead, implement the
                    `template` property, or if you need more control, override the `render`
                    method.

                    @method renderToBuffer
                    @param {Ember.RenderBuffer} buffer the render buffer. If no buffer is
                      passed, a default buffer, using the current view's `tagName`, will
                      be used.
                    @private
                  */
            renderToBuffer: function(buffer) {
                var name = 'render.' + this.instrumentName,
                details = {};

                this.instrumentDetails(details);

                return instrument(name, details, function instrumentRenderToBuffer() {
                    return this._renderToBuffer(buffer);
                }, this);
            },

            _renderToBuffer: function(_buffer) {
                // If this is the top-most view, start a new buffer. Otherwise,
                // create a new buffer relative to the original using the
                // provided buffer operation (for example, `insertAfter` will
                // insert a new buffer after the "parent buffer").
                var tagName = this.tagName;

                if (tagName === null || tagName === undefined) {
                    tagName = 'div';
                }

                var buffer = this.buffer = _buffer && _buffer.begin(tagName) || renderBuffer(tagName);
                this._transitionTo('inBuffer', false);

                this.beforeRender(buffer);
                this.render(buffer);
                this.afterRender(buffer);

                return buffer;
            },

            /**
                    Override the default event firing from `Ember.Evented` to
                    also call methods with the given name.

                    @method trigger
                    @param name {String}
                    @private
                  */
            trigger: function() {
                this._super.apply(this, arguments);
                var name = arguments[0];
                var method = this[name];
                if (method) {
                    var length = arguments.length;
                    var args = new Array(length - 1);
                    for (var i = 1; i < length; i++) {
                        args[i - 1] = arguments[i];
                    }
                    return method.apply(this, args);
                }
            },

            deprecatedSendHandles: function(actionName) {
                return !!this[actionName];
            },

            deprecatedSend: function(actionName) {
                var args = [].slice.call(arguments, 1);
                Ember.assert('' + this + " has the action " + actionName + " but it is not a function", typeof this[actionName] === 'function');
                Ember.deprecate('Action handlers implemented directly on views are deprecated in favor of action handlers on an `actions` object ( action: `' + actionName + '` on ' + this + ')', false);
                this[actionName].apply(this, args);
                return;
            },

            has: function(name) {
                return typeOf(this[name]) === 'function' || this._super(name);
            },

            destroy: function() {
                var parent = this._parentView;

                if (!this._super()) {
                    return;
                }

                // destroy the element -- this will avoid each child view destroying
                // the element over and over again...
                if (!this.removedFromDOM) {
                    this.destroyElement();
                }

                // remove from parent if found. Don't call removeFromParent,
                // as removeFromParent will try to remove the element from
                // the DOM again.
                if (parent) {
                    parent.removeChild(this);
                }

                this._transitionTo('destroying', false);

                return this;
            },

            clearRenderedChildren: Ember.K,
            triggerRecursively: Ember.K,
            invokeRecursively: Ember.K,
            _transitionTo: Ember.K,
            destroyElement: Ember.K
        });

        __exports__["default"] = CoreView;
    });
    define("ember-views/views/states",
    ["ember-metal/platform", "ember-metal/merge", "ember-views/views/states/default", "ember-views/views/states/pre_render", "ember-views/views/states/in_buffer", "ember-views/views/states/has_element", "ember-views/views/states/in_dom", "ember-views/views/states/destroying", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
        "use strict";
        var create = __dependency1__.create;
        var merge = __dependency2__["default"];
        var _default = __dependency3__["default"];
        var preRender = __dependency4__["default"];
        var inBuffer = __dependency5__["default"];
        var hasElement = __dependency6__["default"];
        var inDOM = __dependency7__["default"];
        var destroying = __dependency8__["default"];

        function cloneStates(from) {
            var into = {};

            into._default = {};
            into.preRender = create(into._default);
            into.destroying = create(into._default);
            into.inBuffer = create(into._default);
            into.hasElement = create(into._default);
            into.inDOM = create(into.hasElement);

            for (var stateName in from) {
                if (!from.hasOwnProperty(stateName)) {
                    continue;
                }
                merge(into[stateName], from[stateName]);
            }

            return into;
        }

        __exports__.cloneStates = cloneStates;
        var states = {
            _default: _default,
            preRender: preRender,
            inDOM: inDOM,
            inBuffer: inBuffer,
            hasElement: hasElement,
            destroying: destroying
        };
        __exports__.states = states;
    });
    define("ember-views/views/states/default",
    ["ember-metal/core", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/run_loop", "ember-metal/error", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // Ember.K
        var get = __dependency2__.get;
        var set = __dependency3__.set;
        var run = __dependency4__["default"];
        var EmberError = __dependency5__["default"];

        /**
            @module ember
            @submodule ember-views
            */
        __exports__["default"] = {
            // appendChild is only legal while rendering the buffer.
            appendChild: function() {
                throw new EmberError("You can't use appendChild outside of the rendering process");
            },

            $: function() {
                return undefined;
            },

            getElement: function() {
                return null;
            },

            // Handle events from `Ember.EventDispatcher`
            handleEvent: function() {
                return true; // continue event propagation
            },

            destroyElement: function(view) {
                set(view, 'element', null);
                if (view._scheduledInsert) {
                    run.cancel(view._scheduledInsert);
                    view._scheduledInsert = null;
                }
                return view;
            },

            renderToBufferIfNeeded: function () {
                return false;
            },

            rerender: Ember.K,
            invokeObserver: Ember.K
        };
    });
    define("ember-views/views/states/destroying",
    ["ember-metal/merge", "ember-metal/platform", "ember-runtime/system/string", "ember-views/views/states/default", "ember-metal/error", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
        "use strict";
        var merge = __dependency1__["default"];
        var create = __dependency2__.create;
        var fmt = __dependency3__.fmt;
        var _default = __dependency4__["default"];
        var EmberError = __dependency5__["default"];
        /**
            @module ember
            @submodule ember-views
            */

        var destroyingError = "You can't call %@ on a view being destroyed";

        var destroying = create(_default);

        merge(destroying, {
            appendChild: function() {
                throw new EmberError(fmt(destroyingError, ['appendChild']));
            },
            rerender: function() {
                throw new EmberError(fmt(destroyingError, ['rerender']));
            },
            destroyElement: function() {
                throw new EmberError(fmt(destroyingError, ['destroyElement']));
            },
            empty: function() {
                throw new EmberError(fmt(destroyingError, ['empty']));
            },

            setElement: function() {
                throw new EmberError(fmt(destroyingError, ["set('element', ...)"]));
            },

            renderToBufferIfNeeded: function() {
                return false;
            },

            // Since element insertion is scheduled, don't do anything if
            // the view has been destroyed between scheduling and execution
            insertElement: Ember.K
        });

        __exports__["default"] = destroying;
    });
    define("ember-views/views/states/has_element",
    ["ember-views/views/states/default", "ember-metal/run_loop", "ember-metal/merge", "ember-metal/platform", "ember-views/system/jquery", "ember-metal/error", "ember-metal/property_get", "ember-metal/property_set", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
        "use strict";
        var _default = __dependency1__["default"];
        var run = __dependency2__["default"];
        var merge = __dependency3__["default"];
        var create = __dependency4__.create;
        var jQuery = __dependency5__["default"];
        var EmberError = __dependency6__["default"];

        /**
            @module ember
            @submodule ember-views
            */

        var get = __dependency7__.get;
        var set = __dependency8__.set;

        var hasElement = create(_default);

        merge(hasElement, {
            $: function(view, sel) {
                var elem = get(view, 'element');
                return sel ? jQuery(sel, elem) : jQuery(elem);
            },

            getElement: function(view) {
                var parent = get(view, 'parentView');
                if (parent) {
                    parent = get(parent, 'element');
                }
                if (parent) {
                    return view.findElementInParentElement(parent);
                }
                return jQuery("#" + get(view, 'elementId'))[0];
            },

            setElement: function(view, value) {
                if (value === null) {
                    view._transitionTo('preRender');
                } else {
                    throw new EmberError("You cannot set an element to a non-null value when the element is already in the DOM.");
                }

                return value;
            },

            // once the view has been inserted into the DOM, rerendering is
            // deferred to allow bindings to synchronize.
            rerender: function(view) {
                view.triggerRecursively('willClearRender');

                view.clearRenderedChildren();

                view.domManager.replace(view);
                return view;
            },

            // once the view is already in the DOM, destroying it removes it
            // from the DOM, nukes its element, and puts it back into the
            // preRender state if inDOM.

            destroyElement: function(view) {
                view._notifyWillDestroyElement();
                view.domManager.remove(view);
                set(view, 'element', null);
                if (view._scheduledInsert) {
                    run.cancel(view._scheduledInsert);
                    view._scheduledInsert = null;
                }
                return view;
            },

            empty: function(view) {
                var _childViews = view._childViews, len, idx;
                if (_childViews) {
                    len = _childViews.length;
                    for (idx = 0; idx < len; idx++) {
                        _childViews[idx]._notifyWillDestroyElement();
                    }
                }
                view.domManager.empty(view);
            },

            // Handle events from `Ember.EventDispatcher`
            handleEvent: function(view, eventName, evt) {
                if (view.has(eventName)) {
                    // Handler should be able to re-dispatch events, so we don't
                    // preventDefault or stopPropagation.
                    return view.trigger(eventName, evt);
                } else {
                    return true; // continue event propagation
                }
            },

            invokeObserver: function(target, observer) {
                observer.call(target);
            }
        });

        __exports__["default"] = hasElement;
    });
    define("ember-views/views/states/in_buffer",
    ["ember-views/views/states/default", "ember-metal/error", "ember-metal/core", "ember-metal/platform", "ember-metal/merge", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
        "use strict";
        var _default = __dependency1__["default"];
        var EmberError = __dependency2__["default"];

        var Ember = __dependency3__["default"];
        // Ember.assert
        var create = __dependency4__.create;
        var merge = __dependency5__["default"];

        /**
            @module ember
            @submodule ember-views
            */

        var inBuffer = create(_default);

        merge(inBuffer, {
            $: function(view, sel) {
                // if we don't have an element yet, someone calling this.$() is
                // trying to update an element that isn't in the DOM. Instead,
                // rerender the view to allow the render method to reflect the
                // changes.
                view.rerender();
                return Ember.$();
            },

            // when a view is rendered in a buffer, rerendering it simply
            // replaces the existing buffer with a new one
            rerender: function(view) {
                throw new EmberError("Something you did caused a view to re-render after it rendered but before it was inserted into the DOM.");
            },

            // when a view is rendered in a buffer, appending a child
            // view will render that view and append the resulting
            // buffer into its buffer.
            appendChild: function(view, childView, options) {
                var buffer = view.buffer, _childViews = view._childViews;

                childView = view.createChildView(childView, options);
                if (!_childViews.length) {
                    _childViews = view._childViews = _childViews.slice();
                }
                _childViews.push(childView);

                childView.renderToBuffer(buffer);

                view.propertyDidChange('childViews');

                return childView;
            },

            // when a view is rendered in a buffer, destroying the
            // element will simply destroy the buffer and put the
            // state back into the preRender state.
            destroyElement: function(view) {
                view.clearBuffer();
                var viewCollection = view._notifyWillDestroyElement();
                viewCollection.transitionTo('preRender', false);

                return view;
            },

            empty: function() {
                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.");
            },

            renderToBufferIfNeeded: function (view, buffer) {
                return false;
            },

            // It should be impossible for a rendered view to be scheduled for
            // insertion.
            insertElement: function() {
                throw new EmberError("You can't insert an element that has already been rendered");
            },

            setElement: function(view, value) {
                if (value === null) {
                    view._transitionTo('preRender');
                } else {
                    view.clearBuffer();
                    view._transitionTo('hasElement');
                }

                return value;
            },

            invokeObserver: function(target, observer) {
                observer.call(target);
            }
        });

        __exports__["default"] = inBuffer;
    });
    define("ember-views/views/states/in_dom",
    ["ember-metal/core", "ember-metal/platform", "ember-metal/merge", "ember-metal/error", "ember-views/views/states/has_element", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
        "use strict";
        var Ember = __dependency1__["default"];
        // Ember.assert
        var create = __dependency2__.create;
        var merge = __dependency3__["default"];
        var EmberError = __dependency4__["default"];

        var hasElement = __dependency5__["default"];
        /**
            @module ember
            @submodule ember-views
            */

        var inDOM = create(hasElement);

        var View;

        merge(inDOM, {
            enter: function(view) {
                if (!View) {
                    View = requireModule('ember-views/views/view')["default"];
                }
                // ES6TODO: this sucks. Have to avoid cycles...

                // Register the view for event handling. This hash is used by
                // Ember.EventDispatcher to dispatch incoming events.
                if (!view.isVirtual) {
                    Ember.assert("Attempted to register a view with an id already in use: " + view.elementId, !View.views[view.elementId]);
                    View.views[view.elementId] = view;
                }

                view.addBeforeObserver('elementId', function() {
                    throw new EmberError("Changing a view's elementId after creation is not allowed");
                });
            },

            exit: function(view) {
                if (!View) {
                    View = requireModule('ember-views/views/view')["default"];
                }
                // ES6TODO: this sucks. Have to avoid cycles...

                if (!this.isVirtual) 
                    delete View.views[view.elementId];
            },

            insertElement: function(view, fn) {
                throw new EmberError("You can't insert an element into the DOM that has already been inserted");
            }
        });

        __exports__["default"] = inDOM;
    });
    define("ember-views/views/states/pre_render",
    ["ember-views/views/states/default", "ember-metal/platform", "ember-metal/merge", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        var _default = __dependency1__["default"];
        var create = __dependency2__.create;
        var merge = __dependency3__["default"];

        /**
            @module ember
            @submodule ember-views
            */
        var preRender = create(_default);

        merge(preRender, {
            // a view leaves the preRender state once its element has been
            // created (createElement).
            insertElement: function(view, fn) {
                view.createElement();
                var viewCollection = view.viewHierarchyCollection();

                viewCollection.trigger('willInsertElement');

                fn.call(view);

                // We transition to `inDOM` if the element exists in the DOM
                var element = view.get('element');
                if (document.body.contains(element)) {
                    viewCollection.transitionTo('inDOM', false);
                    viewCollection.trigger('didInsertElement');
                }
            },

            renderToBufferIfNeeded: function(view, buffer) {
                view.renderToBuffer(buffer);
                return true;
            },

            empty: Ember.K,

            setElement: function(view, value) {
                if (value !== null) {
                    view._transitionTo('hasElement');
                }
                return value;
            }
        });

        __exports__["default"] = preRender;
    });
    define("ember-views/views/view",
    ["ember-metal/core", "ember-runtime/mixins/evented", "ember-runtime/system/object", "ember-metal/error", "ember-metal/property_get", "ember-metal/property_set", "ember-metal/set_properties", "ember-metal/run_loop", "ember-metal/observer", "ember-metal/properties", "ember-metal/utils", "ember-metal/computed", "ember-metal/mixin", "ember-metal/is_none", "container/container", "ember-runtime/system/native_array", "ember-runtime/system/string", "ember-metal/enumerable_utils", "ember-runtime/copy", "ember-metal/binding", "ember-metal/property_events", "ember-views/system/jquery", "ember-views/system/ext", "ember-views/views/core_view", "ember-views/views/view_collection", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __dependency19__, __dependency20__, __dependency21__, __dependency22__, __dependency23__, __dependency24__, __dependency25__, __exports__) {
        "use strict";
        // Ember.assert, Ember.deprecate, Ember.warn, Ember.TEMPLATES,
        // Ember.K, jQuery, Ember.lookup,
        // Ember.ContainerView circular dependency
        // Ember.ENV
        var Ember = __dependency1__["default"];

        var Evented = __dependency2__["default"];
        var EmberObject = __dependency3__["default"];
        var EmberError = __dependency4__["default"];
        var get = __dependency5__.get;
        var set = __dependency6__.set;
        var setProperties = __dependency7__["default"];
        var run = __dependency8__["default"];
        var addObserver = __dependency9__.addObserver;
        var removeObserver = __dependency9__.removeObserver;

        var defineProperty = __dependency10__.defineProperty;
        var deprecateProperty = __dependency10__.deprecateProperty;
        var guidFor = __dependency11__.guidFor;
        var meta = __dependency11__.meta;
        var computed = __dependency12__.computed;
        var observer = __dependency13__.observer;

        var typeOf = __dependency11__.typeOf;
        var isArray = __dependency11__.isArray;
        var isNone = __dependency14__.isNone;
        var Mixin = __dependency13__.Mixin;
        var Container = __dependency15__["default"];
        var emberA = __dependency16__.A;

        var dasherize = __dependency17__.dasherize;

        // ES6TODO: functions on EnumerableUtils should get their own export
        var forEach = __dependency18__.forEach;
        var addObject = __dependency18__.addObject;
        var removeObject = __dependency18__.removeObject;

        var beforeObserver = __dependency13__.beforeObserver;
        var copy = __dependency19__["default"];
        var isGlobalPath = __dependency20__.isGlobalPath;

        var propertyWillChange = __dependency21__.propertyWillChange;
        var propertyDidChange = __dependency21__.propertyDidChange;

        var jQuery = __dependency22__["default"];
        // for the side effect of extending Ember.run.queues

        var CoreView = __dependency24__["default"];
        var ViewCollection = __dependency25__["default"];

        /**
            @module ember
            @submodule ember-views
            */

        var ContainerView;

        function nullViewsBuffer(view) {
            view.buffer = null;

        }

        function clearCachedElement(view) {
            meta(view).cache.element = undefined;
        }

        var childViewsProperty = computed(function() {
            var childViews = this._childViews, ret = emberA(), view = this;

            forEach(childViews, function(view) {
                var currentChildViews;
                if (view.isVirtual) {
                    if (currentChildViews = get(view, 'childViews')) {
                        ret.pushObjects(currentChildViews);
                    }
                } else {
                    ret.push(view);
                }
            });

            ret.replace = function (idx, removedCount, addedViews) {
                if (!ContainerView) {
                    ContainerView = requireModule('ember-views/views/container_view')['default'];
                }
                // ES6TODO: stupid circular dep

                if (view instanceof ContainerView) {
                    Ember.deprecate("Manipulating an Ember.ContainerView through its childViews property is deprecated. Please use the ContainerView instance itself as an Ember.MutableArray.");
                    return view.replace(idx, removedCount, addedViews);
                }
                throw new EmberError("childViews is immutable");
            };

            return ret;
        });

        Ember.warn("The VIEW_PRESERVES_CONTEXT flag has been removed and the functionality can no longer be disabled.", Ember.ENV.VIEW_PRESERVES_CONTEXT !== false);

        /**
              Global hash of shared templates. This will automatically be populated
              by the build tools so that you can store your Handlebars templates in
              separate files that get loaded into JavaScript at buildtime.

              @property TEMPLATES
              @for Ember
              @type Hash
            */
        Ember.TEMPLATES = {};

        var EMPTY_ARRAY = [];

        /**
              `Ember.View` is the class in Ember responsible for encapsulating templates of
              HTML content, combining templates with data to render as sections of a page's
              DOM, and registering and responding to user-initiated events.

              ## HTML Tag

              The default HTML tag name used for a view's DOM representation is `div`. This
              can be customized by setting the `tagName` property. The following view
              class:

              ```javascript
              ParagraphView = Ember.View.extend({
                tagName: 'em'
              });
              ```

              Would result in instances with the following HTML:

              ```html
              <em id="ember1" class="ember-view"></em>
              ```

              ## HTML `class` Attribute

              The HTML `class` attribute of a view's tag can be set by providing a
              `classNames` property that is set to an array of strings:

              ```javascript
              MyView = Ember.View.extend({
                classNames: ['my-class', 'my-other-class']
              });
              ```

              Will result in view instances with an HTML representation of:

              ```html
              <div id="ember1" class="ember-view my-class my-other-class"></div>
              ```

              `class` attribute values can also be set by providing a `classNameBindings`
              property set to an array of properties names for the view. The return value
              of these properties will be added as part of the value for the view's `class`
              attribute. These properties can be computed properties:

              ```javascript
              MyView = Ember.View.extend({
                classNameBindings: ['propertyA', 'propertyB'],
                propertyA: 'from-a',
                propertyB: function() {
                  if (someLogic) { return 'from-b'; }
                }.property()
              });
              ```

              Will result in view instances with an HTML representation of:

              ```html
              <div id="ember1" class="ember-view from-a from-b"></div>
              ```

              If the value of a class name binding returns a boolean the property name
              itself will be used as the class name if the property is true. The class name
              will not be added if the value is `false` or `undefined`.

              ```javascript
              MyView = Ember.View.extend({
                classNameBindings: ['hovered'],
                hovered: true
              });
              ```

              Will result in view instances with an HTML representation of:

              ```html
              <div id="ember1" class="ember-view hovered"></div>
              ```

              When using boolean class name bindings you can supply a string value other
              than the property name for use as the `class` HTML attribute by appending the
              preferred value after a ":" character when defining the binding:

              ```javascript
              MyView = Ember.View.extend({
                classNameBindings: ['awesome:so-very-cool'],
                awesome: true
              });
              ```

              Will result in view instances with an HTML representation of:

              ```html
              <div id="ember1" class="ember-view so-very-cool"></div>
              ```

              Boolean value class name bindings whose property names are in a
              camelCase-style format will be converted to a dasherized format:

              ```javascript
              MyView = Ember.View.extend({
                classNameBindings: ['isUrgent'],
                isUrgent: true
              });
              ```

              Will result in view instances with an HTML representation of:

              ```html
              <div id="ember1" class="ember-view is-urgent"></div>
              ```

              Class name bindings can also refer to object values that are found by
              traversing a path relative to the view itself:

              ```javascript
              MyView = Ember.View.extend({
                classNameBindings: ['messages.empty']
                messages: Ember.Object.create({
                  empty: true
                })
              });
              ```

              Will result in view instances with an HTML representation of:

              ```html
              <div id="ember1" class="ember-view empty"></div>
              ```

              If you want to add a class name for a property which evaluates to true and
              and a different class name if it evaluates to false, you can pass a binding
              like this:

              ```javascript
              // Applies 'enabled' class when isEnabled is true and 'disabled' when isEnabled is false
              Ember.View.extend({
                classNameBindings: ['isEnabled:enabled:disabled']
                isEnabled: true
              });
              ```

              Will result in view instances with an HTML representation of:

              ```html
              <div id="ember1" class="ember-view enabled"></div>
              ```

              When isEnabled is `false`, the resulting HTML reprensentation looks like
              this:

              ```html
              <div id="ember1" class="ember-view disabled"></div>
              ```

              This syntax offers the convenience to add a class if a property is `false`:

              ```javascript
              // Applies no class when isEnabled is true and class 'disabled' when isEnabled is false
              Ember.View.extend({
                classNameBindings: ['isEnabled::disabled']
                isEnabled: true
              });
              ```

              Will result in view instances with an HTML representation of:

              ```html
              <div id="ember1" class="ember-view"></div>
              ```

              When the `isEnabled` property on the view is set to `false`, it will result
              in view instances with an HTML representation of:

              ```html
              <div id="ember1" class="ember-view disabled"></div>
              ```

              Updates to the the value of a class name binding will result in automatic
              update of the  HTML `class` attribute in the view's rendered HTML
              representation. If the value becomes `false` or `undefined` the class name
              will be removed.

              Both `classNames` and `classNameBindings` are concatenated properties. See
              [Ember.Object](/api/classes/Ember.Object.html) documentation for more
              information about concatenated properties.

              ## HTML Attributes

              The HTML attribute section of a view's tag can be set by providing an
              `attributeBindings` property set to an array of property names on the view.
              The return value of these properties will be used as the value of the view's
              HTML associated attribute:

              ```javascript
              AnchorView = Ember.View.extend({
                tagName: 'a',
                attributeBindings: ['href'],
                href: 'http://google.com'
              });
              ```

              Will result in view instances with an HTML representation of:

              ```html
              <a id="ember1" class="ember-view" href="http://google.com"></a>
              ```

              One property can be mapped on to another by placing a ":" between
              the source property and the destination property:

              ```javascript
              AnchorView = Ember.View.extend({
                tagName: 'a',
                attributeBindings: ['url:href'],
                url: 'http://google.com'
              });
              ```

              Will result in view instances with an HTML representation of:

              ```html
              <a id="ember1" class="ember-view" href="http://google.com"></a>
              ```

              If the return value of an `attributeBindings` monitored property is a boolean
              the property will follow HTML's pattern of repeating the attribute's name as
              its value:

              ```javascript
              MyTextInput = Ember.View.extend({
                tagName: 'input',
                attributeBindings: ['disabled'],
                disabled: true
              });
              ```

              Will result in view instances with an HTML representation of:

              ```html
              <input id="ember1" class="ember-view" disabled="disabled" />
              ```

              `attributeBindings` can refer to computed properties:

              ```javascript
              MyTextInput = Ember.View.extend({
                tagName: 'input',
                attributeBindings: ['disabled'],
                disabled: function() {
                  if (someLogic) {
                    return true;
                  } else {
                    return false;
                  }
                }.property()
              });
              ```

              Updates to the the property of an attribute binding will result in automatic
              update of the  HTML attribute in the view's rendered HTML representation.

              `attributeBindings` is a concatenated property. See [Ember.Object](/api/classes/Ember.Object.html)
              documentation for more information about concatenated properties.

              ## Templates

              The HTML contents of a view's rendered representation are determined by its
              template. Templates can be any function that accepts an optional context
              parameter and returns a string of HTML that will be inserted within the
              view's tag. Most typically in Ember this function will be a compiled
              `Ember.Handlebars` template.

              ```javascript
              AView = Ember.View.extend({
                template: Ember.Handlebars.compile('I am the template')
              });
              ```

              Will result in view instances with an HTML representation of:

              ```html
              <div id="ember1" class="ember-view">I am the template</div>
              ```

              Within an Ember application is more common to define a Handlebars templates as
              part of a page:

              ```html
              <script type='text/x-handlebars' data-template-name='some-template'>
                Hello
              </script>
              ```

              And associate it by name using a view's `templateName` property:

              ```javascript
              AView = Ember.View.extend({
                templateName: 'some-template'
              });
              ```

              If you have nested resources, your Handlebars template will look like this:

              ```html
              <script type='text/x-handlebars' data-template-name='posts/new'>
                <h1>New Post</h1>
              </script>
              ```

              And `templateName` property:

              ```javascript
              AView = Ember.View.extend({
                templateName: 'posts/new'
              });
              ```

              Using a value for `templateName` that does not have a Handlebars template
              with a matching `data-template-name` attribute will throw an error.

              For views classes that may have a template later defined (e.g. as the block
              portion of a `{{view}}` Handlebars helper call in another template or in
              a subclass), you can provide a `defaultTemplate` property set to compiled
              template function. If a template is not later provided for the view instance
              the `defaultTemplate` value will be used:

              ```javascript
              AView = Ember.View.extend({
                defaultTemplate: Ember.Handlebars.compile('I was the default'),
                template: null,
                templateName: null
              });
              ```

              Will result in instances with an HTML representation of:

              ```html
              <div id="ember1" class="ember-view">I was the default</div>
              ```

              If a `template` or `templateName` is provided it will take precedence over
              `defaultTemplate`:

              ```javascript
              AView = Ember.View.extend({
                defaultTemplate: Ember.Handlebars.compile('I was the default')
              });

              aView = AView.create({
                template: Ember.Handlebars.compile('I was the template, not default')
              });
              ```

              Will result in the following HTML representation when rendered:

              ```html
              <div id="ember1" class="ember-view">I was the template, not default</div>
              ```

              ## View Context

              The default context of the compiled template is the view's controller:

              ```javascript
              AView = Ember.View.extend({
                template: Ember.Handlebars.compile('Hello {{excitedGreeting}}')
              });

              aController = Ember.Object.create({
                firstName: 'Barry',
                excitedGreeting: function() {
                  return this.get("content.firstName") + "!!!"
                }.property()
              });

              aView = AView.create({
                controller: aController
              });
              ```

              Will result in an HTML representation of:

              ```html
              <div id="ember1" class="ember-view">Hello Barry!!!</div>
              ```

              A context can also be explicitly supplied through the view's `context`
              property. If the view has neither `context` nor `controller` properties, the
              `parentView`'s context will be used.

              ## Layouts

              Views can have a secondary template that wraps their main template. Like
              primary templates, layouts can be any function that  accepts an optional
              context parameter and returns a string of HTML that will be inserted inside
              view's tag. Views whose HTML element is self closing (e.g. `<input />`)
              cannot have a layout and this property will be ignored.

              Most typically in Ember a layout will be a compiled `Ember.Handlebars`
              template.

              A view's layout can be set directly with the `layout` property or reference
              an existing Handlebars template by name with the `layoutName` property.

              A template used as a layout must contain a single use of the Handlebars
              `{{yield}}` helper. The HTML contents of a view's rendered `template` will be
              inserted at this location:

              ```javascript
              AViewWithLayout = Ember.View.extend({
                layout: Ember.Handlebars.compile("<div class='my-decorative-class'>{{yield}}</div>"),
                template: Ember.Handlebars.compile("I got wrapped")
              });
              ```

              Will result in view instances with an HTML representation of:

              ```html
              <div id="ember1" class="ember-view">
                <div class="my-decorative-class">
                  I got wrapped
                </div>
              </div>
              ```

              See [Ember.Handlebars.helpers.yield](/api/classes/Ember.Handlebars.helpers.html#method_yield)
              for more information.

              ## Responding to Browser Events

              Views can respond to user-initiated events in one of three ways: method
              implementation, through an event manager, and through `{{action}}` helper use
              in their template or layout.

              ### Method Implementation

              Views can respond to user-initiated events by implementing a method that
              matches the event name. A `jQuery.Event` object will be passed as the
              argument to this method.

              ```javascript
              AView = Ember.View.extend({
                click: function(event) {
                  // will be called when when an instance's
                  // rendered element is clicked
                }
              });
              ```

              ### Event Managers

              Views can define an object as their `eventManager` property. This object can
              then implement methods that match the desired event names. Matching events
              that occur on the view's rendered HTML or the rendered HTML of any of its DOM
              descendants will trigger this method. A `jQuery.Event` object will be passed
              as the first argument to the method and an  `Ember.View` object as the
              second. The `Ember.View` will be the view whose rendered HTML was interacted
              with. This may be the view with the `eventManager` property or one of its
              descendent views.

              ```javascript
              AView = Ember.View.extend({
                eventManager: Ember.Object.create({
                  doubleClick: function(event, view) {
                    // will be called when when an instance's
                    // rendered element or any rendering
                    // of this views's descendent
                    // elements is clicked
                  }
                })
              });
              ```

              An event defined for an event manager takes precedence over events of the
              same name handled through methods on the view.

              ```javascript
              AView = Ember.View.extend({
                mouseEnter: function(event) {
                  // will never trigger.
                },
                eventManager: Ember.Object.create({
                  mouseEnter: function(event, view) {
                    // takes precedence over AView#mouseEnter
                  }
                })
              });
              ```

              Similarly a view's event manager will take precedence for events of any views
              rendered as a descendent. A method name that matches an event name will not
              be called if the view instance was rendered inside the HTML representation of
              a view that has an `eventManager` property defined that handles events of the
              name. Events not handled by the event manager will still trigger method calls
              on the descendent.

              ```javascript
              OuterView = Ember.View.extend({
                template: Ember.Handlebars.compile("outer {{#view InnerView}}inner{{/view}} outer"),
                eventManager: Ember.Object.create({
                  mouseEnter: function(event, view) {
                    // view might be instance of either
                    // OuterView or InnerView depending on
                    // where on the page the user interaction occured
                  }
                })
              });

              InnerView = Ember.View.extend({
                click: function(event) {
                  // will be called if rendered inside
                  // an OuterView because OuterView's
                  // eventManager doesn't handle click events
                },
                mouseEnter: function(event) {
                  // will never be called if rendered inside
                  // an OuterView.
                }
              });
              ```

              ### Handlebars `{{action}}` Helper

              See [Handlebars.helpers.action](/api/classes/Ember.Handlebars.helpers.html#method_action).

              ### Event Names

              All of the event handling approaches described above respond to the same set
              of events. The names of the built-in events are listed below. (The hash of
              built-in events exists in `Ember.EventDispatcher`.) Additional, custom events
              can be registered by using `Ember.Application.customEvents`.

              Touch events:

              * `touchStart`
              * `touchMove`
              * `touchEnd`
              * `touchCancel`

              Keyboard events

              * `keyDown`
              * `keyUp`
              * `keyPress`

              Mouse events

              * `mouseDown`
              * `mouseUp`
              * `contextMenu`
              * `click`
              * `doubleClick`
              * `mouseMove`
              * `focusIn`
              * `focusOut`
              * `mouseEnter`
              * `mouseLeave`

              Form events:

              * `submit`
              * `change`
              * `focusIn`
              * `focusOut`
              * `input`

              HTML5 drag and drop events:

              * `dragStart`
              * `drag`
              * `dragEnter`
              * `dragLeave`
              * `dragOver`
              * `dragEnd`
              * `drop`

              ## Handlebars `{{view}}` Helper

              Other `Ember.View` instances can be included as part of a view's template by
              using the `{{view}}` Handlebars helper. See [Ember.Handlebars.helpers.view](/api/classes/Ember.Handlebars.helpers.html#method_view)
              for additional information.

              @class View
              @namespace Ember
              @extends Ember.CoreView
            */
        var View = CoreView.extend({

            concatenatedProperties: ['classNames', 'classNameBindings', 'attributeBindings'],

            /**
                    @property isView
                    @type Boolean
                    @default true
                    @static
                  */
            isView: true,

            // ..........................................................
            // TEMPLATE SUPPORT
            //

            /**
                    The name of the template to lookup if no template is provided.

                    By default `Ember.View` will lookup a template with this name in
                    `Ember.TEMPLATES` (a shared global object).

                    @property templateName
                    @type String
                    @default null
                  */
            templateName: null,

            /**
                    The name of the layout to lookup if no layout is provided.

                    By default `Ember.View` will lookup a template with this name in
                    `Ember.TEMPLATES` (a shared global object).

                    @property layoutName
                    @type String
                    @default null
                  */
            layoutName: null,

            /**
                    Used to identify this view during debugging

                    @property instrumentDisplay
                    @type String
                  */
            instrumentDisplay: computed(function() {
                if (this.helperName) {
                    return '{{' + this.helperName + '}}';
                }
            }),

            /**
                    The template used to render the view. This should be a function that
                    accepts an optional context parameter and returns a string of HTML that
                    will be inserted into the DOM relative to its parent view.

                    In general, you should set the `templateName` property instead of setting
                    the template yourself.

                    @property template
                    @type Function
                  */
            template: computed('templateName', function(key, value) {
                if (value !== undefined) {
                    return value;
                }

                var templateName = get(this, 'templateName'),
                template = this.templateForName(templateName, 'template');

                Ember.assert("You specified the templateName " + templateName + " for " + this + ", but it did not exist.", !templateName || template);

                return template || get(this, 'defaultTemplate');
            }),

            /**
                    The controller managing this view. If this property is set, it will be
                    made available for use by the template.

                    @property controller
                    @type Object
                  */
            controller: computed('_parentView', function(key) {
                var parentView = get(this, '_parentView');
                return parentView ? get(parentView, 'controller') : null;
            }),

            /**
                    A view may contain a layout. A layout is a regular template but
                    supersedes the `template` property during rendering. It is the
                    responsibility of the layout template to retrieve the `template`
                    property from the view (or alternatively, call `Handlebars.helpers.yield`,
                    `{{yield}}`) to render it in the correct location.

                    This is useful for a view that has a shared wrapper, but which delegates
                    the rendering of the contents of the wrapper to the `template` property
                    on a subclass.

                    @property layout
                    @type Function
                  */
            layout: computed(function(key) {
                var layoutName = get(this, 'layoutName'),
                layout = this.templateForName(layoutName, 'layout');

                Ember.assert("You specified the layoutName " + layoutName + " for " + this + ", but it did not exist.", !layoutName || layout);

                return layout || get(this, 'defaultLayout');
            }).property('layoutName'),

            _yield: function(context, options) {
                var template = get(this, 'template');
                if (template) {
                    template(context, options);
                }
            },

            templateForName: function(name, type) {
                if (!name) {
                    return;
                }
                Ember.assert("templateNames are not allowed to contain periods: " + name, name.indexOf('.') === -1);

                // the defaultContainer is deprecated
                var container = this.container || (Container && Container.defaultContainer);
                return container && container.lookup('template:' + name);
            },

            /**
                    The object from which templates should access properties.

                    This object will be passed to the template function each time the render
                    method is called, but it is up to the individual function to decide what
                    to do with it.

                    By default, this will be the view's controller.

                    @property context
                    @type Object
                  */
            context: computed(function(key, value) {
                if (arguments.length === 2) {
                    set(this, '_context', value);
                    return value;
                } else {
                    return get(this, '_context');
                }
            })["volatile"](),

            /**
                    Private copy of the view's template context. This can be set directly
                    by Handlebars without triggering the observer that causes the view
                    to be re-rendered.

                    The context of a view is looked up as follows:

                    1. Supplied context (usually by Handlebars)
                    2. Specified controller
                    3. `parentView`'s context (for a child of a ContainerView)

                    The code in Handlebars that overrides the `_context` property first
                    checks to see whether the view has a specified controller. This is
                    something of a hack and should be revisited.

                    @property _context
                    @private
                  */
            _context: computed(function(key) {
                var parentView, controller;

                if (controller = get(this, 'controller')) {
                    return controller;
                }

                parentView = this._parentView;
                if (parentView) {
                    return get(parentView, '_context');
                }

                return null;
            }),

            /**
                    If a value that affects template rendering changes, the view should be
                    re-rendered to reflect the new value.

                    @method _contextDidChange
                    @private
                  */
            _contextDidChange: observer('context', function() {
                this.rerender();
            }),

            /**
                    If `false`, the view will appear hidden in DOM.

                    @property isVisible
                    @type Boolean
                    @default null
                  */
            isVisible: true,

            /**
                    Array of child views. You should never edit this array directly.
                    Instead, use `appendChild` and `removeFromParent`.

                    @property childViews
                    @type Array
                    @default []
                    @private
                  */
            childViews: childViewsProperty,

            _childViews: EMPTY_ARRAY,

            // When it's a virtual view, we need to notify the parent that their
            // childViews will change.
            _childViewsWillChange: beforeObserver('childViews', function() {
                if (this.isVirtual) {
                    var parentView = get(this, 'parentView');
                    if (parentView) {
                        propertyWillChange(parentView, 'childViews');
                    }
                }
            }),

            // When it's a virtual view, we need to notify the parent that their
            // childViews did change.
            _childViewsDidChange: observer('childViews', function() {
                if (this.isVirtual) {
                    var parentView = get(this, 'parentView');
                    if (parentView) {
                        propertyDidChange(parentView, 'childViews');
                    }
                }
            }),

            /**
                    Return the nearest ancestor that is an instance of the provided
                    class.

                    @method nearestInstanceOf
                    @param {Class} klass Subclass of Ember.View (or Ember.View itself)
                    @return Ember.View
                    @deprecated
                  */
            nearestInstanceOf: function(klass) {
                Ember.deprecate("nearestInstanceOf is deprecated and will be removed from future releases. Use nearestOfType.");
                var view = get(this, 'parentView');

                while (view) {
                    if (view instanceof klass) {
                        return view;
                    }
                    view = get(view, 'parentView');
                }
            },

            /**
                    Return the nearest ancestor that is an instance of the provided
                    class or mixin.

                    @method nearestOfType
                    @param {Class,Mixin} klass Subclass of Ember.View (or Ember.View itself),
                           or an instance of Ember.Mixin.
                    @return Ember.View
                  */
            nearestOfType: function(klass) {
                var view = get(this, 'parentView'),
                isOfType = klass instanceof Mixin ?
                function(view) {
                    return klass.detect(view);
                }
                :
                function(view) {
                    return klass.detect(view.constructor);
                };

                while (view) {
                    if (isOfType(view)) {
                        return view;
                    }
                    view = get(view, 'parentView');
                }
            },

            /**
                    Return the nearest ancestor that has a given property.

                    @method nearestWithProperty
                    @param {String} property A property name
                    @return Ember.View
                  */
            nearestWithProperty: function(property) {
                var view = get(this, 'parentView');

                while (view) {
                    if (property in view) {
                        return view;
                    }
                    view = get(view, 'parentView');
                }
            },

            /**
                    Return the nearest ancestor whose parent is an instance of
                    `klass`.

                    @method nearestChildOf
                    @param {Class} klass Subclass of Ember.View (or Ember.View itself)
                    @return Ember.View
                  */
            nearestChildOf: function(klass) {
                var view = get(this, 'parentView');

                while (view) {
                    if (get(view, 'parentView') instanceof klass) {
                        return view;
                    }
                    view = get(view, 'parentView');
                }
            },

            /**
                    When the parent view changes, recursively invalidate `controller`

                    @method _parentViewDidChange
                    @private
                  */
            _parentViewDidChange: observer('_parentView', function() {
                if (this.isDestroying) {
                    return;
                }

                this.trigger('parentViewDidChange');

                if (get(this, 'parentView.controller') && !get(this, 'controller')) {
                    this.notifyPropertyChange('controller');
                }
            }),

            _controllerDidChange: observer('controller', function() {
                if (this.isDestroying) {
                    return;
                }

                this.rerender();

                this.forEachChildView(function(view) {
                    view.propertyDidChange('controller');
                });
            }),

            cloneKeywords: function() {
                var templateData = get(this, 'templateData');

                var keywords = templateData ? copy(templateData.keywords) : {};
                set(keywords, 'view', this.isVirtual ? keywords.view : this);
                set(keywords, '_view', this);
                set(keywords, 'controller', get(this, 'controller'));

                return keywords;
            },

            /**
                    Called on your view when it should push strings of HTML into a
                    `Ember.RenderBuffer`. Most users will want to override the `template`
                    or `templateName` properties instead of this method.

                    By default, `Ember.View` will look for a function in the `template`
                    property and invoke it with the value of `context`. The value of
                    `context` will be the view's controller unless you override it.

                    @method render
                    @param {Ember.RenderBuffer} buffer The render buffer
                  */
            render: function(buffer) {
                // If this view has a layout, it is the responsibility of the
                // the layout to render the view's template. Otherwise, render the template
                // directly.
                var template = get(this, 'layout') || get(this, 'template');

                if (template) {
                    var context = get(this, 'context');
                    var keywords = this.cloneKeywords();
                    var output;

                    var data = {
                        view: this,
                        buffer: buffer,
                        isRenderData: true,
                        keywords: keywords,
                        insideGroup: get(this, 'templateData.insideGroup')
                    };

                    // Invoke the template with the provided template context, which
                    // is the view's controller by default. A hash of data is also passed that provides
                    // the template with access to the view and render buffer.

                    Ember.assert('template must be a function. Did you mean to call Ember.Handlebars.compile("...") or specify templateName instead?', typeof template === 'function');
                    // The template should write directly to the render buffer instead
                    // of returning a string.
                    output = template(context, {
                        data: data 
                    });

                    // If the template returned a string instead of writing to the buffer,
                    // push the string onto the buffer.
                    if (output !== undefined) {
                        buffer.push(output);
                    }
                }
            },

            /**
                    Renders the view again. This will work regardless of whether the
                    view is already in the DOM or not. If the view is in the DOM, the
                    rendering process will be deferred to give bindings a chance
                    to synchronize.

                    If children were added during the rendering process using `appendChild`,
                    `rerender` will remove them, because they will be added again
                    if needed by the next `render`.

                    In general, if the display of your view changes, you should modify
                    the DOM element directly instead of manually calling `rerender`, which can
                    be slow.

                    @method rerender
                  */
            rerender: function() {
                return this.currentState.rerender(this);
            },

            clearRenderedChildren: function() {
                var lengthBefore = this.lengthBeforeRender,
                lengthAfter = this.lengthAfterRender;

                // If there were child views created during the last call to render(),
                // remove them under the assumption that they will be re-created when
                // we re-render.

                // VIEW-TODO: Unit test this path.
                var childViews = this._childViews;
                for (var i = lengthAfter-1; i >= lengthBefore; i--) {
                    if (childViews[i]) {
                        childViews[i].destroy();
                    }
                }
            },

            /**
                    Iterates over the view's `classNameBindings` array, inserts the value
                    of the specified property into the `classNames` array, then creates an
                    observer to update the view's element if the bound property ever changes
                    in the future.

                    @method _applyClassNameBindings
                    @private
                  */
            _applyClassNameBindings: function(classBindings) {
                var classNames = this.classNames,
                elem, newClass, dasherizedClass;

                // Loop through all of the configured bindings. These will be either
                // property names ('isUrgent') or property paths relative to the view
                // ('content.isUrgent')
                forEach(classBindings, function(binding) {

                    Ember.assert("classNameBindings must not have spaces in them. Multiple class name bindings can be provided as elements of an array, e.g. ['foo', ':bar']", binding.indexOf(' ') === -1);

                    // Variable in which the old class value is saved. The observer function
                    // closes over this variable, so it knows which string to remove when
                    // the property changes.
                    var oldClass;
                    // Extract just the property name from bindings like 'foo:bar'
                    var parsedPath = View._parsePropertyPath(binding);

                    // Set up an observer on the context. If the property changes, toggle the
                    // class name.
                    var observer = function() {
                        // Get the current value of the property
                        newClass = this._classStringForProperty(binding);
                        elem = this.$();

                        // If we had previously added a class to the element, remove it.
                        if (oldClass) {
                            elem.removeClass(oldClass);
                            // Also remove from classNames so that if the view gets rerendered,
                            // the class doesn't get added back to the DOM.
                            classNames.removeObject(oldClass);
                        }

                        // If necessary, add a new class. Make sure we keep track of it so
                        // it can be removed in the future.
                        if (newClass) {
                            elem.addClass(newClass);
                            oldClass = newClass;
                        } else {
                            oldClass = null;
                        }
                    };

                    // Get the class name for the property at its current value
                    dasherizedClass = this._classStringForProperty(binding);

                    if (dasherizedClass) {
                        // Ensure that it gets into the classNames array
                        // so it is displayed when we render.
                        addObject(classNames, dasherizedClass);

                        // Save a reference to the class name so we can remove it
                        // if the observer fires. Remember that this variable has
                        // been closed over by the observer.
                        oldClass = dasherizedClass;
                    }

                    this.registerObserver(this, parsedPath.path, observer);
                    // Remove className so when the view is rerendered,
                    // the className is added based on binding reevaluation
                    this.one('willClearRender', function() {
                        if (oldClass) {
                            classNames.removeObject(oldClass);
                            oldClass = null;
                        }
                    });

                }, this);
            },

            _unspecifiedAttributeBindings: null,

            /**
                    Iterates through the view's attribute bindings, sets up observers for each,
                    then applies the current value of the attributes to the passed render buffer.

                    @method _applyAttributeBindings
                    @param {Ember.RenderBuffer} buffer
                    @private
                  */
            _applyAttributeBindings: function(buffer, attributeBindings) {
                var attributeValue,
                unspecifiedAttributeBindings = this._unspecifiedAttributeBindings = this._unspecifiedAttributeBindings || {};

                forEach(attributeBindings, function(binding) {
                    var split = binding.split(':'),
                    property = split[0],
                    attributeName = split[1] || property;

                    if (property in this) {
                        this._setupAttributeBindingObservation(property, attributeName);

                        // Determine the current value and add it to the render buffer
                        // if necessary.
                        attributeValue = get(this, property);
                        View.applyAttributeBindings(buffer, attributeName, attributeValue);
                    } else {
                        unspecifiedAttributeBindings[property] = attributeName;
                    }
                }, this);

                // Lazily setup setUnknownProperty after attributeBindings are initially applied
                this.setUnknownProperty = this._setUnknownProperty;
            },

            _setupAttributeBindingObservation: function(property, attributeName) {
                var attributeValue, elem;

                // Create an observer to add/remove/change the attribute if the
                // JavaScript property changes.
                var observer = function() {
                    elem = this.$();

                    attributeValue = get(this, property);

                    View.applyAttributeBindings(elem, attributeName, attributeValue);
                };

                this.registerObserver(this, property, observer);
            },

            /**
                    We're using setUnknownProperty as a hook to setup attributeBinding observers for
                    properties that aren't defined on a view at initialization time.

                    Note: setUnknownProperty will only be called once for each property.

                    @method setUnknownProperty
                    @param key
                    @param value
                    @private
                  */
            setUnknownProperty: null,
            // Gets defined after initialization by _applyAttributeBindings

            _setUnknownProperty: function(key, value) {
                var attributeName = this._unspecifiedAttributeBindings && this._unspecifiedAttributeBindings[key];
                if (attributeName) {
                    this._setupAttributeBindingObservation(key, attributeName);
                }

                defineProperty(this, key);
                return set(this, key, value);
            },

            /**
                    Given a property name, returns a dasherized version of that
                    property name if the property evaluates to a non-falsy value.

                    For example, if the view has property `isUrgent` that evaluates to true,
                    passing `isUrgent` to this method will return `"is-urgent"`.

                    @method _classStringForProperty
                    @param property
                    @private
                  */
            _classStringForProperty: function(property) {
                var parsedPath = View._parsePropertyPath(property);
                var path = parsedPath.path;

                var val = get(this, path);
                if (val === undefined && isGlobalPath(path)) {
                    val = get(Ember.lookup, path);
                }

                return View._classStringForValue(path, val, parsedPath.className, parsedPath.falsyClassName);
            },

            // ..........................................................
            // ELEMENT SUPPORT
            //

            /**
                    Returns the current DOM element for the view.

                    @property element
                    @type DOMElement
                  */
            element: computed('_parentView', function(key, value) {
                if (value !== undefined) {
                    return this.currentState.setElement(this, value);
                } else {
                    return this.currentState.getElement(this);
                }
            }),

            /**
                    Returns a jQuery object for this view's element. If you pass in a selector
                    string, this method will return a jQuery object, using the current element
                    as its buffer.

                    For example, calling `view.$('li')` will return a jQuery object containing
                    all of the `li` elements inside the DOM element of this view.

                    @method $
                    @param {String} [selector] a jQuery-compatible selector string
                    @return {jQuery} the jQuery object for the DOM node
                  */
            $: function(sel) {
                return this.currentState.$(this, sel);
            },

            mutateChildViews: function(callback) {
                var childViews = this._childViews,
                idx = childViews.length,
                view;

                while (--idx >= 0) {
                    view = childViews[idx];
                    callback(this, view, idx);
                }

                return this;
            },

            forEachChildView: function(callback) {
                var childViews = this._childViews;

                if (!childViews) {
                    return this;
                }

                var len = childViews.length,
                view, idx;

                for (idx = 0; idx < len; idx++) {
                    view = childViews[idx];
                    callback(view);
                }

                return this;
            },

            /**
                    Appends the view's element to the specified parent element.

                    If the view does not have an HTML representation yet, `createElement()`
                    will be called automatically.

                    Note that this method just schedules the view to be appended; the DOM
                    element will not be appended to the given element until all bindings have
                    finished synchronizing.

                    This is not typically a function that you will need to call directly when
                    building your application. You might consider using `Ember.ContainerView`
                    instead. If you do need to use `appendTo`, be sure that the target element
                    you are providing is associated with an `Ember.Application` and does not
                    have an ancestor element that is associated with an Ember view.

                    @method appendTo
                    @param {String|DOMElement|jQuery} A selector, element, HTML string, or jQuery object
                    @return {Ember.View} receiver
                  */
            appendTo: function(target) {
                // Schedule the DOM element to be created and appended to the given
                // element after bindings have synchronized.
                this._insertElementLater(function() {
                    Ember.assert("You tried to append to (" + target + ") but that isn't in the DOM", jQuery(target).length > 0);
                    Ember.assert("You cannot append to an existing Ember.View. Consider using Ember.ContainerView instead.", !jQuery(target).is('.ember-view') && !jQuery(target).parents().is('.ember-view'));
                    this.$().appendTo(target);
                });

                return this;
            },

            /**
                    Replaces the content of the specified parent element with this view's
                    element. If the view does not have an HTML representation yet,
                    `createElement()` will be called automatically.

                    Note that this method just schedules the view to be appended; the DOM
                    element will not be appended to the given element until all bindings have
                    finished synchronizing

                    @method replaceIn
                    @param {String|DOMElement|jQuery} target A selector, element, HTML string, or jQuery object
                    @return {Ember.View} received
                  */
            replaceIn: function(target) {
                Ember.assert("You tried to replace in (" + target + ") but that isn't in the DOM", jQuery(target).length > 0);
                Ember.assert("You cannot replace an existing Ember.View. Consider using Ember.ContainerView instead.", !jQuery(target).is('.ember-view') && !jQuery(target).parents().is('.ember-view'));

                this._insertElementLater(function() {
                    jQuery(target).empty();
                    this.$().appendTo(target);
                });

                return this;
            },

            /**
                    Schedules a DOM operation to occur during the next render phase. This
                    ensures that all bindings have finished synchronizing before the view is
                    rendered.

                    To use, pass a function that performs a DOM operation.

                    Before your function is called, this view and all child views will receive
                    the `willInsertElement` event. After your function is invoked, this view
                    and all of its child views will receive the `didInsertElement` event.

                    ```javascript
                    view._insertElementLater(function() {
                      this.createElement();
                      this.$().appendTo('body');
                    });
                    ```

                    @method _insertElementLater
                    @param {Function} fn the function that inserts the element into the DOM
                    @private
                  */
            _insertElementLater: function(fn) {
                this._scheduledInsert = run.scheduleOnce('render', this, '_insertElement', fn);
            },

            _insertElement: function (fn) {
                this._scheduledInsert = null;
                this.currentState.insertElement(this, fn);
            },

            /**
                    Appends the view's element to the document body. If the view does
                    not have an HTML representation yet, `createElement()` will be called
                    automatically.

                    If your application uses the `rootElement` property, you must append
                    the view within that element. Rendering views outside of the `rootElement`
                    is not supported.

                    Note that this method just schedules the view to be appended; the DOM
                    element will not be appended to the document body until all bindings have
                    finished synchronizing.

                    @method append
                    @return {Ember.View} receiver
                  */
            append: function() {
                return this.appendTo(document.body);
            },

            /**
                    Removes the view's element from the element to which it is attached.

                    @method remove
                    @return {Ember.View} receiver
                  */
            remove: function() {
                // What we should really do here is wait until the end of the run loop
                // to determine if the element has been re-appended to a different
                // element.
                // In the interim, we will just re-render if that happens. It is more
                // important than elements get garbage collected.
                if (!this.removedFromDOM) {
                    this.destroyElement();
                }
                this.invokeRecursively(function(view) {
                    if (view.clearRenderedChildren) {
                        view.clearRenderedChildren();
                    }
                });
            },

            elementId: null,

            /**
                    Attempts to discover the element in the parent element. The default
                    implementation looks for an element with an ID of `elementId` (or the
                    view's guid if `elementId` is null). You can override this method to
                    provide your own form of lookup. For example, if you want to discover your
                    element using a CSS class name instead of an ID.

                    @method findElementInParentElement
                    @param {DOMElement} parentElement The parent's DOM element
                    @return {DOMElement} The discovered element
                  */
            findElementInParentElement: function(parentElem) {
                var id = "#" + this.elementId;
                return jQuery(id)[0] || jQuery(id, parentElem)[0];
            },

            /**
                    Creates a DOM representation of the view and all of its
                    child views by recursively calling the `render()` method.

                    After the element has been created, `didInsertElement` will
                    be called on this view and all of its child views.

                    @method createElement
                    @return {Ember.View} receiver
                  */
            createElement: function() {
                if (get(this, 'element')) {
                    return this;
                }

                var buffer = this.renderToBuffer();
                set(this, 'element', buffer.element());

                return this;
            },

            /**
                    Called when a view is going to insert an element into the DOM.

                    @event willInsertElement
                  */
            willInsertElement: Ember.K,

            /**
                    Called when the element of the view has been inserted into the DOM
                    or after the view was re-rendered. Override this function to do any
                    set up that requires an element in the document body.

                    @event didInsertElement
                  */
            didInsertElement: Ember.K,

            /**
                    Called when the view is about to rerender, but before anything has
                    been torn down. This is a good opportunity to tear down any manual
                    observers you have installed based on the DOM state

                    @event willClearRender
                  */
            willClearRender: Ember.K,

            /**
                    Run this callback on the current view (unless includeSelf is false) and recursively on child views.

                    @method invokeRecursively
                    @param fn {Function}
                    @param includeSelf {Boolean} Includes itself if true.
                    @private
                  */
            invokeRecursively: function(fn, includeSelf) {
                var childViews = (includeSelf === false) ? this._childViews : [this];
                var currentViews, view, currentChildViews;

                while (childViews.length) {
                    currentViews = childViews.slice();
                    childViews = [];

                    for (var i = 0, l = currentViews.length; i < l; i++) {
                        view = currentViews[i];
                        currentChildViews = view._childViews ? view._childViews.slice(0) : null;
                        fn(view);
                        if (currentChildViews) {
                            childViews.push.apply(childViews, currentChildViews);
                        }
                    }
                }
            },

            triggerRecursively: function(eventName) {
                var childViews = [this], currentViews, view, currentChildViews;

                while (childViews.length) {
                    currentViews = childViews.slice();
                    childViews = [];

                    for (var i = 0, l = currentViews.length; i < l; i++) {
                        view = currentViews[i];
                        currentChildViews = view._childViews ? view._childViews.slice(0) : null;
                        if (view.trigger) {
                            view.trigger(eventName);
                        }
                        if (currentChildViews) {
                            childViews.push.apply(childViews, currentChildViews);
                        }

                    }
                }
            },

            viewHierarchyCollection: function() {
                var currentView, viewCollection = new ViewCollection([this]);

                for (var i = 0; i < viewCollection.length; i++) {
                    currentView = viewCollection.objectAt(i);
                    if (currentView._childViews) {
                        viewCollection.push.apply(viewCollection, currentView._childViews);
                    }
                }

                return viewCollection;
            },

            /**
                    Destroys any existing element along with the element for any child views
                    as well. If the view does not currently have a element, then this method
                    will do nothing.

                    If you implement `willDestroyElement()` on your view, then this method will
                    be invoked on your view before your element is destroyed to give you a
                    chance to clean up any event handlers, etc.

                    If you write a `willDestroyElement()` handler, you can assume that your
                    `didInsertElement()` handler was called earlier for the same element.

                    You should not call or override this method yourself, but you may
                    want to implement the above callbacks.

                    @method destroyElement
                    @return {Ember.View} receiver
                  */
            destroyElement: function() {
                return this.currentState.destroyElement(this);
            },

            /**
                    Called when the element of the view is going to be destroyed. Override
                    this function to do any teardown that requires an element, like removing
                    event listeners.

                    @event willDestroyElement
                  */
            willDestroyElement: Ember.K,

            /**
                    Triggers the `willDestroyElement` event (which invokes the
                    `willDestroyElement()` method if it exists) on this view and all child
                    views.

                    Before triggering `willDestroyElement`, it first triggers the
                    `willClearRender` event recursively.

                    @method _notifyWillDestroyElement
                    @private
                  */
            _notifyWillDestroyElement: function() {
                var viewCollection = this.viewHierarchyCollection();
                viewCollection.trigger('willClearRender');
                viewCollection.trigger('willDestroyElement');
                return viewCollection;
            },

            /**
                    If this view's element changes, we need to invalidate the caches of our
                    child views so that we do not retain references to DOM elements that are
                    no longer needed.

                    @method _elementDidChange
                    @private
                  */
            _elementDidChange: observer('element', function() {
                this.forEachChildView(clearCachedElement);
            }),

            /**
                    Called when the parentView property has changed.

                    @event parentViewDidChange
                  */
            parentViewDidChange: Ember.K,

            instrumentName: 'view',

            instrumentDetails: function(hash) {
                hash.template = get(this, 'templateName');
                this._super(hash);
            },

            _renderToBuffer: function(buffer) {
                this.lengthBeforeRender = this._childViews.length;
                buffer = this._super(buffer);
                this.lengthAfterRender = this._childViews.length;

                return buffer;
            },

            renderToBufferIfNeeded: function (buffer) {
                return this.currentState.renderToBufferIfNeeded(this, buffer);
            },

            beforeRender: function(buffer) {
                this.applyAttributesToBuffer(buffer);
                buffer.pushOpeningTag();
            },

            afterRender: function(buffer) {
                buffer.pushClosingTag();
            },

            applyAttributesToBuffer: function(buffer) {
                // Creates observers for all registered class name and attribute bindings,
                // then adds them to the element.
                var classNameBindings = get(this, 'classNameBindings');
                if (classNameBindings.length) {
                    this._applyClassNameBindings(classNameBindings);
                }

                // Pass the render buffer so the method can apply attributes directly.
                // This isn't needed for class name bindings because they use the
                // existing classNames infrastructure.
                var attributeBindings = get(this, 'attributeBindings');
                if (attributeBindings.length) {
                    this._applyAttributeBindings(buffer, attributeBindings);
                }

                buffer.setClasses(this.classNames);
                buffer.id(this.elementId);

                var role = get(this, 'ariaRole');
                if (role) {
                    buffer.attr('role', role);
                }

                if (get(this, 'isVisible') === false) {
                    buffer.style('display', 'none');
                }
            },

            // ..........................................................
            // STANDARD RENDER PROPERTIES
            //

            /**
                    Tag name for the view's outer element. The tag name is only used when an
                    element is first created. If you change the `tagName` for an element, you
                    must destroy and recreate the view element.

                    By default, the render buffer will use a `<div>` tag for views.

                    @property tagName
                    @type String
                    @default null
                  */

            // We leave this null by default so we can tell the difference between
            // the default case and a user-specified tag.
            tagName: null,

            /**
                    The WAI-ARIA role of the control represented by this view. For example, a
                    button may have a role of type 'button', or a pane may have a role of
                    type 'alertdialog'. This property is used by assistive software to help
                    visually challenged users navigate rich web applications.

                    The full list of valid WAI-ARIA roles is available at:
                    [http://www.w3.org/TR/wai-aria/roles#roles_categorization](http://www.w3.org/TR/wai-aria/roles#roles_categorization)

                    @property ariaRole
                    @type String
                    @default null
                  */
            ariaRole: null,

            /**
                    Standard CSS class names to apply to the view's outer element. This
                    property automatically inherits any class names defined by the view's
                    superclasses as well.

                    @property classNames
                    @type Array
                    @default ['ember-view']
                  */
            classNames: ['ember-view'],

            /**
                    A list of properties of the view to apply as class names. If the property
                    is a string value, the value of that string will be applied as a class
                    name.

                    ```javascript
                    // Applies the 'high' class to the view element
                    Ember.View.extend({
                      classNameBindings: ['priority']
                      priority: 'high'
                    });
                    ```

                    If the value of the property is a Boolean, the name of that property is
                    added as a dasherized class name.

                    ```javascript
                    // Applies the 'is-urgent' class to the view element
                    Ember.View.extend({
                      classNameBindings: ['isUrgent']
                      isUrgent: true
                    });
                    ```

                    If you would prefer to use a custom value instead of the dasherized
                    property name, you can pass a binding like this:

                    ```javascript
                    // Applies the 'urgent' class to the view element
                    Ember.View.extend({
                      classNameBindings: ['isUrgent:urgent']
                      isUrgent: true
                    });
                    ```

                    This list of properties is inherited from the view's superclasses as well.

                    @property classNameBindings
                    @type Array
                    @default []
                  */
            classNameBindings: EMPTY_ARRAY,

            /**
                    A list of properties of the view to apply as attributes. If the property is
                    a string value, the value of that string will be applied as the attribute.

                    ```javascript
                    // Applies the type attribute to the element
                    // with the value "button", like <div type="button">
                    Ember.View.extend({
                      attributeBindings: ['type'],
                      type: 'button'
                    });
                    ```

                    If the value of the property is a Boolean, the name of that property is
                    added as an attribute.

                    ```javascript
                    // Renders something like <div enabled="enabled">
                    Ember.View.extend({
                      attributeBindings: ['enabled'],
                      enabled: true
                    });
                    ```

                    @property attributeBindings
                  */
            attributeBindings: EMPTY_ARRAY,

            // .......................................................
            // CORE DISPLAY METHODS
            //

            /**
                    Setup a view, but do not finish waking it up.

                    * configure `childViews`
                    * register the view with the global views hash, which is used for event
                      dispatch

                    @method init
                    @private
                  */
            init: function() {
                this.elementId = this.elementId || guidFor(this);

                this._super();

                // setup child views. be sure to clone the child views array first
                this._childViews = this._childViews.slice();

                Ember.assert("Only arrays are allowed for 'classNameBindings'", typeOf(this.classNameBindings) === 'array');
                this.classNameBindings = emberA(this.classNameBindings.slice());

                Ember.assert("Only arrays are allowed for 'classNames'", typeOf(this.classNames) === 'array');
                this.classNames = emberA(this.classNames.slice());
            },

            appendChild: function(view, options) {
                return this.currentState.appendChild(this, view, options);
            },

            /**
                    Removes the child view from the parent view.

                    @method removeChild
                    @param {Ember.View} view
                    @return {Ember.View} receiver
                  */
            removeChild: function(view) {
                // If we're destroying, the entire subtree will be
                // freed, and the DOM will be handled separately,
                // so no need to mess with childViews.
                if (this.isDestroying) {
                    return;
                }

                // update parent node
                set(view, '_parentView', null);

                // remove view from childViews array.
                var childViews = this._childViews;

                removeObject(childViews, view);

                this.propertyDidChange('childViews'); // HUH?! what happened to will change?

                return this;
            },

            /**
                    Removes all children from the `parentView`.

                    @method removeAllChildren
                    @return {Ember.View} receiver
                  */
            removeAllChildren: function() {
                return this.mutateChildViews(function(parentView, view) {
                    parentView.removeChild(view);
                });
            },

            destroyAllChildren: function() {
                return this.mutateChildViews(function(parentView, view) {
                    view.destroy();
                });
            },

            /**
                    Removes the view from its `parentView`, if one is found. Otherwise
                    does nothing.

                    @method removeFromParent
                    @return {Ember.View} receiver
                  */
            removeFromParent: function() {
                var parent = this._parentView;

                // Remove DOM element from parent
                this.remove();

                if (parent) {
                    parent.removeChild(this);
                }
                return this;
            },

            /**
                    You must call `destroy` on a view to destroy the view (and all of its
                    child views). This will remove the view from any parent node, then make
                    sure that the DOM element managed by the view can be released by the
                    memory manager.

                    @method destroy
                  */
            destroy: function() {
                var childViews = this._childViews,
                // get parentView before calling super because it'll be destroyed
                nonVirtualParentView = get(this, 'parentView'),
                viewName = this.viewName,
                childLen, i;

                if (!this._super()) {
                    return;
                }

                childLen = childViews.length;
                for (i = childLen-1; i >= 0; i--) {
                    childViews[i].removedFromDOM = true;
                }

                // remove from non-virtual parent view if viewName was specified
                if (viewName && nonVirtualParentView) {
                    nonVirtualParentView.set(viewName, null);
                }

                childLen = childViews.length;
                for (i = childLen-1; i >= 0; i--) {
                    childViews[i].destroy();
                }

                return this;
            },

            /**
                    Instantiates a view to be added to the childViews array during view
                    initialization. You generally will not call this method directly unless
                    you are overriding `createChildViews()`. Note that this method will
                    automatically configure the correct settings on the new view instance to
                    act as a child of the parent.

                    @method createChildView
                    @param {Class|String} viewClass
                    @param {Hash} [attrs] Attributes to add
                    @return {Ember.View} new instance
                  */
            createChildView: function(view, attrs) {
                if (!view) {
                    throw new TypeError("createChildViews first argument must exist");
                }

                if (view.isView && view._parentView === this && view.container === this.container) {
                    return view;
                }

                attrs = attrs || {};
                attrs._parentView = this;

                if (CoreView.detect(view)) {
                    attrs.templateData = attrs.templateData || get(this, 'templateData');

                    attrs.container = this.container;
                    view = view.create(attrs);

                    // don't set the property on a virtual view, as they are invisible to
                    // consumers of the view API
                    if (view.viewName) {
                        set(get(this, 'concreteView'), view.viewName, view);
                    }
                } else if ('string' === typeof view) {
                    var fullName = 'view:' + view;
                    var ViewKlass = this.container.lookupFactory(fullName);

                    Ember.assert("Could not find view: '" + fullName + "'", !!ViewKlass);

                    attrs.templateData = get(this, 'templateData');
                    view = ViewKlass.create(attrs);
                } else {
                    Ember.assert('You must pass instance or subclass of View', view.isView);
                    attrs.container = this.container;

                    if (!get(view, 'templateData')) {
                        attrs.templateData = get(this, 'templateData');
                    }

                    setProperties(view, attrs);

                }

                return view;
            },

            becameVisible: Ember.K,
            becameHidden: Ember.K,

            /**
                    When the view's `isVisible` property changes, toggle the visibility
                    element of the actual DOM element.

                    @method _isVisibleDidChange
                    @private
                  */
            _isVisibleDidChange: observer('isVisible', function() {
                if (this._isVisible === get(this, 'isVisible')) {
                    return ;
                }
                run.scheduleOnce('render', this, this._toggleVisibility);
            }),

            _toggleVisibility: function() {
                var $el = this.$();
                if (!$el) {
                    return;
                }

                var isVisible = get(this, 'isVisible');

                if (this._isVisible === isVisible) {
                    return ;
                }

                $el.toggle(isVisible);

                this._isVisible = isVisible;

                if (this._isAncestorHidden()) {
                    return;
                }

                if (isVisible) {
                    this._notifyBecameVisible();
                } else {
                    this._notifyBecameHidden();
                }
            },

            _notifyBecameVisible: function() {
                this.trigger('becameVisible');

                this.forEachChildView(function(view) {
                    var isVisible = get(view, 'isVisible');

                    if (isVisible || isVisible === null) {
                        view._notifyBecameVisible();
                    }
                });
            },

            _notifyBecameHidden: function() {
                this.trigger('becameHidden');
                this.forEachChildView(function(view) {
                    var isVisible = get(view, 'isVisible');

                    if (isVisible || isVisible === null) {
                        view._notifyBecameHidden();
                    }
                });
            },

            _isAncestorHidden: function() {
                var parent = get(this, 'parentView');

                while (parent) {
                    if (get(parent, 'isVisible') === false) {
                        return true;
                    }

                    parent = get(parent, 'parentView');
                }

                return false;
            },

            clearBuffer: function() {
                this.invokeRecursively(nullViewsBuffer);
            },
            transitionTo: function(state, children) {
                Ember.deprecate("Ember.View#transitionTo has been deprecated, it is for internal use only");
                this._transitionTo(state, children);
            },
            _transitionTo: function(state, children) {
                var priorState = this.currentState;
                var currentState = this.currentState = this._states[state];

                this._state = state;

                if (priorState && priorState.exit) {
                    priorState.exit(this);
                }
                if (currentState.enter) {
                    currentState.enter(this);
                }
                if (state === 'inDOM') {
                    meta(this).cache.element = undefined;
                }

                if (children !== false) {
                    this.forEachChildView(function(view) {
                        view._transitionTo(state);
                    });
                }
            },

            // .......................................................
            // EVENT HANDLING
            //

            /**
                    Handle events from `Ember.EventDispatcher`

                    @method handleEvent
                    @param eventName {String}
                    @param evt {Event}
                    @private
                  */
            handleEvent: function(eventName, evt) {
                return this.currentState.handleEvent(this, eventName, evt);
            },

            registerObserver: function(root, path, target, observer) {
                if (!observer && 'function' === typeof target) {
                    observer = target;
                    target = null;
                }

                if (!root || typeof root !== 'object') {
                    return;
                }

                var view = this,
                stateCheckedObserver = function() {
                    view.currentState.invokeObserver(this, observer);
                },
                scheduledObserver = function() {
                    run.scheduleOnce('render', this, stateCheckedObserver);
                };

                addObserver(root, path, target, scheduledObserver);

                this.one('willClearRender', function() {
                    removeObserver(root, path, target, scheduledObserver);
                });
            }

        });

        /*
              Describe how the specified actions should behave in the various
              states that a view can exist in. Possible states:

              * preRender: when a view is first instantiated, and after its
                element was destroyed, it is in the preRender state
              * inBuffer: once a view has been rendered, but before it has
                been inserted into the DOM, it is in the inBuffer state
              * hasElement: the DOM representation of the view is created,
                and is ready to be inserted
              * inDOM: once a view has been inserted into the DOM it is in
                the inDOM state. A view spends the vast majority of its
                existence in this state.
              * destroyed: once a view has been destroyed (using the destroy
                method), it is in this state. No further actions can be invoked
                on a destroyed view.
            */

        // in the destroyed state, everything is illegal

        // before rendering has begun, all legal manipulations are noops.

        // inside the buffer, legal manipulations are done on the buffer

        // once the view has been inserted into the DOM, legal manipulations
        // are done on the DOM element.

        function notifyMutationListeners() {
            run.once(View, 'notifyMutationListeners');
        }

        var DOMManager = {
            prepend: function(view, html) {
                view.$().prepend(html);
                notifyMutationListeners();
            },

            after: function(view, html) {
                view.$().after(html);
                notifyMutationListeners();
            },

            html: function(view, html) {
                view.$().html(html);
                notifyMutationListeners();
            },

            replace: function(view) {
                var element = get(view, 'element');

                set(view, 'element', null);

                view._insertElementLater(function() {
                    jQuery(element).replaceWith(get(view, 'element'));
                    notifyMutationListeners();
                });
            },

            remove: function(view) {
                view.$().remove();
                notifyMutationListeners();
            },

            empty: function(view) {
                view.$().empty();
                notifyMutationListeners();
            }
        };

        View.reopen({
            domManager: DOMManager
        });

        View.reopenClass({

            /**
                    Parse a path and return an object which holds the parsed properties.

                    For example a path like "content.isEnabled:enabled:disabled" will return the
                    following object:

                    ```javascript
                    {
                      path: "content.isEnabled",
                      className: "enabled",
                      falsyClassName: "disabled",
                      classNames: ":enabled:disabled"
                    }
                    ```

                    @method _parsePropertyPath
                    @static
                    @private
                  */
            _parsePropertyPath: function(path) {
                var split = path.split(':'),
                propertyPath = split[0],
                classNames = "",
                className,
                falsyClassName;

                // check if the property is defined as prop:class or prop:trueClass:falseClass
                if (split.length > 1) {
                    className = split[1];
                    if (split.length === 3) {
                        falsyClassName = split[2];
                    }

                    classNames = ':' + className;
                    if (falsyClassName) {
                        classNames += ":" + falsyClassName;
                    }
                }

                return {
                    path: propertyPath,
                    classNames: classNames,
                    className: (className === '') ? undefined : className,
                    falsyClassName: falsyClassName
                };
            },

            /**
                    Get the class name for a given value, based on the path, optional
                    `className` and optional `falsyClassName`.

                    - if a `className` or `falsyClassName` has been specified:
                      - if the value is truthy and `className` has been specified,
                        `className` is returned
                      - if the value is falsy and `falsyClassName` has been specified,
                        `falsyClassName` is returned
                      - otherwise `null` is returned
                    - if the value is `true`, the dasherized last part of the supplied path
                      is returned
                    - if the value is not `false`, `undefined` or `null`, the `value`
                      is returned
                    - if none of the above rules apply, `null` is returned

                    @method _classStringForValue
                    @param path
                    @param val
                    @param className
                    @param falsyClassName
                    @static
                    @private
                  */
            _classStringForValue: function(path, val, className, falsyClassName) {
                if (isArray(val)) {
                    val = get(val, 'length') !== 0;
                }

                // When using the colon syntax, evaluate the truthiness or falsiness
                // of the value to determine which className to return
                if (className || falsyClassName) {
                    if (className && !!val) {
                        return className;

                    } else if (falsyClassName && !val) {
                        return falsyClassName;

                    } else {
                        return null;
                    }

                    // If value is a Boolean and true, return the dasherized property
                    // name.
                } else if (val === true) {
                    // Normalize property path to be suitable for use
                    // as a class name. For exaple, content.foo.barBaz
                    // becomes bar-baz.
                    var parts = path.split('.');
                    return dasherize(parts[parts.length-1]);

                    // If the value is not false, undefined, or null, return the current
                    // value of the property.
                } else if (val !== false && val != null) {
                    return val;

                    // Nothing to display. Return null so that the old class is removed
                    // but no new class is added.
                } else {
                    return null;
                }
            }
        });

        var mutation = EmberObject.extend(Evented).create();

        View.addMutationListener = function(callback) {
            mutation.on('change', callback);
        };

        View.removeMutationListener = function(callback) {
            mutation.off('change', callback);
        };

        View.notifyMutationListeners = function() {
            mutation.trigger('change');
        };

        /**
              Global views hash

              @property views
              @static
              @type Hash
            */
        View.views = {};

        // If someone overrides the child views computed property when
        // defining their class, we want to be able to process the user's
        // supplied childViews and then restore the original computed property
        // at view initialization time. This happens in Ember.ContainerView's init
        // method.
        View.childViewsProperty = childViewsProperty;

        View.applyAttributeBindings = function(elem, name, value) {
            var type = typeOf(value);

            // if this changes, also change the logic in ember-handlebars/lib/helpers/binding.js
            if (name !== 'value' && (type === 'string' || (type === 'number' && !isNaN(value)))) {
                if (value !== elem.attr(name)) {
                    elem.attr(name, value);
                }
            } else if (name === 'value' || type === 'boolean') {
                if (isNone(value) || value === false) {
                    // `null`, `undefined` or `false` should remove attribute
                    elem.removeAttr(name);
                    // In IE8 `prop` couldn't remove attribute when name is `required`.
                    if (name === 'required') {
                        elem.removeProp(name);
                    } else {
                        elem.prop(name, '');
                    }
                } else if (value !== elem.prop(name)) {
                    // value should always be properties
                    elem.prop(name, value);
                }
            } else if (!value) {
                elem.removeAttr(name);
            }
        };

        __exports__["default"] = View;
    });
    define("ember-views/views/view_collection",
    ["ember-metal/enumerable_utils", "exports"],
    function(__dependency1__, __exports__) {
        "use strict";
        var forEach = __dependency1__.forEach;

        function ViewCollection(initialViews) {
            var views = this.views = initialViews || [];
            this.length = views.length;
        }

        ViewCollection.prototype = {
            length: 0,

            trigger: function(eventName) {
                var views = this.views, view;
                for (var i = 0, l = views.length; i < l; i++) {
                    view = views[i];
                    if (view.trigger) {
                        view.trigger(eventName);
                    }
                }
            },

            triggerRecursively: function(eventName) {
                var views = this.views;
                for (var i = 0, l = views.length; i < l; i++) {
                    views[i].triggerRecursively(eventName);
                }
            },

            invokeRecursively: function(fn) {
                var views = this.views, view;

                for (var i = 0, l = views.length; i < l; i++) {
                    view = views[i];
                    fn(view);
                }
            },

            transitionTo: function(state, children) {
                var views = this.views;
                for (var i = 0, l = views.length; i < l; i++) {
                    views[i]._transitionTo(state, children);
                }
            },

            push: function() {
                this.length += arguments.length;
                var views = this.views;
                return views.push.apply(views, arguments);
            },

            objectAt: function(idx) {
                return this.views[idx];
            },

            forEach: function(callback) {
                var views = this.views;
                return forEach(views, callback);
            },

            clear: function() {
                this.length = 0;
                this.views.length = 0;
            }
        };

        __exports__["default"] = ViewCollection;
    });
    define("ember",
    ["ember-metal", "ember-runtime", "ember-handlebars", "ember-views", "ember-routing", "ember-routing-handlebars", "ember-application", "ember-extension-support"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__) {
        "use strict";
        // require the main entry points for each of these packages
        // this is so that the global exports occur properly

        // do this to ensure that Ember.Test is defined properly on the global
        // if it is present.
        if (Ember.__loader.registry['ember-testing']) {
            requireModule('ember-testing');
        }

        /**
            Ember

            @module ember
            */

        function throwWithMessage(msg) {
            return function() {
                throw new Ember.Error(msg);
            };
        }

        function generateRemovedClass(className) {
            var msg = " has been moved into a plugin: https://github.com/emberjs/ember-states";

            return {
                extend: throwWithMessage(className + msg),
                create: throwWithMessage(className + msg)
            };
        }

        Ember.StateManager = generateRemovedClass("Ember.StateManager");

        /**
              This was exported to ember-states plugin for v 1.0.0 release. See: https://github.com/emberjs/ember-states

              @class StateManager
              @namespace Ember
            */

        Ember.State = generateRemovedClass("Ember.State");

        /**
              This was exported to ember-states plugin for v 1.0.0 release. See: https://github.com/emberjs/ember-states

              @class State
              @namespace Ember
            */
    });
    define("metamorph",
    [],
    function() {
        "use strict";
        // ==========================================================================
        // Project:   metamorph
        // Copyright: ©2014 Tilde, Inc. All rights reserved.
        // ==========================================================================

        var K = function() {},
        guid = 0,
        disableRange = (function() {
            if ('undefined' !== typeof MetamorphENV) {
                return MetamorphENV.DISABLE_RANGE_API;
            } else if ('undefined' !== ENV) {
                return ENV.DISABLE_RANGE_API;
            } else {
                return false;
            }
        })(),
        // Feature-detect the W3C range API, the extended check is for IE9 which only partially supports ranges
        supportsRange = (!disableRange) && typeof document !== 'undefined' && ('createRange' in document) && (typeof Range !== 'undefined') && Range.prototype.createContextualFragment,
        // Internet Explorer prior to 9 does not allow setting innerHTML if the first element
        // is a "zero-scope" element. This problem can be worked around by making
        // the first node an invisible text node. We, like Modernizr, use &shy;
        needsShy = typeof document !== 'undefined' && (function() {
            var testEl = document.createElement('div');
            testEl.innerHTML = "<div></div>";
            testEl.firstChild.innerHTML = "<script></script>";
            return testEl.firstChild.innerHTML === '';
        })(),

        // IE 8 (and likely earlier) likes to move whitespace preceeding
        // a script tag to appear after it. This means that we can
        // accidentally remove whitespace when updating a morph.
        movesWhitespace = document && (function() {
            var testEl = document.createElement('div');
            testEl.innerHTML = "Test: <script type='text/x-placeholder'></script>Value";
            return testEl.childNodes[0].nodeValue === 'Test:' &&
            testEl.childNodes[2].nodeValue === ' Value';
        })();

        // Constructor that supports either Metamorph('foo') or new
        // Metamorph('foo');
        //
        // Takes a string of HTML as the argument.

        var Metamorph = function(html) {
            var self;

            if (this instanceof Metamorph) {
                self = this;
            } else {
                self = new K();
            }

            self.innerHTML = html;
            var myGuid = 'metamorph-' + (guid++);
            self.start = myGuid + '-start';
            self.end = myGuid + '-end';

            return self;
        };

        K.prototype = Metamorph.prototype;

        var rangeFor, htmlFunc, removeFunc, outerHTMLFunc, appendToFunc, afterFunc, prependFunc, startTagFunc, endTagFunc;

        outerHTMLFunc = function() {
            return this.startTag() + this.innerHTML + this.endTag();
        };

        startTagFunc = function() {
            /*
                   * We replace chevron by its hex code in order to prevent escaping problems.
                   * Check this thread for more explaination:
                   * http://stackoverflow.com/questions/8231048/why-use-x3c-instead-of-when-generating-html-from-javascript
                   */
            return "<script id='" + this.start + "' type='text/x-placeholder'>\x3C/script>";
        };

        endTagFunc = function() {
            /*
                   * We replace chevron by its hex code in order to prevent escaping problems.
                   * Check this thread for more explaination:
                   * http://stackoverflow.com/questions/8231048/why-use-x3c-instead-of-when-generating-html-from-javascript
                   */
            return "<script id='" + this.end + "' type='text/x-placeholder'>\x3C/script>";
        };

        // If we have the W3C range API, this process is relatively straight forward.
        if (supportsRange) {

            // Get a range for the current morph. Optionally include the starting and
            // ending placeholders.
            rangeFor = function(morph, outerToo) {
                var range = document.createRange();
                var before = document.getElementById(morph.start);
                var after = document.getElementById(morph.end);

                if (outerToo) {
                    range.setStartBefore(before);
                    range.setEndAfter(after);
                } else {
                    range.setStartAfter(before);
                    range.setEndBefore(after);
                }

                return range;
            };

            htmlFunc = function(html, outerToo) {
                // get a range for the current metamorph object
                var range = rangeFor(this, outerToo);

                // delete the contents of the range, which will be the
                // nodes between the starting and ending placeholder.
                range.deleteContents();

                // create a new document fragment for the HTML
                var fragment = range.createContextualFragment(html);

                // insert the fragment into the range
                range.insertNode(fragment);
            };

            /**
                  * @public
                  *
                  * Remove this object (including starting and ending
                  * placeholders).
                  *
                  * @method remove
                  */
            removeFunc = function() {
                // get a range for the current metamorph object including
                // the starting and ending placeholders.
                var range = rangeFor(this, true);

                // delete the entire range.
                range.deleteContents();
            };

            appendToFunc = function(node) {
                var range = document.createRange();
                range.setStart(node);
                range.collapse(false);
                var frag = range.createContextualFragment(this.outerHTML());
                node.appendChild(frag);
            };

            afterFunc = function(html) {
                var range = document.createRange();
                var after = document.getElementById(this.end);

                range.setStartAfter(after);
                range.setEndAfter(after);

                var fragment = range.createContextualFragment(html);
                range.insertNode(fragment);
            };

            prependFunc = function(html) {
                var range = document.createRange();
                var start = document.getElementById(this.start);

                range.setStartAfter(start);
                range.setEndAfter(start);

                var fragment = range.createContextualFragment(html);
                range.insertNode(fragment);
            };

        } else {
            /*
                   * This code is mostly taken from jQuery, with one exception. In jQuery's case, we
                   * have some HTML and we need to figure out how to convert it into some nodes.
                   *
                   * In this case, jQuery needs to scan the HTML looking for an opening tag and use
                   * that as the key for the wrap map. In our case, we know the parent node, and
                   * can use its type as the key for the wrap map.
                   **/
            Metamorph._wrapMap = {
                select: [ 1, "<select multiple='multiple'>", "</select>" ],
                fieldset: [ 1, "<fieldset>", "</fieldset>" ],
                table: [ 1, "<table>", "</table>" ],
                tbody: [ 2, "<table><tbody>", "</tbody></table>" ],
                tr: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
                colgroup: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
                map: [ 1, "<map>", "</map>" ],
                _default: [ 0, "", "" ]
            };

            var findChildById = function(element, id) {
                if (element.getAttribute('id') === id) {
                    return element;
                }

                var len = element.childNodes.length, idx, node, found;
                for (idx = 0; idx < len; idx++) {
                    node = element.childNodes[idx];
                    found = node.nodeType === 1 && findChildById(node, id);
                    if (found) {
                        return found;
                    }
                }
            };

            var setInnerHTML = function(element, html) {
                var matches = [];
                if (movesWhitespace) {
                    // Right now we only check for script tags with ids with the
                    // goal of targeting morphs.
                    html = html.replace(/(\s+)(<script id='([^']+)')/g, function(match, spaces, tag, id) {
                        matches.push([id, spaces]);
                        return tag;
                    });
                }

                element.innerHTML = html;

                // If we have to do any whitespace adjustments do them now
                if (matches.length > 0) {
                    var len = matches.length, idx;
                    for (idx = 0; idx < len; idx++) {
                        var script = findChildById(element, matches[idx][0]),
                        node = document.createTextNode(matches[idx][1]);
                        script.parentNode.insertBefore(node, script);
                    }
                }
            };

            /*
                   * Given a parent node and some HTML, generate a set of nodes. Return the first
                   * node, which will allow us to traverse the rest using nextSibling.
                   *
                   * We need to do this because innerHTML in IE does not really parse the nodes.
                   */
            var firstNodeFor = function(parentNode, html) {
                var wrapMap = Metamorph._wrapMap;
                var arr = wrapMap[parentNode.tagName.toLowerCase()] || wrapMap._default;
                var depth = arr[0], start = arr[1], end = arr[2];

                if (needsShy) {
                    html = '&shy;' + html;
                }

                var element = document.createElement('div');

                setInnerHTML(element, start + html + end);

                for (var i = 0; i <= depth; i++) {
                    element = element.firstChild;
                }

                // Look for &shy; to remove it.
                if (needsShy) {
                    var shyElement = element;

                    // Sometimes we get nameless elements with the shy inside
                    while (shyElement.nodeType === 1 && !shyElement.nodeName) {
                        shyElement = shyElement.firstChild;
                    }

                    // At this point it's the actual unicode character.
                    if (shyElement.nodeType === 3 && shyElement.nodeValue.charAt(0) === "\u00AD") {
                        shyElement.nodeValue = shyElement.nodeValue.slice(1);
                    }
                }

                return element;
            };

            /*
                   * In some cases, Internet Explorer can create an anonymous node in
                   * the hierarchy with no tagName. You can create this scenario via:
                   *
                   *     div = document.createElement("div");
                   *     div.innerHTML = "<table>&shy<script></script><tr><td>hi</td></tr></table>";
                   *     div.firstChild.firstChild.tagName //=> ""
                   *
                   * If our script markers are inside such a node, we need to find that
                   * node and use *it* as the marker.
                   */
            var realNode = function(start) {
                while (start.parentNode.tagName === "") {
                    start = start.parentNode;
                }

                return start;
            };

            /*
                   * When automatically adding a tbody, Internet Explorer inserts the
                   * tbody immediately before the first <tr>. Other browsers create it
                   * before the first node, no matter what.
                   *
                   * This means the the following code:
                   *
                   *     div = document.createElement("div");
                   *     div.innerHTML = "<table><script id='first'></script><tr><td>hi</td></tr><script id='last'></script></table>
                   *
                   * Generates the following DOM in IE:
                   *
                   *     + div
                   *       + table
                   *         - script id='first'
                   *         + tbody
                   *           + tr
                   *             + td
                   *               - "hi"
                   *           - script id='last'
                   *
                   * Which means that the two script tags, even though they were
                   * inserted at the same point in the hierarchy in the original
                   * HTML, now have different parents.
                   *
                   * This code reparents the first script tag by making it the tbody's
                   * first child.
                   *
                   */
            var fixParentage = function(start, end) {
                if (start.parentNode !== end.parentNode) {
                    end.parentNode.insertBefore(start, end.parentNode.firstChild);
                }
            };

            htmlFunc = function(html, outerToo) {
                // get the real starting node. see realNode for details.
                var start = realNode(document.getElementById(this.start));
                var end = document.getElementById(this.end);
                var parentNode = end.parentNode;
                var node, nextSibling, last;

                // make sure that the start and end nodes share the same
                // parent. If not, fix it.
                fixParentage(start, end);

                // remove all of the nodes after the starting placeholder and
                // before the ending placeholder.
                node = start.nextSibling;
                while (node) {
                    nextSibling = node.nextSibling;
                    last = node === end;

                    // if this is the last node, and we want to remove it as well,
                    // set the `end` node to the next sibling. This is because
                    // for the rest of the function, we insert the new nodes
                    // before the end (note that insertBefore(node, null) is
                    // the same as appendChild(node)).
                    //
                    // if we do not want to remove it, just break.
                    if (last) {
                        if (outerToo) {
                            end = node.nextSibling;
                        } else {
                            break;
                        }
                    }

                    node.parentNode.removeChild(node);

                    // if this is the last node and we didn't break before
                    // (because we wanted to remove the outer nodes), break
                    // now.
                    if (last) {
                        break;
                    }

                    node = nextSibling;
                }

                // get the first node for the HTML string, even in cases like
                // tables and lists where a simple innerHTML on a div would
                // swallow some of the content.
                node = firstNodeFor(start.parentNode, html);

                if (outerToo) {
                    start.parentNode.removeChild(start);
                }

                // copy the nodes for the HTML between the starting and ending
                // placeholder.
                while (node) {
                    nextSibling = node.nextSibling;
                    parentNode.insertBefore(node, end);
                    node = nextSibling;
                }
            };

            // remove the nodes in the DOM representing this metamorph.
            //
            // this includes the starting and ending placeholders.
            removeFunc = function() {
                var start = realNode(document.getElementById(this.start));
                var end = document.getElementById(this.end);

                this.html('');
                start.parentNode.removeChild(start);
                end.parentNode.removeChild(end);
            };

            appendToFunc = function(parentNode) {
                var node = firstNodeFor(parentNode, this.outerHTML());
                var nextSibling;

                while (node) {
                    nextSibling = node.nextSibling;
                    parentNode.appendChild(node);
                    node = nextSibling;
                }
            };

            afterFunc = function(html) {
                // get the real starting node. see realNode for details.
                var end = document.getElementById(this.end);
                var insertBefore = end.nextSibling;
                var parentNode = end.parentNode;
                var nextSibling;
                var node;

                // get the first node for the HTML string, even in cases like
                // tables and lists where a simple innerHTML on a div would
                // swallow some of the content.
                node = firstNodeFor(parentNode, html);

                // copy the nodes for the HTML between the starting and ending
                // placeholder.
                while (node) {
                    nextSibling = node.nextSibling;
                    parentNode.insertBefore(node, insertBefore);
                    node = nextSibling;
                }
            };

            prependFunc = function(html) {
                var start = document.getElementById(this.start);
                var parentNode = start.parentNode;
                var nextSibling;
                var node;

                node = firstNodeFor(parentNode, html);
                var insertBefore = start.nextSibling;

                while (node) {
                    nextSibling = node.nextSibling;
                    parentNode.insertBefore(node, insertBefore);
                    node = nextSibling;
                }
            };
        }

        Metamorph.prototype.html = function(html) {
            this.checkRemoved();
            if (html === undefined) {
                return this.innerHTML;
            }

            htmlFunc.call(this, html);

            this.innerHTML = html;
        };

        Metamorph.prototype.replaceWith = function(html) {
            this.checkRemoved();
            htmlFunc.call(this, html, true);
        };

        Metamorph.prototype.remove = removeFunc;
        Metamorph.prototype.outerHTML = outerHTMLFunc;
        Metamorph.prototype.appendTo = appendToFunc;
        Metamorph.prototype.after = afterFunc;
        Metamorph.prototype.prepend = prependFunc;
        Metamorph.prototype.startTag = startTagFunc;
        Metamorph.prototype.endTag = endTagFunc;

        Metamorph.prototype.isRemoved = function() {
            var before = document.getElementById(this.start);
            var after = document.getElementById(this.end);

            return !before || !after;
        };

        Metamorph.prototype.checkRemoved = function() {
            if (this.isRemoved()) {
                throw new Error("Cannot perform operations on a Metamorph that is not in the DOM.");
            }
        };

        return Metamorph;
    });

    define("route-recognizer",
    ["exports"],
    function(__exports__) {
        "use strict";
        var specials = [
        '/', '.', '*', '+', '?', '|',
        '(', ')', '[', ']', '{', '}', '\\'
        ];

        var escapeRegex = new RegExp('(\\' + specials.join('|\\') + ')', 'g');

        function isArray(test) {
            return Object.prototype.toString.call(test) === "[object Array]";
        }

        // A Segment represents a segment in the original route description.
        // Each Segment type provides an `eachChar` and `regex` method.
        //
        // The `eachChar` method invokes the callback with one or more character
        // specifications. A character specification consumes one or more input
        // characters.
        //
        // The `regex` method returns a regex fragment for the segment. If the
        // segment is a dynamic of star segment, the regex fragment also includes
        // a capture.
        //
        // A character specification contains:
        //
        // * `validChars`: a String with a list of all valid characters, or
        // * `invalidChars`: a String with a list of all invalid characters
        // * `repeat`: true if the character specification can repeat

        function StaticSegment(string) {
            this.string = string;
        }
        StaticSegment.prototype = {
            eachChar: function(callback) {
                var string = this.string, ch;

                for (var i = 0, l = string.length; i < l; i++) {
                    ch = string.charAt(i);
                    callback({
                        validChars: ch 
                    });
                }
            },

            regex: function() {
                return this.string.replace(escapeRegex, '\\$1');
            },

            generate: function() {
                return this.string;
            }
        };

        function DynamicSegment(name) {
            this.name = name;
        }
        DynamicSegment.prototype = {
            eachChar: function(callback) {
                callback({
                    invalidChars: "/",
                    repeat: true 
                });
            },

            regex: function() {
                return "([^/]+)";
            },

            generate: function(params) {
                return params[this.name];
            }
        };

        function StarSegment(name) {
            this.name = name;
        }
        StarSegment.prototype = {
            eachChar: function(callback) {
                callback({
                    invalidChars: "",
                    repeat: true 
                });
            },

            regex: function() {
                return "(.+)";
            },

            generate: function(params) {
                return params[this.name];
            }
        };

        function EpsilonSegment() {}
        EpsilonSegment.prototype = {
            eachChar: function() {},
            regex: function() {
                return "";
            },
            generate: function() {
                return "";
            }
        };

        function parse(route, names, types) {
            // normalize route as not starting with a "/". Recognition will
            // also normalize.
            if (route.charAt(0) === "/") {
                route = route.substr(1);
            }

            var segments = route.split("/"), results = [];

            for (var i = 0, l = segments.length; i < l; i++) {
                var segment = segments[i], match;

                if (match = segment.match(/^:([^\/]+)$/)) {
                    results.push(new DynamicSegment(match[1]));
                    names.push(match[1]);
                    types.dynamics++;
                } else if (match = segment.match(/^\*([^\/]+)$/)) {
                    results.push(new StarSegment(match[1]));
                    names.push(match[1]);
                    types.stars++;
                } else if (segment === "") {
                    results.push(new EpsilonSegment());
                } else {
                    results.push(new StaticSegment(segment));
                    types.statics++;
                }
            }

            return results;
        }

        // A State has a character specification and (`charSpec`) and a list of possible
        // subsequent states (`nextStates`).
        //
        // If a State is an accepting state, it will also have several additional
        // properties:
        //
        // * `regex`: A regular expression that is used to extract parameters from paths
        //   that reached this accepting state.
        // * `handlers`: Information on how to convert the list of captures into calls
        //   to registered handlers with the specified parameters
        // * `types`: How many static, dynamic or star segments in this route. Used to
        //   decide which route to use if multiple registered routes match a path.
        //
        // Currently, State is implemented naively by looping over `nextStates` and
        // comparing a character specification against a character. A more efficient
        // implementation would use a hash of keys pointing at one or more next states.

        function State(charSpec) {
            this.charSpec = charSpec;
            this.nextStates = [];
        }

        State.prototype = {
            get: function(charSpec) {
                var nextStates = this.nextStates;

                for (var i = 0, l = nextStates.length; i < l; i++) {
                    var child = nextStates[i];

                    var isEqual = child.charSpec.validChars === charSpec.validChars;
                    isEqual = isEqual && child.charSpec.invalidChars === charSpec.invalidChars;

                    if (isEqual) {
                        return child;
                    }
                }
            },

            put: function(charSpec) {
                var state;

                // If the character specification already exists in a child of the current
                // state, just return that state.
                if (state = this.get(charSpec)) {
                    return state;
                }

                // Make a new state for the character spec
                state = new State(charSpec);

                // Insert the new state as a child of the current state
                this.nextStates.push(state);

                // If this character specification repeats, insert the new state as a child
                // of itself. Note that this will not trigger an infinite loop because each
                // transition during recognition consumes a character.
                if (charSpec.repeat) {
                    state.nextStates.push(state);
                }

                // Return the new state
                return state;
            },

            // Find a list of child states matching the next character
            match: function(ch) {
                // DEBUG "Processing `" + ch + "`:"
                var nextStates = this.nextStates,
                child, charSpec, chars;

                // DEBUG "  " + debugState(this)
                var returned = [];

                for (var i = 0, l = nextStates.length; i < l; i++) {
                    child = nextStates[i];

                    charSpec = child.charSpec;

                    if (typeof (chars = charSpec.validChars) !== 'undefined') {
                        if (chars.indexOf(ch) !== -1) {
                            returned.push(child);
                        }
                    } else if (typeof (chars = charSpec.invalidChars) !== 'undefined') {
                        if (chars.indexOf(ch) === -1) {
                            returned.push(child);
                        }
                    }
                }

                return returned;
            }

            /** IF DEBUG
                  , debug: function() {
                    var charSpec = this.charSpec,
                        debug = "[",
                        chars = charSpec.validChars || charSpec.invalidChars;

                    if (charSpec.invalidChars) { debug += "^"; }
                    debug += chars;
                    debug += "]";

                    if (charSpec.repeat) { debug += "+"; }

                    return debug;
                  }
                  END IF **/
        };

        /** IF DEBUG
            function debug(log) {
              console.log(log);
            }

            function debugState(state) {
              return state.nextStates.map(function(n) {
                if (n.nextStates.length === 0) { return "( " + n.debug() + " [accepting] )"; }
                return "( " + n.debug() + " <then> " + n.nextStates.map(function(s) { return s.debug() }).join(" or ") + " )";
              }).join(", ")
            }
            END IF **/

        // This is a somewhat naive strategy, but should work in a lot of cases
        // A better strategy would properly resolve /posts/:id/new and /posts/edit/:id.
        //
        // This strategy generally prefers more static and less dynamic matching.
        // Specifically, it
        //
        //  * prefers fewer stars to more, then
        //  * prefers using stars for less of the match to more, then
        //  * prefers fewer dynamic segments to more, then
        //  * prefers more static segments to more
        function sortSolutions(states) {
            return states.sort(function(a, b) {
                if (a.types.stars !== b.types.stars) {
                    return a.types.stars - b.types.stars;
                }

                if (a.types.stars) {
                    if (a.types.statics !== b.types.statics) {
                        return b.types.statics - a.types.statics;
                    }
                    if (a.types.dynamics !== b.types.dynamics) {
                        return b.types.dynamics - a.types.dynamics;
                    }
                }

                if (a.types.dynamics !== b.types.dynamics) {
                    return a.types.dynamics - b.types.dynamics;
                }
                if (a.types.statics !== b.types.statics) {
                    return b.types.statics - a.types.statics;
                }

                return 0;
            });
        }

        function recognizeChar(states, ch) {
            var nextStates = [];

            for (var i = 0, l = states.length; i < l; i++) {
                var state = states[i];

                nextStates = nextStates.concat(state.match(ch));
            }

            return nextStates;
        }

        var oCreate = Object.create || function(proto) {
            function F() {}
            F.prototype = proto;
            return new F();
        };

        function RecognizeResults(queryParams) {
            this.queryParams = queryParams || {};
        }
        RecognizeResults.prototype = oCreate({
            splice: Array.prototype.splice,
            slice: Array.prototype.slice,
            push: Array.prototype.push,
            length: 0,
            queryParams: null
        });

        function findHandler(state, path, queryParams) {
            var handlers = state.handlers, regex = state.regex;
            var captures = path.match(regex), currentCapture = 1;
            var result = new RecognizeResults(queryParams);

            for (var i = 0, l = handlers.length; i < l; i++) {
                var handler = handlers[i], names = handler.names, params = {};

                for (var j = 0, m = names.length; j < m; j++) {
                    params[names[j]] = captures[currentCapture++];
                }

                result.push({
                    handler: handler.handler,
                    params: params,
                    isDynamic: !!names.length 
                });
            }

            return result;
        }

        function addSegment(currentState, segment) {
            segment.eachChar(function(ch) {
                var state;

                currentState = currentState.put(ch);
            });

            return currentState;
        }

        // The main interface

        var RouteRecognizer = function() {
            this.rootState = new State();
            this.names = {};
        };


        RouteRecognizer.prototype = {
            add: function(routes, options) {
                var currentState = this.rootState, regex = "^",
                types = {
                    statics: 0,
                    dynamics: 0,
                    stars: 0 
                },
                handlers = [], allSegments = [], name;

                var isEmpty = true;

                for (var i = 0, l = routes.length; i < l; i++) {
                    var route = routes[i], names = [];

                    var segments = parse(route.path, names, types);

                    allSegments = allSegments.concat(segments);

                    for (var j = 0, m = segments.length; j < m; j++) {
                        var segment = segments[j];

                        if (segment instanceof EpsilonSegment) {
                            continue;
                        }

                        isEmpty = false;

                        // Add a "/" for the new segment
                        currentState = currentState.put({
                            validChars: "/" 
                        });
                        regex += "/";

                        // Add a representation of the segment to the NFA and regex
                        currentState = addSegment(currentState, segment);
                        regex += segment.regex();
                    }

                    var handler = {
                        handler: route.handler,
                        names: names 
                    };
                    handlers.push(handler);
                }

                if (isEmpty) {
                    currentState = currentState.put({
                        validChars: "/" 
                    });
                    regex += "/";
                }

                currentState.handlers = handlers;
                currentState.regex = new RegExp(regex + "$");
                currentState.types = types;

                if (name = options && options.as) {
                    this.names[name] = {
                        segments: allSegments,
                        handlers: handlers
                    };
                }
            },

            handlersFor: function(name) {
                var route = this.names[name], result = [];
                if (!route) {
                    throw new Error("There is no route named " + name);
                }

                for (var i = 0, l = route.handlers.length; i < l; i++) {
                    result.push(route.handlers[i]);
                }

                return result;
            },

            hasRoute: function(name) {
                return !!this.names[name];
            },

            generate: function(name, params) {
                var route = this.names[name], output = "";
                if (!route) {
                    throw new Error("There is no route named " + name);
                }

                var segments = route.segments;

                for (var i = 0, l = segments.length; i < l; i++) {
                    var segment = segments[i];

                    if (segment instanceof EpsilonSegment) {
                        continue;
                    }

                    output += "/";
                    output += segment.generate(params);
                }

                if (output.charAt(0) !== '/') {
                    output = '/' + output;
                }

                if (params && params.queryParams) {
                    output += this.generateQueryString(params.queryParams, route.handlers);
                }

                return output;
            },

            generateQueryString: function(params, handlers) {
                var pairs = [];
                var keys = [];
                for (var key in params) {
                    if (params.hasOwnProperty(key)) {
                        keys.push(key);
                    }
                }
                keys.sort();
                for (var i = 0, len = keys.length; i < len; i++) {
                    key = keys[i];
                    var value = params[key];
                    if (value == null) {
                        continue;
                    }
                    var pair = key;
                    if (isArray(value)) {
                        for (var j = 0, l = value.length; j < l; j++) {
                            var arrayPair = key + '[]' + '=' + encodeURIComponent(value[j]);
                            pairs.push(arrayPair);
                        }
                    } else {
                        pair += "=" + encodeURIComponent(value);
                        pairs.push(pair);
                    }
                }

                if (pairs.length === 0) {
                    return '';
                }

                return "?" + pairs.join("&");
            },

            parseQueryString: function(queryString) {
                var pairs = queryString.split("&"), queryParams = {};
                for (var i = 0; i < pairs.length; i++) {
                    var pair = pairs[i].split('='),
                    key = decodeURIComponent(pair[0]),
                    keyLength = key.length,
                    isArray = false,
                    value;
                    if (pair.length === 1) {
                        value = 'true';
                    } else {
                        //Handle arrays
                        if (keyLength > 2 && key.slice(keyLength -2) === '[]') {
                            isArray = true;
                            key = key.slice(0, keyLength - 2);
                            if (!queryParams[key]) {
                                queryParams[key] = [];
                            }
                        }
                        value = pair[1] ? decodeURIComponent(pair[1]) : '';
                    }
                    if (isArray) {
                        queryParams[key].push(value);
                    } else {
                        queryParams[key] = decodeURIComponent(value);
                    }
                }
                return queryParams;
            },

            recognize: function(path) {
                var states = [ this.rootState ],
                pathLen, i, l, queryStart, queryParams = {},
                isSlashDropped = false;

                path = decodeURI(path);

                queryStart = path.indexOf('?');
                if (queryStart !== -1) {
                    var queryString = path.substr(queryStart + 1, path.length);
                    path = path.substr(0, queryStart);
                    queryParams = this.parseQueryString(queryString);
                }

                // DEBUG GROUP path

                if (path.charAt(0) !== "/") {
                    path = "/" + path;
                }

                pathLen = path.length;
                if (pathLen > 1 && path.charAt(pathLen - 1) === "/") {
                    path = path.substr(0, pathLen - 1);
                    isSlashDropped = true;
                }

                for (i = 0, l = path.length; i < l; i++) {
                    states = recognizeChar(states, path.charAt(i));
                    if (!states.length) {
                        break;
                    }
                }

                // END DEBUG GROUP

                var solutions = [];
                for (i = 0, l = states.length; i < l; i++) {
                    if (states[i].handlers) {
                        solutions.push(states[i]);
                    }
                }

                states = sortSolutions(solutions);

                var state = solutions[0];

                if (state && state.handlers) {
                    // if a trailing slash was dropped and a star segment is the last segment
                    // specified, put the trailing slash back
                    if (isSlashDropped && state.regex.source.slice(-5) === "(.+)$") {
                        path = path + "/";
                    }
                    return findHandler(state, path, queryParams);
                }
            }
        };

        __exports__["default"] = RouteRecognizer;

        function Target(path, matcher, delegate) {
            this.path = path;
            this.matcher = matcher;
            this.delegate = delegate;
        }

        Target.prototype = {
            to: function(target, callback) {
                var delegate = this.delegate;

                if (delegate && delegate.willAddRoute) {
                    target = delegate.willAddRoute(this.matcher.target, target);
                }

                this.matcher.add(this.path, target);

                if (callback) {
                    if (callback.length === 0) {
                        throw new Error("You must have an argument in the function passed to `to`");
                    }
                    this.matcher.addChild(this.path, target, callback, this.delegate);
                }
                return this;
            }
        };

        function Matcher(target) {
            this.routes = {};
            this.children = {};
            this.target = target;
        }

        Matcher.prototype = {
            add: function(path, handler) {
                this.routes[path] = handler;
            },

            addChild: function(path, target, callback, delegate) {
                var matcher = new Matcher(target);
                this.children[path] = matcher;

                var match = generateMatch(path, matcher, delegate);

                if (delegate && delegate.contextEntered) {
                    delegate.contextEntered(target, match);
                }

                callback(match);
            }
        };

        function generateMatch(startingPath, matcher, delegate) {
            return function(path, nestedCallback) {
                var fullPath = startingPath + path;

                if (nestedCallback) {
                    nestedCallback(generateMatch(fullPath, matcher, delegate));
                } else {
                    return new Target(startingPath + path, matcher, delegate);
                }
            };
        }

        function addRoute(routeArray, path, handler) {
            var len = 0;
            for (var i = 0, l = routeArray.length; i < l; i++) {
                len += routeArray[i].path.length;
            }

            path = path.substr(len);
            var route = {
                path: path,
                handler: handler 
            };
            routeArray.push(route);
        }

        function eachRoute(baseRoute, matcher, callback, binding) {
            var routes = matcher.routes;

            for (var path in routes) {
                if (routes.hasOwnProperty(path)) {
                    var routeArray = baseRoute.slice();
                    addRoute(routeArray, path, routes[path]);

                    if (matcher.children[path]) {
                        eachRoute(routeArray, matcher.children[path], callback, binding);
                    } else {
                        callback.call(binding, routeArray);
                    }
                }
            }
        }

        RouteRecognizer.prototype.map = function(callback, addRouteCallback) {
            var matcher = new Matcher();

            callback(generateMatch("", matcher, this.delegate));

            eachRoute([], matcher, function(route) {
                if (addRouteCallback) {
                    addRouteCallback(this, route);
                } else {
                    this.add(route);
                }
            }, this);
        };
    });

    define("router/handler-info",
    ["./utils", "rsvp/promise", "exports"],
    function(__dependency1__, __dependency2__, __exports__) {
        "use strict";
        var bind = __dependency1__.bind;
        var merge = __dependency1__.merge;
        var serialize = __dependency1__.serialize;
        var promiseLabel = __dependency1__.promiseLabel;
        var Promise = __dependency2__["default"];

        function HandlerInfo(_props) {
            var props = _props || {};
            merge(this, props);
            this.initialize(props);
        }

        HandlerInfo.prototype = {
            name: null,
            handler: null,
            params: null,
            context: null,

            // Injected by the handler info factory.
            factory: null,

            initialize: function() {},

            log: function(payload, message) {
                if (payload.log) {
                    payload.log(this.name + ': ' + message);
                }
            },

            promiseLabel: function(label) {
                return promiseLabel("'" + this.name + "' " + label);
            },

            getUnresolved: function() {
                return this;
            },

            serialize: function() {
                return this.params || {};
            },

            resolve: function(shouldContinue, payload) {
                var checkForAbort = bind(this, this.checkForAbort, shouldContinue),
                beforeModel = bind(this, this.runBeforeModelHook, payload),
                model = bind(this, this.getModel, payload),
                afterModel = bind(this, this.runAfterModelHook, payload),
                becomeResolved = bind(this, this.becomeResolved, payload);

                return Promise.resolve(undefined, this.promiseLabel("Start handler"))
                .then(checkForAbort, null, this.promiseLabel("Check for abort"))
                .then(beforeModel, null, this.promiseLabel("Before model"))
                .then(checkForAbort, null, this.promiseLabel("Check if aborted during 'beforeModel' hook"))
                .then(model, null, this.promiseLabel("Model"))
                .then(checkForAbort, null, this.promiseLabel("Check if aborted in 'model' hook"))
                .then(afterModel, null, this.promiseLabel("After model"))
                .then(checkForAbort, null, this.promiseLabel("Check if aborted in 'afterModel' hook"))
                .then(becomeResolved, null, this.promiseLabel("Become resolved"));
            },

            runBeforeModelHook: function(payload) {
                if (payload.trigger) {
                    payload.trigger(true, 'willResolveModel', payload, this.handler);
                }
                return this.runSharedModelHook(payload, 'beforeModel', []);
            },

            runAfterModelHook: function(payload, resolvedModel) {
                // Stash the resolved model on the payload.
                // This makes it possible for users to swap out
                // the resolved model in afterModel.
                var name = this.name;
                this.stashResolvedModel(payload, resolvedModel);

                return this.runSharedModelHook(payload, 'afterModel', [resolvedModel])
                .then(function() {
                    // Ignore the fulfilled value returned from afterModel.
                    // Return the value stashed in resolvedModels, which
                    // might have been swapped out in afterModel.
                    return payload.resolvedModels[name];
                }, null, this.promiseLabel("Ignore fulfillment value and return model value"));
            },

            runSharedModelHook: function(payload, hookName, args) {
                this.log(payload, "calling " + hookName + " hook");

                if (this.queryParams) {
                    args.push(this.queryParams);
                }
                args.push(payload);

                var handler = this.handler;
                var result = handler[hookName] && handler[hookName].apply(handler, args);

                if (result && result.isTransition) {
                    result = null;
                }

                return Promise.resolve(result, null, this.promiseLabel("Resolve value returned from one of the model hooks"));
            },

            // overridden by subclasses
            getModel: null,

            checkForAbort: function(shouldContinue, promiseValue) {
                return Promise.resolve(shouldContinue(), this.promiseLabel("Check for abort")).then(function() {
                    // We don't care about shouldContinue's resolve value;
                    // pass along the original value passed to this fn.
                    return promiseValue;
                }, null, this.promiseLabel("Ignore fulfillment value and continue"));
            },

            stashResolvedModel: function(payload, resolvedModel) {
                payload.resolvedModels = payload.resolvedModels || {};
                payload.resolvedModels[this.name] = resolvedModel;
            },

            becomeResolved: function(payload, resolvedContext) {
                var params = this.serialize(resolvedContext);

                if (payload) {
                    this.stashResolvedModel(payload, resolvedContext);
                    payload.params = payload.params || {};
                    payload.params[this.name] = params;
                }

                return this.factory('resolved', {
                    context: resolvedContext,
                    name: this.name,
                    handler: this.handler,
                    params: params
                });
            },

            shouldSupercede: function(other) {
                // Prefer this newer handlerInfo over `other` if:
                // 1) The other one doesn't exist
                // 2) The names don't match
                // 3) This handler has a context that doesn't match
                //    the other one (or the other one doesn't have one).
                // 4) This handler has parameters that don't match the other.
                if (!other) {
                    return true;
                }

                var contextsMatch = (other.context === this.context);
                return other.name !== this.name ||
                (this.hasOwnProperty('context') && !contextsMatch) ||
                (this.hasOwnProperty('params') && !paramsMatch(this.params, other.params));
            }
        };

        function paramsMatch(a, b) {
            if ((!a) ^ (!b)) {
                // Only one is null.
                return false;
            }

            if (!a) {
                // Both must be null.
                return true;
            }

            // Note: this assumes that both params have the same
            // number of keys, but since we're comparing the
            // same handlers, they should.
            for (var k in a) {
                if (a.hasOwnProperty(k) && a[k] !== b[k]) {
                    return false;
                }
            }
            return true;
        }

        __exports__["default"] = HandlerInfo;
    });
    define("router/handler-info/factory",
    ["router/handler-info/resolved-handler-info", "router/handler-info/unresolved-handler-info-by-object", "router/handler-info/unresolved-handler-info-by-param", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        var ResolvedHandlerInfo = __dependency1__["default"];
        var UnresolvedHandlerInfoByObject = __dependency2__["default"];
        var UnresolvedHandlerInfoByParam = __dependency3__["default"];

        handlerInfoFactory.klasses = {
            resolved: ResolvedHandlerInfo,
            param: UnresolvedHandlerInfoByParam,
            object: UnresolvedHandlerInfoByObject
        };

        function handlerInfoFactory(name, props) {
            var Ctor = handlerInfoFactory.klasses[name],
            handlerInfo = new Ctor(props || {});
            handlerInfo.factory = handlerInfoFactory;
            return handlerInfo;
        }

        __exports__["default"] = handlerInfoFactory;
    });
    define("router/handler-info/resolved-handler-info",
    ["../handler-info", "router/utils", "rsvp/promise", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        var HandlerInfo = __dependency1__["default"];
        var subclass = __dependency2__.subclass;
        var promiseLabel = __dependency2__.promiseLabel;
        var Promise = __dependency3__["default"];

        var ResolvedHandlerInfo = subclass(HandlerInfo, {
            resolve: function(shouldContinue, payload) {
                // A ResolvedHandlerInfo just resolved with itself.
                if (payload && payload.resolvedModels) {
                    payload.resolvedModels[this.name] = this.context;
                }
                return Promise.resolve(this, this.promiseLabel("Resolve"));
            },

            getUnresolved: function() {
                return this.factory('param', {
                    name: this.name,
                    handler: this.handler,
                    params: this.params
                });
            },

            isResolved: true
        });

        __exports__["default"] = ResolvedHandlerInfo;
    });
    define("router/handler-info/unresolved-handler-info-by-object",
    ["../handler-info", "router/utils", "rsvp/promise", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        var HandlerInfo = __dependency1__["default"];
        var merge = __dependency2__.merge;
        var subclass = __dependency2__.subclass;
        var promiseLabel = __dependency2__.promiseLabel;
        var isParam = __dependency2__.isParam;
        var Promise = __dependency3__["default"];

        var UnresolvedHandlerInfoByObject = subclass(HandlerInfo, {
            getModel: function(payload) {
                this.log(payload, this.name + ": resolving provided model");
                return Promise.resolve(this.context);
            },

            initialize: function(props) {
                this.names = props.names || [];
                this.context = props.context;
            },

            /**
                    @private

                    Serializes a handler using its custom `serialize` method or
                    by a default that looks up the expected property name from
                    the dynamic segment.

                    @param {Object} model the model to be serialized for this handler
                  */
            serialize: function(_model) {
                var model = _model || this.context,
                names = this.names,
                handler = this.handler;

                var object = {};
                if (isParam(model)) {
                    object[names[0]] = model;
                    return object;
                }

                // Use custom serialize if it exists.
                if (handler.serialize) {
                    return handler.serialize(model, names);
                }

                if (names.length !== 1) {
                    return;
                }

                var name = names[0];

                if (/_id$/.test(name)) {
                    object[name] = model.id;
                } else {
                    object[name] = model;
                }
                return object;
            }
        });

        __exports__["default"] = UnresolvedHandlerInfoByObject;
    });
    define("router/handler-info/unresolved-handler-info-by-param",
    ["../handler-info", "router/utils", "exports"],
    function(__dependency1__, __dependency2__, __exports__) {
        "use strict";
        var HandlerInfo = __dependency1__["default"];
        var merge = __dependency2__.merge;
        var subclass = __dependency2__.subclass;
        var promiseLabel = __dependency2__.promiseLabel;

        // Generated by URL transitions and non-dynamic route segments in named Transitions.
        var UnresolvedHandlerInfoByParam = subclass (HandlerInfo, {
            initialize: function(props) {
                this.params = props.params || {};
            },

            getModel: function(payload) {
                var fullParams = this.params;
                if (payload && payload.queryParams) {
                    fullParams = {};
                    merge(fullParams, this.params);
                    fullParams.queryParams = payload.queryParams;
                }

                var hookName = typeof this.handler.deserialize === 'function' ?
                'deserialize' : 'model';

                return this.runSharedModelHook(payload, hookName, [fullParams]);
            }
        });

        __exports__["default"] = UnresolvedHandlerInfoByParam;
    });
    define("router/router",
    ["route-recognizer", "rsvp/promise", "./utils", "./transition-state", "./transition", "./transition-intent/named-transition-intent", "./transition-intent/url-transition-intent", "./handler-info", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
        "use strict";
        var RouteRecognizer = __dependency1__["default"];
        var Promise = __dependency2__["default"];
        var trigger = __dependency3__.trigger;
        var log = __dependency3__.log;
        var slice = __dependency3__.slice;
        var forEach = __dependency3__.forEach;
        var merge = __dependency3__.merge;
        var serialize = __dependency3__.serialize;
        var extractQueryParams = __dependency3__.extractQueryParams;
        var getChangelist = __dependency3__.getChangelist;
        var promiseLabel = __dependency3__.promiseLabel;
        var TransitionState = __dependency4__["default"];
        var logAbort = __dependency5__.logAbort;
        var Transition = __dependency5__.Transition;
        var TransitionAborted = __dependency5__.TransitionAborted;
        var NamedTransitionIntent = __dependency6__["default"];
        var URLTransitionIntent = __dependency7__["default"];
        var ResolvedHandlerInfo = __dependency8__.ResolvedHandlerInfo;

        var pop = Array.prototype.pop;

        function Router() {
            this.recognizer = new RouteRecognizer();
            this.reset();
        }

        Router.prototype = {

            /**
                    The main entry point into the router. The API is essentially
                    the same as the `map` method in `route-recognizer`.

                    This method extracts the String handler at the last `.to()`
                    call and uses it as the name of the whole route.

                    @param {Function} callback
                  */
            map: function(callback) {
                this.recognizer.delegate = this.delegate;

                this.recognizer.map(callback, function(recognizer, routes) {
                    for (var i = routes.length - 1, proceed = true; i >= 0 && proceed; --i) {
                        var route = routes[i];
                        recognizer.add(routes, {
                            as: route.handler 
                        });
                        proceed = route.path === '/' || route.path === '' || route.handler.slice(-6) === '.index';
                    }
                });
            },

            hasRoute: function(route) {
                return this.recognizer.hasRoute(route);
            },

            queryParamsTransition: function(changelist, wasTransitioning, oldState, newState) {
                var router = this;

                fireQueryParamDidChange(this, newState, changelist);

                if (!wasTransitioning && this.activeTransition) {
                    // One of the handlers in queryParamsDidChange
                    // caused a transition. Just return that transition.
                    return this.activeTransition;
                } else {
                    // Running queryParamsDidChange didn't change anything.
                    // Just update query params and be on our way.

                    // We have to return a noop transition that will
                    // perform a URL update at the end. This gives
                    // the user the ability to set the url update
                    // method (default is replaceState).
                    var newTransition = new Transition(this);
                    newTransition.queryParamsOnly = true;

                    oldState.queryParams = finalizeQueryParamChange(this, newState.handlerInfos, newState.queryParams, newTransition);

                    newTransition.promise = newTransition.promise.then(function(result) {
                        updateURL(newTransition, oldState, true);
                        if (router.didTransition) {
                            router.didTransition(router.currentHandlerInfos);
                        }
                        return result;
                    }, null, promiseLabel("Transition complete"));
                    return newTransition;
                }
            },

            // NOTE: this doesn't really belong here, but here
            // it shall remain until our ES6 transpiler can
            // handle cyclical deps.
            transitionByIntent: function(intent, isIntermediate) {

                var wasTransitioning = !!this.activeTransition;
                var oldState = wasTransitioning ? this.activeTransition.state : this.state;
                var newTransition;
                var router = this;

                try {
                    var newState = intent.applyToState(oldState, this.recognizer, this.getHandler, isIntermediate);
                    var queryParamChangelist = getChangelist(oldState.queryParams, newState.queryParams);

                    if (handlerInfosEqual(newState.handlerInfos, oldState.handlerInfos)) {

                        // This is a no-op transition. See if query params changed.
                        if (queryParamChangelist) {
                            newTransition = this.queryParamsTransition(queryParamChangelist, wasTransitioning, oldState, newState);
                            if (newTransition) {
                                return newTransition;
                            }
                        }

                        // No-op. No need to create a new transition.
                        return new Transition(this);
                    }

                    if (isIntermediate) {
                        setupContexts(this, newState);
                        return;
                    }

                    // Create a new transition to the destination route.
                    newTransition = new Transition(this, intent, newState);

                    // Abort and usurp any previously active transition.
                    if (this.activeTransition) {
                        this.activeTransition.abort();
                    }
                    this.activeTransition = newTransition;

                    // Transition promises by default resolve with resolved state.
                    // For our purposes, swap out the promise to resolve
                    // after the transition has been finalized.
                    newTransition.promise = newTransition.promise.then(function(result) {
                        return finalizeTransition(newTransition, result.state);
                    }, null, promiseLabel("Settle transition promise when transition is finalized"));

                    if (!wasTransitioning) {
                        notifyExistingHandlers(this, newState, newTransition);
                    }

                    fireQueryParamDidChange(this, newState, queryParamChangelist);

                    return newTransition;
                } catch (e) {
                    return new Transition(this, intent, null, e);
                }
            },

            /**
                    Clears the current and target route handlers and triggers exit
                    on each of them starting at the leaf and traversing up through
                    its ancestors.
                  */
            reset: function() {
                if (this.state) {
                    forEach(this.state.handlerInfos, function(handlerInfo) {
                        var handler = handlerInfo.handler;
                        if (handler.exit) {
                            handler.exit();
                        }
                    });
                }

                this.state = new TransitionState();
                this.currentHandlerInfos = null;
            },

            activeTransition: null,

            /**
                    var handler = handlerInfo.handler;
                    The entry point for handling a change to the URL (usually
                    via the back and forward button).

                    Returns an Array of handlers and the parameters associated
                    with those parameters.

                    @param {String} url a URL to process

                    @return {Array} an Array of `[handler, parameter]` tuples
                  */
            handleURL: function(url) {
                // Perform a URL-based transition, but don't change
                // the URL afterward, since it already happened.
                var args = slice.call(arguments);
                if (url.charAt(0) !== '/') {
                    args[0] = '/' + url;
                }

                return doTransition(this, args).method(null);
            },

            /**
                    Hook point for updating the URL.

                    @param {String} url a URL to update to
                  */
            updateURL: function() {
                throw new Error("updateURL is not implemented");
            },

            /**
                    Hook point for replacing the current URL, i.e. with replaceState

                    By default this behaves the same as `updateURL`

                    @param {String} url a URL to update to
                  */
            replaceURL: function(url) {
                this.updateURL(url);
            },

            /**
                    Transition into the specified named route.

                    If necessary, trigger the exit callback on any handlers
                    that are no longer represented by the target route.

                    @param {String} name the name of the route
                  */
            transitionTo: function(name) {
                return doTransition(this, arguments);
            },

            intermediateTransitionTo: function(name) {
                doTransition(this, arguments, true);
            },

            refresh: function(pivotHandler) {
                var state = this.activeTransition ? this.activeTransition.state : this.state;
                var handlerInfos = state.handlerInfos;
                var params = {};
                for (var i = 0, len = handlerInfos.length; i < len; ++i) {
                    var handlerInfo = handlerInfos[i];
                    params[handlerInfo.name] = handlerInfo.params || {};
                }

                log(this, "Starting a refresh transition");
                var intent = new NamedTransitionIntent({
                    name: handlerInfos[handlerInfos.length - 1].name,
                    pivotHandler: pivotHandler || handlerInfos[0].handler,
                    contexts: [],
                    // TODO collect contexts...?
                    queryParams: this._changedQueryParams || state.queryParams || {}
                });

                return this.transitionByIntent(intent, false);
            },

            /**
                    Identical to `transitionTo` except that the current URL will be replaced
                    if possible.

                    This method is intended primarily for use with `replaceState`.

                    @param {String} name the name of the route
                  */
            replaceWith: function(name) {
                return doTransition(this, arguments).method('replace');
            },

            /**
                    Take a named route and context objects and generate a
                    URL.

                    @param {String} name the name of the route to generate
                      a URL for
                    @param {...Object} objects a list of objects to serialize

                    @return {String} a URL
                  */
            generate: function(handlerName) {

                var partitionedArgs = extractQueryParams(slice.call(arguments, 1)),
                suppliedParams = partitionedArgs[0],
                queryParams = partitionedArgs[1];

                // Construct a TransitionIntent with the provided params
                // and apply it to the present state of the router.
                var intent = new NamedTransitionIntent({
                    name: handlerName,
                    contexts: suppliedParams 
                });
                var state = intent.applyToState(this.state, this.recognizer, this.getHandler);
                var params = {};

                for (var i = 0, len = state.handlerInfos.length; i < len; ++i) {
                    var handlerInfo = state.handlerInfos[i];
                    var handlerParams = handlerInfo.serialize();
                    merge(params, handlerParams);
                }
                params.queryParams = queryParams;

                return this.recognizer.generate(handlerName, params);
            },

            applyIntent: function(handlerName, contexts) {
                var intent = new NamedTransitionIntent({
                    name: handlerName,
                    contexts: contexts
                });

                var state = this.activeTransition && this.activeTransition.state || this.state;
                return intent.applyToState(state, this.recognizer, this.getHandler);
            },

            isActiveIntent: function(handlerName, contexts, queryParams) {
                var targetHandlerInfos = this.state.handlerInfos,
                found = false, names, object, handlerInfo, handlerObj, i, len;

                if (!targetHandlerInfos.length) {
                    return false;
                }

                var targetHandler = targetHandlerInfos[targetHandlerInfos.length - 1].name;
                var recogHandlers = this.recognizer.handlersFor(targetHandler);

                var index = 0;
                for (len = recogHandlers.length; index < len; ++index) {
                    handlerInfo = targetHandlerInfos[index];
                    if (handlerInfo.name === handlerName) {
                        break;
                    }
                }

                if (index === recogHandlers.length) {
                    // The provided route name isn't even in the route hierarchy.
                    return false;
                }

                var state = new TransitionState();
                state.handlerInfos = targetHandlerInfos.slice(0, index + 1);
                recogHandlers = recogHandlers.slice(0, index + 1);

                var intent = new NamedTransitionIntent({
                    name: targetHandler,
                    contexts: contexts
                });

                var newState = intent.applyToHandlers(state, recogHandlers, this.getHandler, targetHandler, true, true);

                var handlersEqual = handlerInfosEqual(newState.handlerInfos, state.handlerInfos);
                if (!queryParams || !handlersEqual) {
                    return handlersEqual;
                }

                // Get a hash of QPs that will still be active on new route
                var activeQPsOnNewHandler = {};
                merge(activeQPsOnNewHandler, queryParams);

                var activeQueryParams = this.state.queryParams;
                for (var key in activeQueryParams) {
                    if (activeQueryParams.hasOwnProperty(key) &&
                    activeQPsOnNewHandler.hasOwnProperty(key)) {
                        activeQPsOnNewHandler[key] = activeQueryParams[key];
                    }
                }

                return handlersEqual && !getChangelist(activeQPsOnNewHandler, queryParams);
            },

            isActive: function(handlerName) {
                var partitionedArgs = extractQueryParams(slice.call(arguments, 1));
                return this.isActiveIntent(handlerName, partitionedArgs[0], partitionedArgs[1]);
            },

            trigger: function(name) {
                var args = slice.call(arguments);
                trigger(this, this.currentHandlerInfos, false, args);
            },

            /**
                    Hook point for logging transition status updates.

                    @param {String} message The message to log.
                  */
            log: null,

            _willChangeContextEvent: 'willChangeContext',
            _triggerWillChangeContext: function(handlerInfos, newTransition) {
                trigger(this, handlerInfos, true, [this._willChangeContextEvent, newTransition]);
            },

            _triggerWillLeave: function(handlerInfos, newTransition, leavingChecker) {
                trigger(this, handlerInfos, true, ['willLeave', newTransition, leavingChecker]);
            }
        };

        /**
              @private

              Fires queryParamsDidChange event
            */
        function fireQueryParamDidChange(router, newState, queryParamChangelist) {
            // If queryParams changed trigger event
            if (queryParamChangelist) {

                // This is a little hacky but we need some way of storing
                // changed query params given that no activeTransition
                // is guaranteed to have occurred.
                router._changedQueryParams = queryParamChangelist.all;
                trigger(router, newState.handlerInfos, true, ['queryParamsDidChange', queryParamChangelist.changed, queryParamChangelist.all, queryParamChangelist.removed]);
                router._changedQueryParams = null;
            }
        }

        /**
              @private

              Takes an Array of `HandlerInfo`s, figures out which ones are
              exiting, entering, or changing contexts, and calls the
              proper handler hooks.

              For example, consider the following tree of handlers. Each handler is
              followed by the URL segment it handles.

              ```
              |~index ("/")
              | |~posts ("/posts")
              | | |-showPost ("/:id")
              | | |-newPost ("/new")
              | | |-editPost ("/edit")
              | |~about ("/about/:id")
              ```

              Consider the following transitions:

              1. A URL transition to `/posts/1`.
                 1. Triggers the `*model` callbacks on the
                    `index`, `posts`, and `showPost` handlers
                 2. Triggers the `enter` callback on the same
                 3. Triggers the `setup` callback on the same
              2. A direct transition to `newPost`
                 1. Triggers the `exit` callback on `showPost`
                 2. Triggers the `enter` callback on `newPost`
                 3. Triggers the `setup` callback on `newPost`
              3. A direct transition to `about` with a specified
                 context object
                 1. Triggers the `exit` callback on `newPost`
                    and `posts`
                 2. Triggers the `serialize` callback on `about`
                 3. Triggers the `enter` callback on `about`
                 4. Triggers the `setup` callback on `about`

              @param {Router} transition
              @param {TransitionState} newState
            */
        function setupContexts(router, newState, transition) {
            var partition = partitionHandlers(router.state, newState);

            forEach(partition.exited, function(handlerInfo) {
                var handler = handlerInfo.handler;
                delete handler.context;
                if (handler.reset) {
                    handler.reset(true, transition);
                }
                if (handler.exit) {
                    handler.exit(transition);
                }
            });

            var oldState = router.oldState = router.state;
            router.state = newState;
            var currentHandlerInfos = router.currentHandlerInfos = partition.unchanged.slice();

            try {
                forEach(partition.reset, function(handlerInfo) {
                    var handler = handlerInfo.handler;
                    if (handler.reset) {
                        handler.reset(false, transition);
                    }
                });

                forEach(partition.updatedContext, function(handlerInfo) {
                    return handlerEnteredOrUpdated(currentHandlerInfos, handlerInfo, false, transition);
                });

                forEach(partition.entered, function(handlerInfo) {
                    return handlerEnteredOrUpdated(currentHandlerInfos, handlerInfo, true, transition);
                });
            } catch (e) {
                router.state = oldState;
                router.currentHandlerInfos = oldState.handlerInfos;
                throw e;
            }

            router.state.queryParams = finalizeQueryParamChange(router, currentHandlerInfos, newState.queryParams, transition);
        }


        /**
              @private

              Helper method used by setupContexts. Handles errors or redirects
              that may happen in enter/setup.
            */
        function handlerEnteredOrUpdated(currentHandlerInfos, handlerInfo, enter, transition) {

            var handler = handlerInfo.handler,
            context = handlerInfo.context;

            if (enter && handler.enter) {
                handler.enter(transition);
            }
            if (transition && transition.isAborted) {
                throw new TransitionAborted();
            }

            handler.context = context;
            if (handler.contextDidChange) {
                handler.contextDidChange();
            }

            if (handler.setup) {
                handler.setup(context, transition);
            }
            if (transition && transition.isAborted) {
                throw new TransitionAborted();
            }

            currentHandlerInfos.push(handlerInfo);

            return true;
        }


        /**
              @private

              This function is called when transitioning from one URL to
              another to determine which handlers are no longer active,
              which handlers are newly active, and which handlers remain
              active but have their context changed.

              Take a list of old handlers and new handlers and partition
              them into four buckets:

              * unchanged: the handler was active in both the old and
                new URL, and its context remains the same
              * updated context: the handler was active in both the
                old and new URL, but its context changed. The handler's
                `setup` method, if any, will be called with the new
                context.
              * exited: the handler was active in the old URL, but is
                no longer active.
              * entered: the handler was not active in the old URL, but
                is now active.

              The PartitionedHandlers structure has four fields:

              * `updatedContext`: a list of `HandlerInfo` objects that
                represent handlers that remain active but have a changed
                context
              * `entered`: a list of `HandlerInfo` objects that represent
                handlers that are newly active
              * `exited`: a list of `HandlerInfo` objects that are no
                longer active.
              * `unchanged`: a list of `HanderInfo` objects that remain active.

              @param {Array[HandlerInfo]} oldHandlers a list of the handler
                information for the previous URL (or `[]` if this is the
                first handled transition)
              @param {Array[HandlerInfo]} newHandlers a list of the handler
                information for the new URL

              @return {Partition}
            */
        function partitionHandlers(oldState, newState) {
            var oldHandlers = oldState.handlerInfos;
            var newHandlers = newState.handlerInfos;

            var handlers = {
                updatedContext: [],
                exited: [],
                entered: [],
                unchanged: []
            };

            var handlerChanged, contextChanged, i, l;

            for (i = 0, l = newHandlers.length; i < l; i++) {
                var oldHandler = oldHandlers[i], newHandler = newHandlers[i];

                if (!oldHandler || oldHandler.handler !== newHandler.handler) {
                    handlerChanged = true;
                }

                if (handlerChanged) {
                    handlers.entered.push(newHandler);
                    if (oldHandler) {
                        handlers.exited.unshift(oldHandler);
                    }
                } else if (contextChanged || oldHandler.context !== newHandler.context) {
                    contextChanged = true;
                    handlers.updatedContext.push(newHandler);
                } else {
                    handlers.unchanged.push(oldHandler);
                }
            }

            for (i = newHandlers.length, l = oldHandlers.length; i < l; i++) {
                handlers.exited.unshift(oldHandlers[i]);
            }

            handlers.reset = handlers.updatedContext.slice();
            handlers.reset.reverse();

            return handlers;
        }

        function updateURL(transition, state, inputUrl) {
            var urlMethod = transition.urlMethod;

            if (!urlMethod) {
                return;
            }

            var router = transition.router,
            handlerInfos = state.handlerInfos,
            handlerName = handlerInfos[handlerInfos.length - 1].name,
            params = {};

            for (var i = handlerInfos.length - 1; i >= 0; --i) {
                var handlerInfo = handlerInfos[i];
                merge(params, handlerInfo.params);
                if (handlerInfo.handler.inaccessibleByURL) {
                    urlMethod = null;
                }
            }

            if (urlMethod) {
                params.queryParams = transition._visibleQueryParams || state.queryParams;
                var url = router.recognizer.generate(handlerName, params);

                if (urlMethod === 'replace') {
                    router.replaceURL(url);
                } else {
                    router.updateURL(url);
                }
            }
        }

        /**
              @private

              Updates the URL (if necessary) and calls `setupContexts`
              to update the router's array of `currentHandlerInfos`.
             */
        function finalizeTransition(transition, newState) {

            try {
                log(transition.router, transition.sequence, "Resolved all models on destination route; finalizing transition.");

                var router = transition.router,
                handlerInfos = newState.handlerInfos,
                seq = transition.sequence;

                // Run all the necessary enter/setup/exit hooks
                setupContexts(router, newState, transition);

                // Check if a redirect occurred in enter/setup
                if (transition.isAborted) {
                    // TODO: cleaner way? distinguish b/w targetHandlerInfos?
                    router.state.handlerInfos = router.currentHandlerInfos;
                    return Promise.reject(logAbort(transition));
                }

                updateURL(transition, newState, transition.intent.url);

                transition.isActive = false;
                router.activeTransition = null;

                trigger(router, router.currentHandlerInfos, true, ['didTransition']);

                if (router.didTransition) {
                    router.didTransition(router.currentHandlerInfos);
                }

                log(router, transition.sequence, "TRANSITION COMPLETE.");

                // Resolve with the final handler.
                return handlerInfos[handlerInfos.length - 1].handler;
            } catch (e) {
                if (!((e instanceof TransitionAborted))) {
                    //var erroneousHandler = handlerInfos.pop();
                    var infos = transition.state.handlerInfos;
                    transition.trigger(true, 'error', e, transition, infos[infos.length-1].handler);
                    transition.abort();
                }

                throw e;
            }
        }

        /**
              @private

              Begins and returns a Transition based on the provided
              arguments. Accepts arguments in the form of both URL
              transitions and named transitions.

              @param {Router} router
              @param {Array[Object]} args arguments passed to transitionTo,
                replaceWith, or handleURL
            */
        function doTransition(router, args, isIntermediate) {
            // Normalize blank transitions to root URL transitions.
            var name = args[0] || '/';

            var lastArg = args[args.length-1];
            var queryParams = {};
            if (lastArg && lastArg.hasOwnProperty('queryParams')) {
                queryParams = pop.call(args).queryParams;
            }

            var intent;
            if (args.length === 0) {

                log(router, "Updating query params");

                // A query param update is really just a transition
                // into the route you're already on.
                var handlerInfos = router.state.handlerInfos;
                intent = new NamedTransitionIntent({
                    name: handlerInfos[handlerInfos.length - 1].name,
                    contexts: [],
                    queryParams: queryParams
                });

            } else if (name.charAt(0) === '/') {

                log(router, "Attempting URL transition to " + name);
                intent = new URLTransitionIntent({
                    url: name 
                });

            } else {

                log(router, "Attempting transition to " + name);
                intent = new NamedTransitionIntent({
                    name: args[0],
                    contexts: slice.call(args, 1),
                    queryParams: queryParams
                });
            }

            return router.transitionByIntent(intent, isIntermediate);
        }

        function handlerInfosEqual(handlerInfos, otherHandlerInfos) {
            if (handlerInfos.length !== otherHandlerInfos.length) {
                return false;
            }

            for (var i = 0, len = handlerInfos.length; i < len; ++i) {
                if (handlerInfos[i] !== otherHandlerInfos[i]) {
                    return false;
                }
            }
            return true;
        }

        function finalizeQueryParamChange(router, resolvedHandlers, newQueryParams, transition) {
            // We fire a finalizeQueryParamChange event which
            // gives the new route hierarchy a chance to tell
            // us which query params it's consuming and what
            // their final values are. If a query param is
            // no longer consumed in the final route hierarchy,
            // its serialized segment will be removed
            // from the URL.

            for (var k in newQueryParams) {
                if (newQueryParams.hasOwnProperty(k) &&
                newQueryParams[k] === null) {
                    delete newQueryParams[k];
                }
            }

            var finalQueryParamsArray = [];
            trigger(router, resolvedHandlers, true, ['finalizeQueryParamChange', newQueryParams, finalQueryParamsArray, transition]);

            if (transition) {
                transition._visibleQueryParams = {};
            }

            var finalQueryParams = {};
            for (var i = 0, len = finalQueryParamsArray.length; i < len; ++i) {
                var qp = finalQueryParamsArray[i];
                finalQueryParams[qp.key] = qp.value;
                if (transition && qp.visible !== false) {
                    transition._visibleQueryParams[qp.key] = qp.value;
                }
            }
            return finalQueryParams;
        }

        function notifyExistingHandlers(router, newState, newTransition) {
            var oldHandlers = router.state.handlerInfos,
            changing = [],
            leavingIndex = null,
            leaving, leavingChecker, i, oldHandler, newHandler;

            for (i = 0; i < oldHandlers.length; i++) {
                oldHandler = oldHandlers[i];
                newHandler = newState.handlerInfos[i];

                if (!newHandler || oldHandler.name !== newHandler.name) {
                    leavingIndex = i;
                    break;
                }

                if (!newHandler.isResolved) {
                    changing.push(oldHandler);
                }
            }

            if (leavingIndex !== null) {
                leaving = oldHandlers.slice(leavingIndex, oldHandlers.length);
                leavingChecker = function(name) {
                    for (var h = 0; h < leaving.length; h++) {
                        if (leaving[h].name === name) {
                            return true;
                        }
                    }
                    return false;
                };

                router._triggerWillLeave(leaving, newTransition, leavingChecker);
            }

            if (changing.length > 0) {
                router._triggerWillChangeContext(changing, newTransition);
            }

            trigger(router, oldHandlers, true, ['willTransition', newTransition]);
        }

        __exports__["default"] = Router;
    });
    define("router/transition-intent",
    ["./utils", "exports"],
    function(__dependency1__, __exports__) {
        "use strict";
        var merge = __dependency1__.merge;

        function TransitionIntent(props) {
            this.initialize(props);

            // TODO: wat
            this.data = this.data || {};
        }

        TransitionIntent.prototype = {
            initialize: null,
            applyToState: null
        };

        __exports__["default"] = TransitionIntent;
    });
    define("router/transition-intent/named-transition-intent",
    ["../transition-intent", "../transition-state", "../handler-info/factory", "../utils", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
        "use strict";
        var TransitionIntent = __dependency1__["default"];
        var TransitionState = __dependency2__["default"];
        var handlerInfoFactory = __dependency3__["default"];
        var isParam = __dependency4__.isParam;
        var extractQueryParams = __dependency4__.extractQueryParams;
        var merge = __dependency4__.merge;
        var subclass = __dependency4__.subclass;

        __exports__["default"] = subclass(TransitionIntent, {
            name: null,
            pivotHandler: null,
            contexts: null,
            queryParams: null,

            initialize: function(props) {
                this.name = props.name;
                this.pivotHandler = props.pivotHandler;
                this.contexts = props.contexts || [];
                this.queryParams = props.queryParams;
            },

            applyToState: function(oldState, recognizer, getHandler, isIntermediate) {

                var partitionedArgs = extractQueryParams([this.name].concat(this.contexts)),
                pureArgs = partitionedArgs[0],
                queryParams = partitionedArgs[1],
                handlers = recognizer.handlersFor(pureArgs[0]);

                var targetRouteName = handlers[handlers.length-1].handler;

                return this.applyToHandlers(oldState, handlers, getHandler, targetRouteName, isIntermediate);
            },

            applyToHandlers: function(oldState, handlers, getHandler, targetRouteName, isIntermediate, checkingIfActive) {

                var i;
                var newState = new TransitionState();
                var objects = this.contexts.slice(0);

                var invalidateIndex = handlers.length;

                // Pivot handlers are provided for refresh transitions
                if (this.pivotHandler) {
                    for (i = 0; i < handlers.length; ++i) {
                        if (getHandler(handlers[i].handler) === this.pivotHandler) {
                            invalidateIndex = i;
                            break;
                        }
                    }
                }

                var pivotHandlerFound = !this.pivotHandler;

                for (i = handlers.length - 1; i >= 0; --i) {
                    var result = handlers[i];
                    var name = result.handler;
                    var handler = getHandler(name);

                    var oldHandlerInfo = oldState.handlerInfos[i];
                    var newHandlerInfo = null;

                    if (result.names.length > 0) {
                        if (i >= invalidateIndex) {
                            newHandlerInfo = this.createParamHandlerInfo(name, handler, result.names, objects, oldHandlerInfo);
                        } else {
                            newHandlerInfo = this.getHandlerInfoForDynamicSegment(name, handler, result.names, objects, oldHandlerInfo, targetRouteName, i);
                        }
                    } else {
                        // This route has no dynamic segment.
                        // Therefore treat as a param-based handlerInfo
                        // with empty params. This will cause the `model`
                        // hook to be called with empty params, which is desirable.
                        newHandlerInfo = this.createParamHandlerInfo(name, handler, result.names, objects, oldHandlerInfo);
                    }

                    if (checkingIfActive) {
                        // If we're performing an isActive check, we want to
                        // serialize URL params with the provided context, but
                        // ignore mismatches between old and new context.
                        newHandlerInfo = newHandlerInfo.becomeResolved(null, newHandlerInfo.context);
                        var oldContext = oldHandlerInfo && oldHandlerInfo.context;
                        if (result.names.length > 0 && newHandlerInfo.context === oldContext) {
                            // If contexts match in isActive test, assume params also match.
                            // This allows for flexibility in not requiring that every last
                            // handler provide a `serialize` method
                            newHandlerInfo.params = oldHandlerInfo && oldHandlerInfo.params;
                        }
                        newHandlerInfo.context = oldContext;
                    }

                    var handlerToUse = oldHandlerInfo;
                    if (i >= invalidateIndex || newHandlerInfo.shouldSupercede(oldHandlerInfo)) {
                        invalidateIndex = Math.min(i, invalidateIndex);
                        handlerToUse = newHandlerInfo;
                    }

                    if (isIntermediate && !checkingIfActive) {
                        handlerToUse = handlerToUse.becomeResolved(null, handlerToUse.context);
                    }

                    newState.handlerInfos.unshift(handlerToUse);
                }

                if (objects.length > 0) {
                    throw new Error("More context objects were passed than there are dynamic segments for the route: " + targetRouteName);
                }

                if (!isIntermediate) {
                    this.invalidateChildren(newState.handlerInfos, invalidateIndex);
                }

                merge(newState.queryParams, this.queryParams || {});

                return newState;
            },

            invalidateChildren: function(handlerInfos, invalidateIndex) {
                for (var i = invalidateIndex, l = handlerInfos.length; i < l; ++i) {
                    var handlerInfo = handlerInfos[i];
                    handlerInfos[i] = handlerInfos[i].getUnresolved();
                }
            },

            getHandlerInfoForDynamicSegment: function(name, handler, names, objects, oldHandlerInfo, targetRouteName, i) {

                var numNames = names.length;
                var objectToUse;
                if (objects.length > 0) {

                    // Use the objects provided for this transition.
                    objectToUse = objects[objects.length - 1];
                    if (isParam(objectToUse)) {
                        return this.createParamHandlerInfo(name, handler, names, objects, oldHandlerInfo);
                    } else {
                        objects.pop();
                    }
                } else if (oldHandlerInfo && oldHandlerInfo.name === name) {
                    // Reuse the matching oldHandlerInfo
                    return oldHandlerInfo;
                } else {
                    if (this.preTransitionState) {
                        var preTransitionHandlerInfo = this.preTransitionState.handlerInfos[i];
                        objectToUse = preTransitionHandlerInfo && preTransitionHandlerInfo.context;
                    } else {
                        // Ideally we should throw this error to provide maximal
                        // information to the user that not enough context objects
                        // were provided, but this proves too cumbersome in Ember
                        // in cases where inner template helpers are evaluated
                        // before parent helpers un-render, in which cases this
                        // error somewhat prematurely fires.
                        //throw new Error("Not enough context objects were provided to complete a transition to " + targetRouteName + ". Specifically, the " + name + " route needs an object that can be serialized into its dynamic URL segments [" + names.join(', ') + "]");
                        return oldHandlerInfo;
                    }
                }

                return handlerInfoFactory('object', {
                    name: name,
                    handler: handler,
                    context: objectToUse,
                    names: names
                });
            },

            createParamHandlerInfo: function(name, handler, names, objects, oldHandlerInfo) {
                var params = {};

                // Soak up all the provided string/numbers
                var numNames = names.length;
                while (numNames--) {

                    // Only use old params if the names match with the new handler
                    var oldParams = (oldHandlerInfo && name === oldHandlerInfo.name && oldHandlerInfo.params) || {};

                    var peek = objects[objects.length - 1];
                    var paramName = names[numNames];
                    if (isParam(peek)) {
                        params[paramName] = "" + objects.pop();
                    } else {
                        // If we're here, this means only some of the params
                        // were string/number params, so try and use a param
                        // value from a previous handler.
                        if (oldParams.hasOwnProperty(paramName)) {
                            params[paramName] = oldParams[paramName];
                        } else {
                            throw new Error("You didn't provide enough string/numeric parameters to satisfy all of the dynamic segments for route " + name);
                        }
                    }
                }

                return handlerInfoFactory('param', {
                    name: name,
                    handler: handler,
                    params: params
                });
            }
        });
    });
    define("router/transition-intent/url-transition-intent",
    ["../transition-intent", "../transition-state", "../handler-info/factory", "../utils", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
        "use strict";
        var TransitionIntent = __dependency1__["default"];
        var TransitionState = __dependency2__["default"];
        var handlerInfoFactory = __dependency3__["default"];
        var oCreate = __dependency4__.oCreate;
        var merge = __dependency4__.merge;
        var subclass = __dependency4__.subclass;

        __exports__["default"] = subclass(TransitionIntent, {
            url: null,

            initialize: function(props) {
                this.url = props.url;
            },

            applyToState: function(oldState, recognizer, getHandler) {
                var newState = new TransitionState();

                var results = recognizer.recognize(this.url),
                queryParams = {},
                i, len;

                if (!results) {
                    throw new UnrecognizedURLError(this.url);
                }

                var statesDiffer = false;

                for (i = 0, len = results.length; i < len; ++i) {
                    var result = results[i];
                    var name = result.handler;
                    var handler = getHandler(name);

                    if (handler.inaccessibleByURL) {
                        throw new UnrecognizedURLError(this.url);
                    }

                    var newHandlerInfo = handlerInfoFactory('param', {
                        name: name,
                        handler: handler,
                        params: result.params
                    });

                    var oldHandlerInfo = oldState.handlerInfos[i];
                    if (statesDiffer || newHandlerInfo.shouldSupercede(oldHandlerInfo)) {
                        statesDiffer = true;
                        newState.handlerInfos[i] = newHandlerInfo;
                    } else {
                        newState.handlerInfos[i] = oldHandlerInfo;
                    }
                }

                merge(newState.queryParams, results.queryParams);

                return newState;
            }
        });

        /**
              Promise reject reasons passed to promise rejection
              handlers for failed transitions.
             */
        function UnrecognizedURLError(message) {
            this.message = (message || "UnrecognizedURLError");
            this.name = "UnrecognizedURLError";
        }
    });
    define("router/transition-state",
    ["./handler-info", "./utils", "rsvp/promise", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        var ResolvedHandlerInfo = __dependency1__.ResolvedHandlerInfo;
        var forEach = __dependency2__.forEach;
        var promiseLabel = __dependency2__.promiseLabel;
        var Promise = __dependency3__["default"];

        function TransitionState(other) {
            this.handlerInfos = [];
            this.queryParams = {};
            this.params = {};
        }

        TransitionState.prototype = {
            handlerInfos: null,
            queryParams: null,
            params: null,

            promiseLabel: function(label) {
                var targetName = '';
                forEach(this.handlerInfos, function(handlerInfo) {
                    if (targetName !== '') {
                        targetName += '.';
                    }
                    targetName += handlerInfo.name;
                });
                return promiseLabel("'" + targetName + "': " + label);
            },

            resolve: function(shouldContinue, payload) {
                var self = this;
                // First, calculate params for this state. This is useful
                // information to provide to the various route hooks.
                var params = this.params;
                forEach(this.handlerInfos, function(handlerInfo) {
                    params[handlerInfo.name] = handlerInfo.params || {};
                });

                payload = payload || {};
                payload.resolveIndex = 0;

                var currentState = this;
                var wasAborted = false;

                // The prelude RSVP.resolve() asyncs us into the promise land.
                return Promise.resolve(null, this.promiseLabel("Start transition"))
                .then(resolveOneHandlerInfo, null, this.promiseLabel('Resolve handler'))['catch'](handleError, this.promiseLabel('Handle error'));

                function innerShouldContinue() {
                    return Promise.resolve(shouldContinue(), promiseLabel("Check if should continue"))['catch'](function(reason) {
                        // We distinguish between errors that occurred
                        // during resolution (e.g. beforeModel/model/afterModel),
                        // and aborts due to a rejecting promise from shouldContinue().
                        wasAborted = true;
                        return Promise.reject(reason);
                    }, promiseLabel("Handle abort"));
                }

                function handleError(error) {
                    // This is the only possible
                    // reject value of TransitionState#resolve
                    var handlerInfos = currentState.handlerInfos;
                    var errorHandlerIndex = payload.resolveIndex >= handlerInfos.length ?
                    handlerInfos.length - 1 : payload.resolveIndex;
                    return Promise.reject({
                        error: error,
                        handlerWithError: currentState.handlerInfos[errorHandlerIndex].handler,
                        wasAborted: wasAborted,
                        state: currentState
                    });
                }

                function proceed(resolvedHandlerInfo) {
                    var wasAlreadyResolved = currentState.handlerInfos[payload.resolveIndex].isResolved;

                    // Swap the previously unresolved handlerInfo with
                    // the resolved handlerInfo
                    currentState.handlerInfos[payload.resolveIndex++] = resolvedHandlerInfo;

                    if (!wasAlreadyResolved) {
                        // Call the redirect hook. The reason we call it here
                        // vs. afterModel is so that redirects into child
                        // routes don't re-run the model hooks for this
                        // already-resolved route.
                        var handler = resolvedHandlerInfo.handler;
                        if (handler && handler.redirect) {
                            handler.redirect(resolvedHandlerInfo.context, payload);
                        }
                    }

                    // Proceed after ensuring that the redirect hook
                    // didn't abort this transition by transitioning elsewhere.
                    return innerShouldContinue().then(resolveOneHandlerInfo, null, promiseLabel('Resolve handler'));
                }

                function resolveOneHandlerInfo() {
                    if (payload.resolveIndex === currentState.handlerInfos.length) {
                        // This is is the only possible
                        // fulfill value of TransitionState#resolve
                        return {
                            error: null,
                            state: currentState
                        };
                    }

                    var handlerInfo = currentState.handlerInfos[payload.resolveIndex];

                    return handlerInfo.resolve(innerShouldContinue, payload)
                    .then(proceed, null, promiseLabel('Proceed'));
                }
            }
        };

        __exports__["default"] = TransitionState;
    });
    define("router/transition",
    ["rsvp/promise", "./handler-info", "./utils", "exports"],
    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
        "use strict";
        var Promise = __dependency1__["default"];
        var ResolvedHandlerInfo = __dependency2__.ResolvedHandlerInfo;
        var trigger = __dependency3__.trigger;
        var slice = __dependency3__.slice;
        var log = __dependency3__.log;
        var promiseLabel = __dependency3__.promiseLabel;

        /**
              @private

              A Transition is a thennable (a promise-like object) that represents
              an attempt to transition to another route. It can be aborted, either
              explicitly via `abort` or by attempting another transition while a
              previous one is still underway. An aborted transition can also
              be `retry()`d later.
             */
        function Transition(router, intent, state, error) {
            var transition = this;
            this.state = state || router.state;
            this.intent = intent;
            this.router = router;
            this.data = this.intent && this.intent.data || {};
            this.resolvedModels = {};
            this.queryParams = {};

            if (error) {
                this.promise = Promise.reject(error);
                return;
            }

            if (state) {
                this.params = state.params;
                this.queryParams = state.queryParams;
                this.handlerInfos = state.handlerInfos;

                var len = state.handlerInfos.length;
                if (len) {
                    this.targetName = state.handlerInfos[state.handlerInfos.length-1].name;
                }

                for (var i = 0; i < len; ++i) {
                    var handlerInfo = state.handlerInfos[i];

                    // TODO: this all seems hacky
                    if (!handlerInfo.isResolved) {
                        break;
                    }
                    this.pivotHandler = handlerInfo.handler;
                }

                this.sequence = Transition.currentSequence++;
                this.promise = state.resolve(checkForAbort, this)['catch'](function(result) {
                    if (result.wasAborted || transition.isAborted) {
                        return Promise.reject(logAbort(transition));
                    } else {
                        transition.trigger('error', result.error, transition, result.handlerWithError);
                        transition.abort();
                        return Promise.reject(result.error);
                    }
                }, promiseLabel('Handle Abort'));
            } else {
                this.promise = Promise.resolve(this.state);
                this.params = {};
            }

            function checkForAbort() {
                if (transition.isAborted) {
                    return Promise.reject(undefined, promiseLabel("Transition aborted - reject"));
                }
            }
        }

        Transition.currentSequence = 0;

        Transition.prototype = {
            targetName: null,
            urlMethod: 'update',
            intent: null,
            params: null,
            pivotHandler: null,
            resolveIndex: 0,
            handlerInfos: null,
            resolvedModels: null,
            isActive: true,
            state: null,
            queryParamsOnly: false,

            isTransition: true,

            isExiting: function(handler) {
                var handlerInfos = this.handlerInfos;
                for (var i = 0, len = handlerInfos.length; i < len; ++i) {
                    var handlerInfo = handlerInfos[i];
                    if (handlerInfo.name === handler || handlerInfo.handler === handler) {
                        return false;
                    }
                }
                return true;
            },

            /**
                    @public

                    The Transition's internal promise. Calling `.then` on this property
                    is that same as calling `.then` on the Transition object itself, but
                    this property is exposed for when you want to pass around a
                    Transition's promise, but not the Transition object itself, since
                    Transition object can be externally `abort`ed, while the promise
                    cannot.
                   */
            promise: null,

            /**
                    @public

                    Custom state can be stored on a Transition's `data` object.
                    This can be useful for decorating a Transition within an earlier
                    hook and shared with a later hook. Properties set on `data` will
                    be copied to new transitions generated by calling `retry` on this
                    transition.
                   */
            data: null,

            /**
                    @public

                    A standard promise hook that resolves if the transition
                    succeeds and rejects if it fails/redirects/aborts.

                    Forwards to the internal `promise` property which you can
                    use in situations where you want to pass around a thennable,
                    but not the Transition itself.

                    @param {Function} success
                    @param {Function} failure
                   */
            then: function(success, failure) {
                return this.promise.then(success, failure);
            },

            /**
                    @public

                    Aborts the Transition. Note you can also implicitly abort a transition
                    by initiating another transition while a previous one is underway.
                   */
            abort: function() {
                if (this.isAborted) {
                    return this;
                }
                log(this.router, this.sequence, this.targetName + ": transition was aborted");
                this.intent.preTransitionState = this.router.state;
                this.isAborted = true;
                this.isActive = false;
                this.router.activeTransition = null;
                return this;
            },

            /**
                    @public

                    Retries a previously-aborted transition (making sure to abort the
                    transition if it's still active). Returns a new transition that
                    represents the new attempt to transition.
                   */
            retry: function() {
                // TODO: add tests for merged state retry()s
                this.abort();
                return this.router.transitionByIntent(this.intent, false);
            },

            /**
                    @public

                    Sets the URL-changing method to be employed at the end of a
                    successful transition. By default, a new Transition will just
                    use `updateURL`, but passing 'replace' to this method will
                    cause the URL to update using 'replaceWith' instead. Omitting
                    a parameter will disable the URL change, allowing for transitions
                    that don't update the URL at completion (this is also used for
                    handleURL, since the URL has already changed before the
                    transition took place).

                    @param {String} method the type of URL-changing method to use
                      at the end of a transition. Accepted values are 'replace',
                      falsy values, or any other non-falsy value (which is
                      interpreted as an updateURL transition).

                    @return {Transition} this transition
                   */
            method: function(method) {
                this.urlMethod = method;
                return this;
            },

            /**
                    @public

                    Fires an event on the current list of resolved/resolving
                    handlers within this transition. Useful for firing events
                    on route hierarchies that haven't fully been entered yet.

                    Note: This method is also aliased as `send`

                    @param {Boolean} [ignoreFailure=false] a boolean specifying whether unhandled events throw an error
                    @param {String} name the name of the event to fire
                   */
            trigger: function (ignoreFailure) {
                var args = slice.call(arguments);
                if (typeof ignoreFailure === 'boolean') {
                    args.shift();
                } else {
                    // Throw errors on unhandled trigger events by default
                    ignoreFailure = false;
                }
                trigger(this.router, this.state.handlerInfos.slice(0, this.resolveIndex + 1), ignoreFailure, args);
            },

            /**
                    @public

                    Transitions are aborted and their promises rejected
                    when redirects occur; this method returns a promise
                    that will follow any redirects that occur and fulfill
                    with the value fulfilled by any redirecting transitions
                    that occur.

                    @return {Promise} a promise that fulfills with the same
                      value that the final redirecting transition fulfills with
                   */
            followRedirects: function() {
                var router = this.router;
                return this.promise['catch'](function(reason) {
                    if (router.activeTransition) {
                        return router.activeTransition.followRedirects();
                    }
                    return Promise.reject(reason);
                });
            },

            toString: function() {
                return "Transition (sequence " + this.sequence + ")";
            },

            /**
                    @private
                   */
            log: function(message) {
                log(this.router, this.sequence, message);
            }
        };

        // Alias 'trigger' as 'send'
        Transition.prototype.send = Transition.prototype.trigger;

        /**
              @private

              Logs and returns a TransitionAborted error.
             */
        function logAbort(transition) {
            log(transition.router, transition.sequence, "detected abort.");
            return new TransitionAborted();
        }

        function TransitionAborted(message) {
            this.message = (message || "TransitionAborted");
            this.name = "TransitionAborted";
        }

        __exports__.Transition = Transition;
        __exports__.logAbort = logAbort;
        __exports__.TransitionAborted = TransitionAborted;
    });
    define("router/utils",
    ["exports"],
    function(__exports__) {
        "use strict";
        var slice = Array.prototype.slice;

        var _isArray;
        if (!Array.isArray) {
            _isArray = function (x) {
                return Object.prototype.toString.call(x) === "[object Array]";
            };
        } else {
            _isArray = Array.isArray;
        }

        var isArray = _isArray;
        __exports__.isArray = isArray;
        function merge(hash, other) {
            for (var prop in other) {
                if (other.hasOwnProperty(prop)) {
                    hash[prop] = other[prop];
                }
            }
        }

        var oCreate = Object.create || function(proto) {
            function F() {}
            F.prototype = proto;
            return new F();
        };
        __exports__.oCreate = oCreate;
        /**
              @private

              Extracts query params from the end of an array
            **/
        function extractQueryParams(array) {
            var len = (array && array.length), head, queryParams;

            if (len && len > 0 && array[len - 1] && array[len - 1].hasOwnProperty('queryParams')) {
                queryParams = array[len - 1].queryParams;
                head = slice.call(array, 0, len - 1);
                return [head, queryParams];
            } else {
                return [array, null];
            }
        }

        __exports__.extractQueryParams = extractQueryParams; /**
              @private

              Coerces query param properties and array elements into strings.
            **/
        function coerceQueryParamsToString(queryParams) {
            for (var key in queryParams) {
                if (typeof queryParams[key] === 'number') {
                    queryParams[key] = '' + queryParams[key];
                } else if (isArray(queryParams[key])) {
                    for (var i = 0, l = queryParams[key].length; i < l; i++) {
                        queryParams[key][i] = '' + queryParams[key][i];
                    }
                }
            }
        }
        /**
              @private
             */
        function log(router, sequence, msg) {
            if (!router.log) {
                return;
            }

            if (arguments.length === 3) {
                router.log("Transition #" + sequence + ": " + msg);
            } else {
                msg = sequence;
                router.log(msg);
            }
        }

        __exports__.log = log;
        function bind(context, fn) {
            var boundArgs = arguments;
            return function(value) {
                var args = slice.call(boundArgs, 2);
                args.push(value);
                return fn.apply(context, args);
            };
        }

        __exports__.bind = bind;
        function isParam(object) {
            return (typeof object === "string" || object instanceof String || typeof object === "number" || object instanceof Number);
        }


        function forEach(array, callback) {
            for (var i = 0, l = array.length; i < l && false !== callback(array[i]); i++) {}
        }

        __exports__.forEach = forEach;
        function trigger(router, handlerInfos, ignoreFailure, args) {
            if (router.triggerEvent) {
                router.triggerEvent(handlerInfos, ignoreFailure, args);
                return;
            }

            var name = args.shift();

            if (!handlerInfos) {
                if (ignoreFailure) {
                    return;
                }
                throw new Error("Could not trigger event '" + name + "'. There are no active handlers");
            }

            var eventWasHandled = false;

            for (var i = handlerInfos.length-1; i >= 0; i--) {
                var handlerInfo = handlerInfos[i],
                handler = handlerInfo.handler;

                if (handler.events && handler.events[name]) {
                    if (handler.events[name].apply(handler, args) === true) {
                        eventWasHandled = true;
                    } else {
                        return;
                    }
                }
            }

            if (!eventWasHandled && !ignoreFailure) {
                throw new Error("Nothing handled the event '" + name + "'.");
            }
        }

        __exports__.trigger = trigger;
        function getChangelist(oldObject, newObject) {
            var key;
            var results = {
                all: {},
                changed: {},
                removed: {}
            };

            merge(results.all, newObject);

            var didChange = false;
            coerceQueryParamsToString(oldObject);
            coerceQueryParamsToString(newObject);

            // Calculate removals
            for (key in oldObject) {
                if (oldObject.hasOwnProperty(key)) {
                    if (!newObject.hasOwnProperty(key)) {
                        didChange = true;
                        results.removed[key] = oldObject[key];
                    }
                }
            }

            // Calculate changes
            for (key in newObject) {
                if (newObject.hasOwnProperty(key)) {
                    if (isArray(oldObject[key]) && isArray(newObject[key])) {
                        if (oldObject[key].length !== newObject[key].length) {
                            results.changed[key] = newObject[key];
                            didChange = true;
                        } else {
                            for (var i = 0, l = oldObject[key].length; i < l; i++) {
                                if (oldObject[key][i] !== newObject[key][i]) {
                                    results.changed[key] = newObject[key];
                                    didChange = true;
                                }
                            }
                        }
                    } else {
                        if (oldObject[key] !== newObject[key]) {
                            results.changed[key] = newObject[key];
                            didChange = true;
                        }
                    }
                }
            }

            return didChange && results;
        }

        __exports__.getChangelist = getChangelist;
        function promiseLabel(label) {
            return 'Router: ' + label;
        }

        __exports__.promiseLabel = promiseLabel;
        function subclass(parentConstructor, proto) {
            function C(props) {
                parentConstructor.call(this, props || {});
            }
            C.prototype = oCreate(parentConstructor.prototype);
            merge(C.prototype, proto);
            return C;
        }

        __exports__.subclass = subclass;
        __exports__.merge = merge;
        __exports__.slice = slice;
        __exports__.isParam = isParam;
        __exports__.coerceQueryParamsToString = coerceQueryParamsToString;
    });
    define("router",
    ["./router/router", "exports"],
    function(__dependency1__, __exports__) {
        "use strict";
        var Router = __dependency1__["default"];

        __exports__["default"] = Router;
    });
    /**
      @class RSVP
      @module RSVP
      */
    define('rsvp/-internal', [
    './utils',
    './instrument',
    './config',
    'exports'
    ], function (__dependency1__, __dependency2__, __dependency3__, __exports__) {
        'use strict';
        var objectOrFunction = __dependency1__.objectOrFunction;
        var isFunction = __dependency1__.isFunction;
        var now = __dependency1__.now;
        var instrument = __dependency2__['default'];
        var config = __dependency3__.config;
        function noop() {}
        var PENDING = void 0;
        var FULFILLED = 1;
        var REJECTED = 2;
        var GET_THEN_ERROR = new ErrorObject();
        function getThen(promise) {
            try {
                return promise.then;
            } catch (error) {
                GET_THEN_ERROR.error = error;
                return GET_THEN_ERROR;
            }
        }
        function tryThen(then, value, fulfillmentHandler, rejectionHandler) {
            try {
                then.call(value, fulfillmentHandler, rejectionHandler);
            } catch (e) {
                return e;
            }
        }
        function handleForeignThenable(promise, thenable, then) {
            config.async(function (promise$2) {
                var sealed = false;
                var error = tryThen(then, thenable, function (value) {
                    if (sealed) {
                        return;
                    }
                    sealed = true;
                    if (thenable !== value) {
                        resolve(promise$2, value);
                    } else {
                        fulfill(promise$2, value);
                    }
                }, function (reason) {
                    if (sealed) {
                        return;
                    }
                    sealed = true;
                    reject(promise$2, reason);
                }, 'Settle: ' + (promise$2._label || ' unknown promise'));
                if (!sealed && error) {
                    sealed = true;
                    reject(promise$2, error);
                }
            }, promise);
        }
        function handleOwnThenable(promise, thenable) {
            promise._onerror = null;
            if (thenable._state === FULFILLED) {
                fulfill(promise, thenable._result);
            } else if (promise._state === REJECTED) {
                reject(promise, thenable._result);
            } else {
                subscribe(thenable, undefined, function (value) {
                    if (thenable !== value) {
                        resolve(promise, value);
                    } else {
                        fulfill(promise, value);
                    }
                }, function (reason) {
                    reject(promise, reason);
                });
            }
        }
        function handleMaybeThenable(promise, maybeThenable) {
            if (maybeThenable instanceof promise.constructor) {
                handleOwnThenable(promise, maybeThenable);
            } else {
                var then = getThen(maybeThenable);
                if (then === GET_THEN_ERROR) {
                    reject(promise, GET_THEN_ERROR.error);
                } else if (then === undefined) {
                    fulfill(promise, maybeThenable);
                } else if (isFunction(then)) {
                    handleForeignThenable(promise, maybeThenable, then);
                } else {
                    fulfill(promise, maybeThenable);
                }
            }
        }
        function resolve(promise, value) {
            if (promise === value) {
                fulfill(promise, value);
            } else if (objectOrFunction(value)) {
                handleMaybeThenable(promise, value);
            } else {
                fulfill(promise, value);
            }
        }
        function publishRejection(promise) {
            if (promise._onerror) {
                promise._onerror(promise._result);
            }
            publish(promise);
        }
        function fulfill(promise, value) {
            if (promise._state !== PENDING) {
                return;
            }
            promise._result = value;
            promise._state = FULFILLED;
            if (promise._subscribers.length === 0) {
                if (config.instrument) {
                    instrument('fulfilled', promise);
                }
            } else {
                config.async(publish, promise);
            }
        }
        function reject(promise, reason) {
            if (promise._state !== PENDING) {
                return;
            }
            promise._state = REJECTED;
            promise._result = reason;
            config.async(publishRejection, promise);
        }
        function subscribe(parent, child, onFulfillment, onRejection) {
            var subscribers = parent._subscribers;
            var length = subscribers.length;
            parent._onerror = null;
            subscribers[length] = child;
            subscribers[length + FULFILLED] = onFulfillment;
            subscribers[length + REJECTED] = onRejection;
            if (length === 0 && parent._state) {
                config.async(publish, parent);
            }
        }
        function publish(promise) {
            var subscribers = promise._subscribers;
            var settled = promise._state;
            if (config.instrument) {
                instrument(settled === FULFILLED ? 'fulfilled' : 'rejected', promise);
            }
            if (subscribers.length === 0) {
                return;
            }
            var child, callback, detail = promise._result;
            for (var i = 0; i < subscribers.length; i += 3) {
                child = subscribers[i];
                callback = subscribers[i + settled];
                if (child) {
                    invokeCallback(settled, child, callback, detail);
                } else {
                    callback(detail);
                }
            }
            promise._subscribers.length = 0;
        }
        function ErrorObject() {
            this.error = null;
        }
        var TRY_CATCH_ERROR = new ErrorObject();
        function tryCatch(callback, detail) {
            try {
                return callback(detail);
            } catch (e) {
                TRY_CATCH_ERROR.error = e;
                return TRY_CATCH_ERROR;
            }
        }
        function invokeCallback(settled, promise, callback, detail) {
            var hasCallback = isFunction(callback), value, error, succeeded, failed;
            if (hasCallback) {
                value = tryCatch(callback, detail);
                if (value === TRY_CATCH_ERROR) {
                    failed = true;
                    error = value.error;
                    value = null;
                } else {
                    succeeded = true;
                }
                if (promise === value) {
                    reject(promise, new TypeError('A promises callback cannot return that same promise.'));
                    return;
                }
            } else {
                value = detail;
                succeeded = true;
            }
            if (promise._state !== PENDING) {}
            // noop
            else if (hasCallback && succeeded) {
                resolve(promise, value);
            } else if (failed) {
                reject(promise, error);
            } else if (settled === FULFILLED) {
                fulfill(promise, value);
            } else if (settled === REJECTED) {
                reject(promise, value);
            }
        }
        function initializePromise(promise, resolver) {
            try {
                resolver(function resolvePromise(value) {
                    resolve(promise, value);
                }, function rejectPromise(reason) {
                    reject(promise, reason);
                });
            } catch (e) {
                reject(promise, e);
            }
        }
        __exports__.noop = noop;
        __exports__.resolve = resolve;
        __exports__.reject = reject;
        __exports__.fulfill = fulfill;
        __exports__.subscribe = subscribe;
        __exports__.publish = publish;
        __exports__.publishRejection = publishRejection;
        __exports__.initializePromise = initializePromise;
        __exports__.invokeCallback = invokeCallback;
        __exports__.FULFILLED = FULFILLED;
        __exports__.REJECTED = REJECTED;
    });
    define('rsvp/all-settled', [
    './enumerator',
    './promise',
    './utils',
    'exports'
    ], function (__dependency1__, __dependency2__, __dependency3__, __exports__) {
        'use strict';
        var Enumerator = __dependency1__['default'];
        var makeSettledResult = __dependency1__.makeSettledResult;
        var Promise = __dependency2__['default'];
        var o_create = __dependency3__.o_create;
        function AllSettled(Constructor, entries, label) {
            this._superConstructor(Constructor, entries, false, label);
        }
        AllSettled.prototype = o_create(Enumerator.prototype);
        AllSettled.prototype._superConstructor = Enumerator;
        AllSettled.prototype._makeResult = makeSettledResult;
        AllSettled.prototype._validationError = function () {
            return new Error('allSettled must be called with an array');
        };
        /**
              `RSVP.allSettled` is similar to `RSVP.all`, but instead of implementing
              a fail-fast method, it waits until all the promises have returned and
              shows you all the results. This is useful if you want to handle multiple
              promises' failure states together as a set.

              Returns a promise that is fulfilled when all the given promises have been
              settled. The return promise is fulfilled with an array of the states of
              the promises passed into the `promises` array argument.

              Each state object will either indicate fulfillment or rejection, and
              provide the corresponding value or reason. The states will take one of
              the following formats:

              ```javascript
              { state: 'fulfilled', value: value }
                or
              { state: 'rejected', reason: reason }
              ```

              Example:

              ```javascript
              var promise1 = RSVP.Promise.resolve(1);
              var promise2 = RSVP.Promise.reject(new Error('2'));
              var promise3 = RSVP.Promise.reject(new Error('3'));
              var promises = [ promise1, promise2, promise3 ];

              RSVP.allSettled(promises).then(function(array){
                // array == [
                //   { state: 'fulfilled', value: 1 },
                //   { state: 'rejected', reason: Error },
                //   { state: 'rejected', reason: Error }
                // ]
                // Note that for the second item, reason.message will be "2", and for the
                // third item, reason.message will be "3".
              }, function(error) {
                // Not run. (This block would only be called if allSettled had failed,
                // for instance if passed an incorrect argument type.)
              });
              ```

              @method allSettled
              @static
              @for RSVP
              @param {Array} promises
              @param {String} label - optional string that describes the promise.
              Useful for tooling.
              @return {Promise} promise that is fulfilled with an array of the settled
              states of the constituent promises.
            */
        __exports__['default'] = function allSettled(entries, label) {
            return new AllSettled(Promise, entries, label).promise;
        };
    });
    define('rsvp/all', [
    './promise',
    'exports'
    ], function (__dependency1__, __exports__) {
        'use strict';
        var Promise = __dependency1__['default'];
        /**
              This is a convenient alias for `RSVP.Promise.all`.

              @method all
              @static
              @for RSVP
              @param {Array} array Array of promises.
              @param {String} label An optional label. This is useful
              for tooling.
            */
        __exports__['default'] = function all(array, label) {
            return Promise.all(array, label);
        };
    });
    define('rsvp/asap', ['exports'], function (__exports__) {
        'use strict';
        var length = 0;
        __exports__['default'] = function asap(callback, arg) {
            queue[length] = callback;
            queue[length + 1] = arg;
            length += 2;
            if (length === 2) {
                // If length is 1, that means that we need to schedule an async flush.
                // If additional callbacks are queued before the queue is flushed, they
                // will be processed by this flush that we are scheduling.
                scheduleFlush();
            }
        };
        var browserGlobal = typeof window !== 'undefined' ? window : {};
        var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
        // test for web worker but not in IE10
        var isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined';
        // node
        function useNextTick() {
            return function () {
                process.nextTick(flush);
            };
        }
        function useMutationObserver() {
            var iterations = 0;
            var observer = new BrowserMutationObserver(flush);
            var node = document.createTextNode('');
            observer.observe(node, {
                characterData: true 
            });
            return function () {
                node.data = iterations = ++iterations % 2;
            };
        }
        // web worker
        function useMessageChannel() {
            var channel = new MessageChannel();
            channel.port1.onmessage = flush;
            return function () {
                channel.port2.postMessage(0);
            };
        }
        function useSetTimeout() {
            return function () {
                setTimeout(flush, 1);
            };
        }
        var queue = new Array(1000);
        function flush() {
            for (var i = 0; i < length; i += 2) {
                var callback = queue[i];
                var arg = queue[i + 1];
                callback(arg);
                queue[i] = undefined;
                queue[i + 1] = undefined;
            }
            length = 0;
        }
        var scheduleFlush;
        // Decide what async method to use to triggering processing of queued callbacks:
        if (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]') {
            scheduleFlush = useNextTick();
        } else if (BrowserMutationObserver) {
            scheduleFlush = useMutationObserver();
        } else if (isWorker) {
            scheduleFlush = useMessageChannel();
        } else {
            scheduleFlush = useSetTimeout();
        }
    });
    define('rsvp/config', [
    './events',
    'exports'
    ], function (__dependency1__, __exports__) {
        'use strict';
        var EventTarget = __dependency1__['default'];
        var config = {
            instrument: false 
        };
        EventTarget.mixin(config);
        function configure(name, value) {
            if (name === 'onerror') {
                // handle for legacy users that expect the actual
                // error to be passed to their function added via
                // `RSVP.configure('onerror', someFunctionHere);`
                config.on('error', value);
                return;
            }
            if (arguments.length === 2) {
                config[name] = value;
            } else {
                return config[name];
            }
        }
        __exports__.config = config;
        __exports__.configure = configure;
    });
    define('rsvp/defer', [
    './promise',
    'exports'
    ], function (__dependency1__, __exports__) {
        'use strict';
        var Promise = __dependency1__['default'];
        /**
              `RSVP.defer` returns an object similar to jQuery's `$.Deferred`.
              `RSVP.defer` should be used when porting over code reliant on `$.Deferred`'s
              interface. New code should use the `RSVP.Promise` constructor instead.

              The object returned from `RSVP.defer` is a plain object with three properties:

              * promise - an `RSVP.Promise`.
              * reject - a function that causes the `promise` property on this object to
                become rejected
              * resolve - a function that causes the `promise` property on this object to
                become fulfilled.

              Example:

               ```javascript
               var deferred = RSVP.defer();

               deferred.resolve("Success!");

               defered.promise.then(function(value){
                 // value here is "Success!"
               });
               ```

              @method defer
              @static
              @for RSVP
              @param {String} label optional string for labeling the promise.
              Useful for tooling.
              @return {Object}
             */
        __exports__['default'] = function defer(label) {
            var deferred = {};
            deferred.promise = new Promise(function (resolve, reject) {
                deferred.resolve = resolve;
                deferred.reject = reject;
            }, label);
            return deferred;
        };
    });
    define('rsvp/enumerator', [
    './utils',
    './-internal',
    'exports'
    ], function (__dependency1__, __dependency2__, __exports__) {
        'use strict';
        var isArray = __dependency1__.isArray;
        var isMaybeThenable = __dependency1__.isMaybeThenable;
        var noop = __dependency2__.noop;
        var reject = __dependency2__.reject;
        var fulfill = __dependency2__.fulfill;
        var subscribe = __dependency2__.subscribe;
        var FULFILLED = __dependency2__.FULFILLED;
        var REJECTED = __dependency2__.REJECTED;
        var PENDING = __dependency2__.PENDING;
        var ABORT_ON_REJECTION = true;
        __exports__.ABORT_ON_REJECTION = ABORT_ON_REJECTION;
        function makeSettledResult(state, position, value) {
            if (state === FULFILLED) {
                return {
                    state: 'fulfilled',
                    value: value
                };
            } else {
                return {
                    state: 'rejected',
                    reason: value
                };
            }
        }
        __exports__.makeSettledResult = makeSettledResult;
        function Enumerator(Constructor, input, abortOnReject, label) {
            this._instanceConstructor = Constructor;
            this.promise = new Constructor(noop, label);
            this._abortOnReject = abortOnReject;
            if (this._validateInput(input)) {
                this._input = input;
                this.length = input.length;
                this._remaining = input.length;
                this._init();
                if (this.length === 0) {
                    fulfill(this.promise, this._result);
                } else {
                    this.length = this.length || 0;
                    this._enumerate();
                    if (this._remaining === 0) {
                        fulfill(this.promise, this._result);
                    }
                }
            } else {
                reject(this.promise, this._validationError());
            }
        }
        Enumerator.prototype._validateInput = function (input) {
            return isArray(input);
        };
        Enumerator.prototype._validationError = function () {
            return new Error('Array Methods must be provided an Array');
        };
        Enumerator.prototype._init = function () {
            this._result = new Array(this.length);
        };
        __exports__['default'] = Enumerator;
        Enumerator.prototype._enumerate = function () {
            var length = this.length;
            var promise = this.promise;
            var input = this._input;
            for (var i = 0; promise._state === PENDING && i < length; i++) {
                this._eachEntry(input[i], i);
            }
        };
        Enumerator.prototype._eachEntry = function (entry, i) {
            var c = this._instanceConstructor;
            if (isMaybeThenable(entry)) {
                if (entry.constructor === c && entry._state !== PENDING) {
                    entry._onerror = null;
                    this._settledAt(entry._state, i, entry._result);
                } else {
                    this._willSettleAt(c.resolve(entry), i);
                }
            } else {
                this._remaining--;
                this._result[i] = this._makeResult(FULFILLED, i, entry);
            }
        };
        Enumerator.prototype._settledAt = function (state, i, value) {
            var promise = this.promise;
            if (promise._state === PENDING) {
                this._remaining--;
                if (this._abortOnReject && state === REJECTED) {
                    reject(promise, value);
                } else {
                    this._result[i] = this._makeResult(state, i, value);
                }
            }
            if (this._remaining === 0) {
                fulfill(promise, this._result);
            }
        };
        Enumerator.prototype._makeResult = function (state, i, value) {
            return value;
        };
        Enumerator.prototype._willSettleAt = function (promise, i) {
            var enumerator = this;
            subscribe(promise, undefined, function (value) {
                enumerator._settledAt(FULFILLED, i, value);
            }, function (reason) {
                enumerator._settledAt(REJECTED, i, reason);
            });
        };
    });
    define('rsvp/events', ['exports'], function (__exports__) {
        'use strict';
        function indexOf(callbacks, callback) {
            for (var i = 0, l = callbacks.length; i < l; i++) {
                if (callbacks[i] === callback) {
                    return i;
                }
            }
            return -1;
        }
        function callbacksFor(object) {
            var callbacks = object._promiseCallbacks;
            if (!callbacks) {
                callbacks = object._promiseCallbacks = {};
            }
            return callbacks;
        }
        /**
              @class RSVP.EventTarget
            */
        __exports__['default'] = {
            mixin: function (object) {
                object.on = this.on;
                object.off = this.off;
                object.trigger = this.trigger;
                object._promiseCallbacks = undefined;
                return object;
            },
            on: function (eventName, callback) {
                var allCallbacks = callbacksFor(this), callbacks;
                callbacks = allCallbacks[eventName];
                if (!callbacks) {
                    callbacks = allCallbacks[eventName] = [];
                }
                if (indexOf(callbacks, callback) === -1) {
                    callbacks.push(callback);
                }
            },
            off: function (eventName, callback) {
                var allCallbacks = callbacksFor(this), callbacks, index;
                if (!callback) {
                    allCallbacks[eventName] = [];
                    return;
                }
                callbacks = allCallbacks[eventName];
                index = indexOf(callbacks, callback);
                if (index !== -1) {
                    callbacks.splice(index, 1);
                }
            },
            trigger: function (eventName, options) {
                var allCallbacks = callbacksFor(this), callbacks, callbackTuple, callback, binding;
                if (callbacks = allCallbacks[eventName]) {
                    // Don't cache the callbacks.length since it may grow
                    for (var i = 0; i < callbacks.length; i++) {
                        callback = callbacks[i];
                        callback(options);
                    }
                }
            }
        };
    });
    define('rsvp/filter', [
    './promise',
    './utils',
    'exports'
    ], function (__dependency1__, __dependency2__, __exports__) {
        'use strict';
        var Promise = __dependency1__['default'];
        var isFunction = __dependency2__.isFunction;
        var isMaybeThenable = __dependency2__.isMaybeThenable;
        /**
             `RSVP.filter` is similar to JavaScript's native `filter` method, except that it
              waits for all promises to become fulfilled before running the `filterFn` on
              each item in given to `promises`. `RSVP.filter` returns a promise that will
              become fulfilled with the result of running `filterFn` on the values the
              promises become fulfilled with.

              For example:

              ```javascript

              var promise1 = RSVP.resolve(1);
              var promise2 = RSVP.resolve(2);
              var promise3 = RSVP.resolve(3);

              var promises = [promise1, promise2, promise3];

              var filterFn = function(item){
                return item > 1;
              };

              RSVP.filter(promises, filterFn).then(function(result){
                // result is [ 2, 3 ]
              });
              ```

              If any of the `promises` given to `RSVP.filter` are rejected, the first promise
              that is rejected will be given as an argument to the returned promise's
              rejection handler. For example:

              ```javascript
              var promise1 = RSVP.resolve(1);
              var promise2 = RSVP.reject(new Error("2"));
              var promise3 = RSVP.reject(new Error("3"));
              var promises = [ promise1, promise2, promise3 ];

              var filterFn = function(item){
                return item > 1;
              };

              RSVP.filter(promises, filterFn).then(function(array){
                // Code here never runs because there are rejected promises!
              }, function(reason) {
                // reason.message === "2"
              });
              ```

              `RSVP.filter` will also wait for any promises returned from `filterFn`.
              For instance, you may want to fetch a list of users then return a subset
              of those users based on some asynchronous operation:

              ```javascript

              var alice = { name: 'alice' };
              var bob   = { name: 'bob' };
              var users = [ alice, bob ];

              var promises = users.map(function(user){
                return RSVP.resolve(user);
              });

              var filterFn = function(user){
                // Here, Alice has permissions to create a blog post, but Bob does not.
                return getPrivilegesForUser(user).then(function(privs){
                  return privs.can_create_blog_post === true;
                });
              };
              RSVP.filter(promises, filterFn).then(function(users){
                // true, because the server told us only Alice can create a blog post.
                users.length === 1;
                // false, because Alice is the only user present in `users`
                users[0] === bob;
              });
              ```

              @method filter
              @static
              @for RSVP
              @param {Array} promises
              @param {Function} filterFn - function to be called on each resolved value to
              filter the final results.
              @param {String} label optional string describing the promise. Useful for
              tooling.
              @return {Promise}
            */
        __exports__['default'] = function filter(promises, filterFn, label) {
            return Promise.all(promises, label).then(function (values) {
                if (!isFunction(filterFn)) {
                    throw new TypeError('You must pass a function as filter\'s second argument.');
                }
                var length = values.length;
                var filtered = new Array(length);
                for (var i = 0; i < length; i++) {
                    filtered[i] = filterFn(values[i]);
                }
                return Promise.all(filtered, label).then(function (filtered$2) {
                    var results = new Array(length);
                    var newLength = 0;
                    for (var i$2 = 0; i$2 < length; i$2++) {
                        if (filtered$2[i$2]) {
                            results[newLength] = values[i$2];
                            newLength++;
                        }
                    }
                    results.length = newLength;
                    return results;
                });
            });
        };
    });
    define('rsvp/hash-settled', [
    './promise',
    './enumerator',
    './promise-hash',
    './utils',
    'exports'
    ], function (__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
        'use strict';
        var Promise = __dependency1__['default'];
        var makeSettledResult = __dependency2__.makeSettledResult;
        var PromiseHash = __dependency3__['default'];
        var Enumerator = __dependency2__['default'];
        var o_create = __dependency4__.o_create;
        function HashSettled(Constructor, object, label) {
            this._superConstructor(Constructor, object, false, label);
        }
        HashSettled.prototype = o_create(PromiseHash.prototype);
        HashSettled.prototype._superConstructor = Enumerator;
        HashSettled.prototype._makeResult = makeSettledResult;
        HashSettled.prototype._validationError = function () {
            return new Error('hashSettled must be called with an object');
        };
        /**
              `RSVP.hashSettled` is similar to `RSVP.allSettled`, but takes an object
              instead of an array for its `promises` argument.

              Unlike `RSVP.all` or `RSVP.hash`, which implement a fail-fast method,
              but like `RSVP.allSettled`, `hashSettled` waits until all the
              constituent promises have returned and then shows you all the results
              with their states and values/reasons. This is useful if you want to
              handle multiple promises' failure states together as a set.

              Returns a promise that is fulfilled when all the given promises have been
              settled, or rejected if the passed parameters are invalid.

              The returned promise is fulfilled with a hash that has the same key names as
              the `promises` object argument. If any of the values in the object are not
              promises, they will be copied over to the fulfilled object and marked with state
              'fulfilled'.

              Example:

              ```javascript
              var promises = {
                myPromise: RSVP.Promise.resolve(1),
                yourPromise: RSVP.Promise.resolve(2),
                theirPromise: RSVP.Promise.resolve(3),
                notAPromise: 4
              };

              RSVP.hashSettled(promises).then(function(hash){
                // hash here is an object that looks like:
                // {
                //   myPromise: { state: 'fulfilled', value: 1 },
                //   yourPromise: { state: 'fulfilled', value: 2 },
                //   theirPromise: { state: 'fulfilled', value: 3 },
                //   notAPromise: { state: 'fulfilled', value: 4 }
                // }
              });
              ```

              If any of the `promises` given to `RSVP.hash` are rejected, the state will
              be set to 'rejected' and the reason for rejection provided.

              Example:

              ```javascript
              var promises = {
                myPromise: RSVP.Promise.resolve(1),
                rejectedPromise: RSVP.Promise.reject(new Error('rejection')),
                anotherRejectedPromise: RSVP.Promise.reject(new Error('more rejection'))
              };

              RSVP.hashSettled(promises).then(function(hash){
                // hash here is an object that looks like:
                // {
                //   myPromise:              { state: 'fulfilled', value: 1 },
                //   rejectedPromise:        { state: 'rejected', reason: Error },
                //   anotherRejectedPromise: { state: 'rejected', reason: Error },
                // }
                // Note that for rejectedPromise, reason.message == 'rejection',
                // and for anotherRejectedPromise, reason.message == 'more rejection'.
              });
              ```

              An important note: `RSVP.hashSettled` is intended for plain JavaScript objects that
              are just a set of keys and values. `RSVP.hashSettled` will NOT preserve prototype
              chains.

              Example:

              ```javascript
              function MyConstructor(){
                this.example = RSVP.Promise.resolve('Example');
              }

              MyConstructor.prototype = {
                protoProperty: RSVP.Promise.resolve('Proto Property')
              };

              var myObject = new MyConstructor();

              RSVP.hashSettled(myObject).then(function(hash){
                // protoProperty will not be present, instead you will just have an
                // object that looks like:
                // {
                //   example: { state: 'fulfilled', value: 'Example' }
                // }
                //
                // hash.hasOwnProperty('protoProperty'); // false
                // 'undefined' === typeof hash.protoProperty
              });
              ```

              @method hashSettled
              @for RSVP
              @param {Object} promises
              @param {String} label optional string that describes the promise.
              Useful for tooling.
              @return {Promise} promise that is fulfilled when when all properties of `promises`
              have been settled.
              @static
            */
        __exports__['default'] = function hashSettled(object, label) {
            return new HashSettled(Promise, object, label).promise;
        };
    });
    define('rsvp/hash', [
    './promise',
    './promise-hash',
    './enumerator',
    'exports'
    ], function (__dependency1__, __dependency2__, __dependency3__, __exports__) {
        'use strict';
        var Promise = __dependency1__['default'];
        var PromiseHash = __dependency2__['default'];
        var ABORT_ON_REJECTION = __dependency3__.ABORT_ON_REJECTION;
        /**
              `RSVP.hash` is similar to `RSVP.all`, but takes an object instead of an array
              for its `promises` argument.

              Returns a promise that is fulfilled when all the given promises have been
              fulfilled, or rejected if any of them become rejected. The returned promise
              is fulfilled with a hash that has the same key names as the `promises` object
              argument. If any of the values in the object are not promises, they will
              simply be copied over to the fulfilled object.

              Example:

              ```javascript
              var promises = {
                myPromise: RSVP.resolve(1),
                yourPromise: RSVP.resolve(2),
                theirPromise: RSVP.resolve(3),
                notAPromise: 4
              };

              RSVP.hash(promises).then(function(hash){
                // hash here is an object that looks like:
                // {
                //   myPromise: 1,
                //   yourPromise: 2,
                //   theirPromise: 3,
                //   notAPromise: 4
                // }
              });
              ````

              If any of the `promises` given to `RSVP.hash` are rejected, the first promise
              that is rejected will be given as the reason to the rejection handler.

              Example:

              ```javascript
              var promises = {
                myPromise: RSVP.resolve(1),
                rejectedPromise: RSVP.reject(new Error("rejectedPromise")),
                anotherRejectedPromise: RSVP.reject(new Error("anotherRejectedPromise"))
              };

              RSVP.hash(promises).then(function(hash){
                // Code here never runs because there are rejected promises!
              }, function(reason) {
                // reason.message === "rejectedPromise"
              });
              ```

              An important note: `RSVP.hash` is intended for plain JavaScript objects that
              are just a set of keys and values. `RSVP.hash` will NOT preserve prototype
              chains.

              Example:

              ```javascript
              function MyConstructor(){
                this.example = RSVP.resolve("Example");
              }

              MyConstructor.prototype = {
                protoProperty: RSVP.resolve("Proto Property")
              };

              var myObject = new MyConstructor();

              RSVP.hash(myObject).then(function(hash){
                // protoProperty will not be present, instead you will just have an
                // object that looks like:
                // {
                //   example: "Example"
                // }
                //
                // hash.hasOwnProperty('protoProperty'); // false
                // 'undefined' === typeof hash.protoProperty
              });
              ```

              @method hash
              @static
              @for RSVP
              @param {Object} promises
              @param {String} label optional string that describes the promise.
              Useful for tooling.
              @return {Promise} promise that is fulfilled when all properties of `promises`
              have been fulfilled, or rejected if any of them become rejected.
            */
        __exports__['default'] = function hash(object, label) {
            return new PromiseHash(Promise, object, label).promise;
        };
    });
    define('rsvp/instrument', [
    './config',
    './utils',
    'exports'
    ], function (__dependency1__, __dependency2__, __exports__) {
        'use strict';
        var config = __dependency1__.config;
        var now = __dependency2__.now;
        var queue = [];
        __exports__['default'] = function instrument(eventName, promise, child) {
            if (1 === queue.push({
                name: eventName,
                payload: {
                    guid: promise._guidKey + promise._id,
                    eventName: eventName,
                    detail: promise._result,
                    childGuid: child && promise._guidKey + child._id,
                    label: promise._label,
                    timeStamp: now(),
                    stack: new Error(promise._label).stack
                }
            })) {
                setTimeout(function () {
                    var entry;
                    for (var i = 0; i < queue.length; i++) {
                        entry = queue[i];
                        config.trigger(entry.name, entry.payload);
                    }
                    queue.length = 0;
                }, 50);
            }
        };
    });
    define('rsvp/map', [
    './promise',
    './utils',
    'exports'
    ], function (__dependency1__, __dependency2__, __exports__) {
        'use strict';
        var Promise = __dependency1__['default'];
        var isArray = __dependency2__.isArray;
        var isFunction = __dependency2__.isFunction;
        /**
             `RSVP.map` is similar to JavaScript's native `map` method, except that it
              waits for all promises to become fulfilled before running the `mapFn` on
              each item in given to `promises`. `RSVP.map` returns a promise that will
              become fulfilled with the result of running `mapFn` on the values the promises
              become fulfilled with.

              For example:

              ```javascript

              var promise1 = RSVP.resolve(1);
              var promise2 = RSVP.resolve(2);
              var promise3 = RSVP.resolve(3);
              var promises = [ promise1, promise2, promise3 ];

              var mapFn = function(item){
                return item + 1;
              };

              RSVP.map(promises, mapFn).then(function(result){
                // result is [ 2, 3, 4 ]
              });
              ```

              If any of the `promises` given to `RSVP.map` are rejected, the first promise
              that is rejected will be given as an argument to the returned promise's
              rejection handler. For example:

              ```javascript
              var promise1 = RSVP.resolve(1);
              var promise2 = RSVP.reject(new Error("2"));
              var promise3 = RSVP.reject(new Error("3"));
              var promises = [ promise1, promise2, promise3 ];

              var mapFn = function(item){
                return item + 1;
              };

              RSVP.map(promises, mapFn).then(function(array){
                // Code here never runs because there are rejected promises!
              }, function(reason) {
                // reason.message === "2"
              });
              ```

              `RSVP.map` will also wait if a promise is returned from `mapFn`. For example,
              say you want to get all comments from a set of blog posts, but you need
              the blog posts first because they contain a url to those comments.

              ```javscript

              var mapFn = function(blogPost){
                // getComments does some ajax and returns an RSVP.Promise that is fulfilled
                // with some comments data
                return getComments(blogPost.comments_url);
              };

              // getBlogPosts does some ajax and returns an RSVP.Promise that is fulfilled
              // with some blog post data
              RSVP.map(getBlogPosts(), mapFn).then(function(comments){
                // comments is the result of asking the server for the comments
                // of all blog posts returned from getBlogPosts()
              });
              ```

              @method map
              @static
              @for RSVP
              @param {Array} promises
              @param {Function} mapFn function to be called on each fulfilled promise.
              @param {String} label optional string for labeling the promise.
              Useful for tooling.
              @return {Promise} promise that is fulfilled with the result of calling
              `mapFn` on each fulfilled promise or value when they become fulfilled.
               The promise will be rejected if any of the given `promises` become rejected.
              @static
            */
        __exports__['default'] = function map(promises, mapFn, label) {
            return Promise.all(promises, label).then(function (values) {
                if (!isFunction(mapFn)) {
                    throw new TypeError('You must pass a function as map\'s second argument.');
                }
                var length = values.length;
                var results = new Array(length);
                for (var i = 0; i < length; i++) {
                    results[i] = mapFn(values[i]);
                }
                return Promise.all(results, label);
            });
        };
    });
    define('rsvp/node', [
    './promise',
    './utils',
    'exports'
    ], function (__dependency1__, __dependency2__, __exports__) {
        'use strict';
        /* global  arraySlice */
        var Promise = __dependency1__['default'];
        var isArray = __dependency2__.isArray;
        /**
              `RSVP.denodeify` takes a "node-style" function and returns a function that
              will return an `RSVP.Promise`. You can use `denodeify` in Node.js or the
              browser when you'd prefer to use promises over using callbacks. For example,
              `denodeify` transforms the following:

              ```javascript
              var fs = require('fs');

              fs.readFile('myfile.txt', function(err, data){
                if (err) return handleError(err);
                handleData(data);
              });
              ```

              into:

              ```javascript
              var fs = require('fs');
              var readFile = RSVP.denodeify(fs.readFile);

              readFile('myfile.txt').then(handleData, handleError);
              ```

              If the node function has multiple success parameters, then `denodeify`
              just returns the first one:

              ```javascript
              var request = RSVP.denodeify(require('request'));

              request('http://example.com').then(function(res) {
                // ...
              });
              ```

              However, if you need all success parameters, setting `denodeify`'s
              second parameter to `true` causes it to return all success parameters
              as an array:

              ```javascript
              var request = RSVP.denodeify(require('request'), true);

              request('http://example.com').then(function(result) {
                // result[0] -> res
                // result[1] -> body
              });
              ```

              Or if you pass it an array with names it returns the parameters as a hash:

              ```javascript
              var request = RSVP.denodeify(require('request'), ['res', 'body']);

              request('http://example.com').then(function(result) {
                // result.res
                // result.body
              });
              ```

              Sometimes you need to retain the `this`:

              ```javascript
              var app = require('express')();
              var render = RSVP.denodeify(app.render.bind(app));
              ```

              The denodified function inherits from the original function. It works in all
              environments, except IE 10 and below. Consequently all properties of the original
              function are available to you. However, any properties you change on the
              denodeified function won't be changed on the original function. Example:

              ```javascript
              var request = RSVP.denodeify(require('request')),
                  cookieJar = request.jar(); // <- Inheritance is used here

              request('http://example.com', {jar: cookieJar}).then(function(res) {
                // cookieJar.cookies holds now the cookies returned by example.com
              });
              ```

              Using `denodeify` makes it easier to compose asynchronous operations instead
              of using callbacks. For example, instead of:

              ```javascript
              var fs = require('fs');

              fs.readFile('myfile.txt', function(err, data){
                if (err) { ... } // Handle error
                fs.writeFile('myfile2.txt', data, function(err){
                  if (err) { ... } // Handle error
                  console.log('done')
                });
              });
              ```

              you can chain the operations together using `then` from the returned promise:

              ```javascript
              var fs = require('fs');
              var readFile = RSVP.denodeify(fs.readFile);
              var writeFile = RSVP.denodeify(fs.writeFile);

              readFile('myfile.txt').then(function(data){
                return writeFile('myfile2.txt', data);
              }).then(function(){
                console.log('done')
              }).catch(function(error){
                // Handle error
              });
              ```

              @method denodeify
              @static
              @for RSVP
              @param {Function} nodeFunc a "node-style" function that takes a callback as
              its last argument. The callback expects an error to be passed as its first
              argument (if an error occurred, otherwise null), and the value from the
              operation as its second argument ("function(err, value){ }").
              @param {Boolean|Array} argumentNames An optional paramter that if set
              to `true` causes the promise to fulfill with the callback's success arguments
              as an array. This is useful if the node function has multiple success
              paramters. If you set this paramter to an array with names, the promise will
              fulfill with a hash with these names as keys and the success parameters as
              values.
              @return {Function} a function that wraps `nodeFunc` to return an
              `RSVP.Promise`
              @static
            */
        __exports__['default'] = function denodeify(nodeFunc, argumentNames) {
            var asArray = argumentNames === true;
            var asHash = isArray(argumentNames);
            function denodeifiedFunction() {
                var length = arguments.length;
                var nodeArgs = new Array(length);
                for (var i = 0; i < length; i++) {
                    nodeArgs[i] = arguments[i];
                }
                var thisArg;
                if (!asArray && !asHash && argumentNames) {
                    if (typeof console === 'object') {
                        console.warn('Deprecation: RSVP.denodeify() doesn\'t allow setting the ' + '"this" binding anymore. Use yourFunction.bind(yourThis) instead.');
                    }
                    thisArg = argumentNames;
                } else {
                    thisArg = this;
                }
                return Promise.all(nodeArgs).then(function (nodeArgs$2) {
                    return new Promise(resolver);
                    // sweet.js has a bug, this resolver can't be defined in the constructor
                    // or the arraySlice macro doesn't work
                    function resolver(resolve, reject) {
                        function callback() {
                            var length$2 = arguments.length;
                            var args = new Array(length$2);
                            for (var i$2 = 0; i$2 < length$2; i$2++) {
                                args[i$2] = arguments[i$2];
                            }
                            var error = args[0];
                            var value = args[1];
                            if (error) {
                                reject(error);
                            } else if (asArray) {
                                resolve(args.slice(1));
                            } else if (asHash) {
                                var obj = {};
                                var successArguments = args.slice(1);
                                var name;
                                var i$3;
                                for (i$3 = 0; i$3 < argumentNames.length; i$3++) {
                                    name = argumentNames[i$3];
                                    obj[name] = successArguments[i$3];
                                }
                                resolve(obj);
                            } else {
                                resolve(value);
                            }
                        }
                        nodeArgs$2.push(callback);
                        nodeFunc.apply(thisArg, nodeArgs$2);
                    }
                });
            }
            denodeifiedFunction.__proto__ = nodeFunc;
            return denodeifiedFunction;
        };
    });
    define('rsvp/promise-hash', [
    './enumerator',
    './-internal',
    './utils',
    'exports'
    ], function (__dependency1__, __dependency2__, __dependency3__, __exports__) {
        'use strict';
        var Enumerator = __dependency1__['default'];
        var PENDING = __dependency2__.PENDING;
        var FULFILLED = __dependency2__.FULFILLED;
        var o_create = __dependency3__.o_create;
        function PromiseHash(Constructor, object, label) {
            this._superConstructor(Constructor, object, true, label);
        }
        __exports__['default'] = PromiseHash;
        PromiseHash.prototype = o_create(Enumerator.prototype);
        PromiseHash.prototype._superConstructor = Enumerator;
        PromiseHash.prototype._init = function () {
            this._result = {};
        };
        PromiseHash.prototype._validateInput = function (input) {
            return input && typeof input === 'object';
        };
        PromiseHash.prototype._validationError = function () {
            return new Error('Promise.hash must be called with an object');
        };
        PromiseHash.prototype._enumerate = function () {
            var promise = this.promise;
            var input = this._input;
            var results = [];
            for (var key in input) {
                if (promise._state === PENDING && input.hasOwnProperty(key)) {
                    results.push({
                        position: key,
                        entry: input[key]
                    });
                }
            }
            var length = results.length;
            this._remaining = length;
            var result;
            for (var i = 0; promise._state === PENDING && i < length; i++) {
                result = results[i];
                this._eachEntry(result.entry, result.position);
            }
        };
    });
    define('rsvp/promise', [
    './config',
    './events',
    './instrument',
    './utils',
    './-internal',
    './promise/cast',
    './promise/all',
    './promise/race',
    './promise/resolve',
    './promise/reject',
    'exports'
    ], function (__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __exports__) {
        'use strict';
        var config = __dependency1__.config;
        var EventTarget = __dependency2__['default'];
        var instrument = __dependency3__['default'];
        var objectOrFunction = __dependency4__.objectOrFunction;
        var isFunction = __dependency4__.isFunction;
        var now = __dependency4__.now;
        var noop = __dependency5__.noop;
        var resolve = __dependency5__.resolve;
        var reject = __dependency5__.reject;
        var fulfill = __dependency5__.fulfill;
        var subscribe = __dependency5__.subscribe;
        var initializePromise = __dependency5__.initializePromise;
        var invokeCallback = __dependency5__.invokeCallback;
        var FULFILLED = __dependency5__.FULFILLED;
        var cast = __dependency6__['default'];
        var all = __dependency7__['default'];
        var race = __dependency8__['default'];
        var Resolve = __dependency9__['default'];
        var Reject = __dependency10__['default'];
        var guidKey = 'rsvp_' + now() + '-';
        var counter = 0;
        function needsResolver() {
            throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
        }
        function needsNew() {
            throw new TypeError('Failed to construct \'Promise\': Please use the \'new\' operator, this object constructor cannot be called as a function.');
        }
        __exports__['default'] = Promise;
        /**
              Promise objects represent the eventual result of an asynchronous operation. The
              primary way of interacting with a promise is through its `then` method, which
              registers callbacks to receive either a promise’s eventual value or the reason
              why the promise cannot be fulfilled.

              Terminology
              -----------

              - `promise` is an object or function with a `then` method whose behavior conforms to this specification.
              - `thenable` is an object or function that defines a `then` method.
              - `value` is any legal JavaScript value (including undefined, a thenable, or a promise).
              - `exception` is a value that is thrown using the throw statement.
              - `reason` is a value that indicates why a promise was rejected.
              - `settled` the final resting state of a promise, fulfilled or rejected.

              A promise can be in one of three states: pending, fulfilled, or rejected.

              Promises that are fulfilled have a fulfillment value and are in the fulfilled
              state.  Promises that are rejected have a rejection reason and are in the
              rejected state.  A fulfillment value is never a thenable.

              Promises can also be said to *resolve* a value.  If this value is also a
              promise, then the original promise's settled state will match the value's
              settled state.  So a promise that *resolves* a promise that rejects will
              itself reject, and a promise that *resolves* a promise that fulfills will
              itself fulfill.


              Basic Usage:
              ------------

              ```js
              var promise = new Promise(function(resolve, reject) {
                // on success
                resolve(value);

                // on failure
                reject(reason);
              });

              promise.then(function(value) {
                // on fulfillment
              }, function(reason) {
                // on rejection
              });
              ```

              Advanced Usage:
              ---------------

              Promises shine when abstracting away asynchronous interactions such as
              `XMLHttpRequest`s.

              ```js
              function getJSON(url) {
                return new Promise(function(resolve, reject){
                  var xhr = new XMLHttpRequest();

                  xhr.open('GET', url);
                  xhr.onreadystatechange = handler;
                  xhr.responseType = 'json';
                  xhr.setRequestHeader('Accept', 'application/json');
                  xhr.send();

                  function handler() {
                    if (this.readyState === this.DONE) {
                      if (this.status === 200) {
                        resolve(this.response);
                      } else {
                        reject(new Error("getJSON: `" + url + "` failed with status: [" + this.status + "]"));
                      }
                    }
                  };
                });
              }

              getJSON('/posts.json').then(function(json) {
                // on fulfillment
              }, function(reason) {
                // on rejection
              });
              ```

              Unlike callbacks, promises are great composable primitives.

              ```js
              Promise.all([
                getJSON('/posts'),
                getJSON('/comments')
              ]).then(function(values){
                values[0] // => postsJSON
                values[1] // => commentsJSON

                return values;
              });
              ```

              @class RSVP.Promise
              @param {function} resolver
              @param {String} label optional string for labeling the promise.
              Useful for tooling.
              @constructor
            */
        function Promise(resolver, label) {
            this._id = counter++;
            this._label = label;
            this._subscribers = [];
            if (config.instrument) {
                instrument('created', this);
            }
            if (noop !== resolver) {
                if (!isFunction(resolver)) {
                    needsResolver();
                }
                if (!(this instanceof Promise)) {
                    needsNew();
                }
                initializePromise(this, resolver);
            }
        }
        Promise.cast = cast;
        Promise.all = all;
        Promise.race = race;
        Promise.resolve = Resolve;
        Promise.reject = Reject;
        Promise.prototype = {
            constructor: Promise,
            _id: undefined,
            _guidKey: guidKey,
            _label: undefined,
            _state: undefined,
            _result: undefined,
            _subscribers: undefined,
            _onerror: function (reason) {
                config.trigger('error', reason);
            },
            then: function (onFulfillment, onRejection, label) {
                var parent = this;
                parent._onerror = null;
                var child = new this.constructor(noop, label);
                var state = parent._state;
                var result = parent._result;
                if (config.instrument) {
                    instrument('chained', parent, child);
                }
                if (state === FULFILLED && onFulfillment) {
                    config.async(function () {
                        invokeCallback(state, child, onFulfillment, result);
                    });
                } else {
                    subscribe(parent, child, onFulfillment, onRejection);
                }
                return child;
            },
            'catch': function (onRejection, label) {
                return this.then(null, onRejection, label);
            },
            'finally': function (callback, label) {
                var constructor = this.constructor;
                return this.then(function (value) {
                    return constructor.resolve(callback()).then(function () {
                        return value;
                    });
                }, function (reason) {
                    return constructor.resolve(callback()).then(function () {
                        throw reason;
                    });
                }, label);
            }
        };
    });
    define('rsvp/promise/all', [
    '../enumerator',
    'exports'
    ], function (__dependency1__, __exports__) {
        'use strict';
        var Enumerator = __dependency1__['default'];
        /**
              `RSVP.Promise.all` accepts an array of promises, and returns a new promise which
              is fulfilled with an array of fulfillment values for the passed promises, or
              rejected with the reason of the first passed promise to be rejected. It casts all
              elements of the passed iterable to promises as it runs this algorithm.

              Example:

              ```javascript
              var promise1 = RSVP.resolve(1);
              var promise2 = RSVP.resolve(2);
              var promise3 = RSVP.resolve(3);
              var promises = [ promise1, promise2, promise3 ];

              RSVP.Promise.all(promises).then(function(array){
                // The array here would be [ 1, 2, 3 ];
              });
              ```

              If any of the `promises` given to `RSVP.all` are rejected, the first promise
              that is rejected will be given as an argument to the returned promises's
              rejection handler. For example:

              Example:

              ```javascript
              var promise1 = RSVP.resolve(1);
              var promise2 = RSVP.reject(new Error("2"));
              var promise3 = RSVP.reject(new Error("3"));
              var promises = [ promise1, promise2, promise3 ];

              RSVP.Promise.all(promises).then(function(array){
                // Code here never runs because there are rejected promises!
              }, function(error) {
                // error.message === "2"
              });
              ```

              @method all
              @static
              @param {Array} entries array of promises
              @param {String} label optional string for labeling the promise.
              Useful for tooling.
              @return {Promise} promise that is fulfilled when all `promises` have been
              fulfilled, or rejected if any of them become rejected.
              @static
            */
        __exports__['default'] = function all(entries, label) {
            return new Enumerator(this, entries, true, label).promise;
        };
    });
    define('rsvp/promise/cast', [
    './resolve',
    'exports'
    ], function (__dependency1__, __exports__) {
        'use strict';
        var resolve = __dependency1__['default'];
        /**
              @deprecated

              `RSVP.Promise.cast` coerces its argument to a promise, or returns the
              argument if it is already a promise which shares a constructor with the caster.

              Example:

              ```javascript
              var promise = RSVP.Promise.resolve(1);
              var casted = RSVP.Promise.cast(promise);

              console.log(promise === casted); // true
              ```

              In the case of a promise whose constructor does not match, it is assimilated.
              The resulting promise will fulfill or reject based on the outcome of the
              promise being casted.

              Example:

              ```javascript
              var thennable = $.getJSON('/api/foo');
              var casted = RSVP.Promise.cast(thennable);

              console.log(thennable === casted); // false
              console.log(casted instanceof RSVP.Promise) // true

              casted.then(function(data) {
                // data is the value getJSON fulfills with
              });
              ```

              In the case of a non-promise, a promise which will fulfill with that value is
              returned.

              Example:

              ```javascript
              var value = 1; // could be a number, boolean, string, undefined...
              var casted = RSVP.Promise.cast(value);

              console.log(value === casted); // false
              console.log(casted instanceof RSVP.Promise) // true

              casted.then(function(val) {
                val === value // => true
              });
              ```

              `RSVP.Promise.cast` is similar to `RSVP.Promise.resolve`, but `RSVP.Promise.cast` differs in the
              following ways:

              * `RSVP.Promise.cast` serves as a memory-efficient way of getting a promise, when you
              have something that could either be a promise or a value. RSVP.resolve
              will have the same effect but will create a new promise wrapper if the
              argument is a promise.
              * `RSVP.Promise.cast` is a way of casting incoming thenables or promise subclasses to
              promises of the exact class specified, so that the resulting object's `then` is
              ensured to have the behavior of the constructor you are calling cast on (i.e., RSVP.Promise).

              @method cast
              @static
              @param {Object} object to be casted
              @param {String} label optional string for labeling the promise.
              Useful for tooling.
              @return {Promise} promise
            */
        __exports__['default'] = resolve;
    });
    define('rsvp/promise/race', [
    '../utils',
    '../-internal',
    'exports'
    ], function (__dependency1__, __dependency2__, __exports__) {
        'use strict';
        var isArray = __dependency1__.isArray;
        var isFunction = __dependency1__.isFunction;
        var isMaybeThenable = __dependency1__.isMaybeThenable;
        var noop = __dependency2__.noop;
        var resolve = __dependency2__.resolve;
        var reject = __dependency2__.reject;
        var subscribe = __dependency2__.subscribe;
        var PENDING = __dependency2__.PENDING;
        /**
              `RSVP.Promise.race` returns a new promise which is settled in the same way as the
              first passed promise to settle.

              Example:

              ```javascript
              var promise1 = new RSVP.Promise(function(resolve, reject){
                setTimeout(function(){
                  resolve("promise 1");
                }, 200);
              });

              var promise2 = new RSVP.Promise(function(resolve, reject){
                setTimeout(function(){
                  resolve("promise 2");
                }, 100);
              });

              RSVP.Promise.race([promise1, promise2]).then(function(result){
                // result === "promise 2" because it was resolved before promise1
                // was resolved.
              });
              ```

              `RSVP.Promise.race` is deterministic in that only the state of the first
              settled promise matters. For example, even if other promises given to the
              `promises` array argument are resolved, but the first settled promise has
              become rejected before the other promises became fulfilled, the returned
              promise will become rejected:

              ```javascript
              var promise1 = new RSVP.Promise(function(resolve, reject){
                setTimeout(function(){
                  resolve("promise 1");
                }, 200);
              });

              var promise2 = new RSVP.Promise(function(resolve, reject){
                setTimeout(function(){
                  reject(new Error("promise 2"));
                }, 100);
              });

              RSVP.Promise.race([promise1, promise2]).then(function(result){
                // Code here never runs
              }, function(reason){
                // reason.message === "promise 2" because promise 2 became rejected before
                // promise 1 became fulfilled
              });
              ```

              An example real-world use case is implementing timeouts:

              ```javascript
              RSVP.Promise.race([ajax('foo.json'), timeout(5000)])
              ```

              @method race
              @static
              @param {Array} promises array of promises to observe
              @param {String} label optional string for describing the promise returned.
              Useful for tooling.
              @return {Promise} a promise which settles in the same way as the first passed
              promise to settle.
            */
        __exports__['default'] = function race(entries, label) {
            /*jshint validthis:true */
            var Constructor = this, entry;
            var promise = new Constructor(noop, label);
            if (!isArray(entries)) {
                reject(promise, new TypeError('You must pass an array to race.'));
                return promise;
            }
            var length = entries.length;
            function onFulfillment(value) {
                resolve(promise, value);
            }
            function onRejection(reason) {
                reject(promise, reason);
            }
            for (var i = 0; promise._state === PENDING && i < length; i++) {
                subscribe(Constructor.resolve(entries[i]), undefined, onFulfillment, onRejection);
            }
            return promise;
        };
    });
    define('rsvp/promise/reject', [
    '../-internal',
    'exports'
    ], function (__dependency1__, __exports__) {
        'use strict';
        var noop = __dependency1__.noop;
        var _reject = __dependency1__.reject;
        /**
              `RSVP.Promise.reject` returns a promise rejected with the passed `reason`.
              It is shorthand for the following:

              ```javascript
              var promise = new RSVP.Promise(function(resolve, reject){
                reject(new Error('WHOOPS'));
              });

              promise.then(function(value){
                // Code here doesn't run because the promise is rejected!
              }, function(reason){
                // reason.message === 'WHOOPS'
              });
              ```

              Instead of writing the above, your code now simply becomes the following:

              ```javascript
              var promise = RSVP.Promise.reject(new Error('WHOOPS'));

              promise.then(function(value){
                // Code here doesn't run because the promise is rejected!
              }, function(reason){
                // reason.message === 'WHOOPS'
              });
              ```

              @method reject
              @static
              @param {Any} reason value that the returned promise will be rejected with.
              @param {String} label optional string for identifying the returned promise.
              Useful for tooling.
              @return {Promise} a promise rejected with the given `reason`.
            */
        __exports__['default'] = function reject(reason, label) {
            /*jshint validthis:true */
            var Constructor = this;
            var promise = new Constructor(noop, label);
            _reject(promise, reason);
            return promise;
        };
    });
    define('rsvp/promise/resolve', [
    '../-internal',
    'exports'
    ], function (__dependency1__, __exports__) {
        'use strict';
        var noop = __dependency1__.noop;
        var _resolve = __dependency1__.resolve;
        /**
              `RSVP.Promise.resolve` returns a promise that will become resolved with the
              passed `value`. It is shorthand for the following:

              ```javascript
              var promise = new RSVP.Promise(function(resolve, reject){
                resolve(1);
              });

              promise.then(function(value){
                // value === 1
              });
              ```

              Instead of writing the above, your code now simply becomes the following:

              ```javascript
              var promise = RSVP.Promise.resolve(1);

              promise.then(function(value){
                // value === 1
              });
              ```

              @method resolve
              @static
              @param {Any} value value that the returned promise will be resolved with
              @param {String} label optional string for identifying the returned promise.
              Useful for tooling.
              @return {Promise} a promise that will become fulfilled with the given
              `value`
            */
        __exports__['default'] = function resolve(object, label) {
            /*jshint validthis:true */
            var Constructor = this;
            if (object && typeof object === 'object' && object.constructor === Constructor) {
                return object;
            }
            var promise = new Constructor(noop, label);
            _resolve(promise, object);
            return promise;
        };
    });
    define('rsvp/race', [
    './promise',
    'exports'
    ], function (__dependency1__, __exports__) {
        'use strict';
        var Promise = __dependency1__['default'];
        /**
              This is a convenient alias for `RSVP.Promise.race`.

              @method race
              @static
              @for RSVP
              @param {Array} array Array of promises.
              @param {String} label An optional label. This is useful
              for tooling.
             */
        __exports__['default'] = function race(array, label) {
            return Promise.race(array, label);
        };
    });
    define('rsvp/reject', [
    './promise',
    'exports'
    ], function (__dependency1__, __exports__) {
        'use strict';
        var Promise = __dependency1__['default'];
        /**
              This is a convenient alias for `RSVP.Promise.reject`.

              @method reject
              @static
              @for RSVP
              @param {Any} reason value that the returned promise will be rejected with.
              @param {String} label optional string for identifying the returned promise.
              Useful for tooling.
              @return {Promise} a promise rejected with the given `reason`.
            */
        __exports__['default'] = function reject(reason, label) {
            return Promise.reject(reason, label);
        };
    });
    define('rsvp/resolve', [
    './promise',
    'exports'
    ], function (__dependency1__, __exports__) {
        'use strict';
        var Promise = __dependency1__['default'];
        /**
              This is a convenient alias for `RSVP.Promise.resolve`.

              @method resolve
              @static
              @for RSVP
              @param {Any} value value that the returned promise will be resolved with
              @param {String} label optional string for identifying the returned promise.
              Useful for tooling.
              @return {Promise} a promise that will become fulfilled with the given
              `value`
            */
        __exports__['default'] = function resolve(value, label) {
            return Promise.resolve(value, label);
        };
    });
    define('rsvp/rethrow', ['exports'], function (__exports__) {
        'use strict';
        /**
              `RSVP.rethrow` will rethrow an error on the next turn of the JavaScript event
              loop in order to aid debugging.

              Promises A+ specifies that any exceptions that occur with a promise must be
              caught by the promises implementation and bubbled to the last handler. For
              this reason, it is recommended that you always specify a second rejection
              handler function to `then`. However, `RSVP.rethrow` will throw the exception
              outside of the promise, so it bubbles up to your console if in the browser,
              or domain/cause uncaught exception in Node. `rethrow` will also throw the
              error again so the error can be handled by the promise per the spec.

              ```javascript
              function throws(){
                throw new Error('Whoops!');
              }

              var promise = new RSVP.Promise(function(resolve, reject){
                throws();
              });

              promise.catch(RSVP.rethrow).then(function(){
                // Code here doesn't run because the promise became rejected due to an
                // error!
              }, function (err){
                // handle the error here
              });
              ```

              The 'Whoops' error will be thrown on the next turn of the event loop
              and you can watch for it in your console. You can also handle it using a
              rejection handler given to `.then` or `.catch` on the returned promise.

              @method rethrow
              @static
              @for RSVP
              @param {Error} reason reason the promise became rejected.
              @throws Error
              @static
            */
        __exports__['default'] = function rethrow(reason) {
            setTimeout(function () {
                throw reason;
            });
            throw reason;
        };
    });
    define('rsvp/utils', ['exports'], function (__exports__) {
        'use strict';
        function objectOrFunction(x) {
            return typeof x === 'function' || typeof x === 'object' && x !== null;
        }
        __exports__.objectOrFunction = objectOrFunction;
        function isFunction(x) {
            return typeof x === 'function';
        }
        __exports__.isFunction = isFunction;
        function isMaybeThenable(x) {
            return typeof x === 'object' && x !== null;
        }
        __exports__.isMaybeThenable = isMaybeThenable;
        var _isArray;
        if (!Array.isArray) {
            _isArray = function (x) {
                return Object.prototype.toString.call(x) === '[object Array]';
            };
        } else {
            _isArray = Array.isArray;
        }
        var isArray = _isArray;
        __exports__.isArray = isArray;
        // Date.now is not available in browsers < IE9
        // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now#Compatibility
        var now = Date.now || function () {
            return new Date().getTime();
        };
        __exports__.now = now;
        var o_create = Object.create || function (object) {
            var o = function () {};
            o.prototype = object;
            return o;
        };
        __exports__.o_create = o_create;
    });
    define('rsvp', [
    './rsvp/promise',
    './rsvp/events',
    './rsvp/node',
    './rsvp/all',
    './rsvp/all-settled',
    './rsvp/race',
    './rsvp/hash',
    './rsvp/hash-settled',
    './rsvp/rethrow',
    './rsvp/defer',
    './rsvp/config',
    './rsvp/map',
    './rsvp/resolve',
    './rsvp/reject',
    './rsvp/filter',
    './rsvp/asap',
    'exports'
    ], function (__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __exports__) {
        'use strict';
        var Promise = __dependency1__['default'];
        var EventTarget = __dependency2__['default'];
        var denodeify = __dependency3__['default'];
        var all = __dependency4__['default'];
        var allSettled = __dependency5__['default'];
        var race = __dependency6__['default'];
        var hash = __dependency7__['default'];
        var hashSettled = __dependency8__['default'];
        var rethrow = __dependency9__['default'];
        var defer = __dependency10__['default'];
        var config = __dependency11__.config;
        var configure = __dependency11__.configure;
        var map = __dependency12__['default'];
        var resolve = __dependency13__['default'];
        var reject = __dependency14__['default'];
        var filter = __dependency15__['default'];
        var asap = __dependency16__['default'];
        config.async = asap;
        // default async is asap;
        function async(callback, arg) {
            config.async(callback, arg);
        }
        function on() {
            config.on.apply(config, arguments);
        }
        function off() {
            config.off.apply(config, arguments);
        }
        // Set up instrumentation through `window.__PROMISE_INTRUMENTATION__`
        if (typeof window !== 'undefined' && typeof window.__PROMISE_INSTRUMENTATION__ === 'object') {
            var callbacks = window.__PROMISE_INSTRUMENTATION__;
            configure('instrument', true);
            for (var eventName in callbacks) {
                if (callbacks.hasOwnProperty(eventName)) {
                    on(eventName, callbacks[eventName]);
                }
            }
        }
        __exports__.Promise = Promise;
        __exports__.EventTarget = EventTarget;
        __exports__.all = all;
        __exports__.allSettled = allSettled;
        __exports__.race = race;
        __exports__.hash = hash;
        __exports__.hashSettled = hashSettled;
        __exports__.rethrow = rethrow;
        __exports__.defer = defer;
        __exports__.denodeify = denodeify;
        __exports__.configure = configure;
        __exports__.on = on;
        __exports__.off = off;
        __exports__.resolve = resolve;
        __exports__.reject = reject;
        __exports__.async = async;
        __exports__.map = map;
        __exports__.filter = filter;
    });

    requireModule("ember");

})();
